Fippiyのプログラム学習内容アウトプットBlog

日々の学習内容をアウトプットして振り返りを実施する。

VBAプログラム開発、スクレイピング・ログイン機能【2-2】ログイン処理を作成する

ログイン機能の作成手順検討が終了したので、実際にVBAコードを作成して意図した通りの処理が行えることを確認していきます。 

今回の目的

VBA操作によるWebログインが行えるようにする

なぜやるか

ログイン状況を確認し、未ログイン時には自動的にログイン処理を実施し、その後の処理を続けて実施することで、一度の処理で全てを完結できるようにするため

やりたいこと

  • VBAによるWeb操作でログインフォームにアクセスして、ログイン情報を入力しログインを完了させる

やったこと

  • Web表示URLを確認する
  • ログイン画面で必要項目を入力してログインする
  • ログインできていることを確認する

実施内容

ログイン処理を作成する 

URLを確認する

書籍情報削除のVBA作成時にURLを確認する手法を使用していました。

ログインページのURLであるか判定ができれば、ログインページの時だけログイン処理をしてやればログインできます。

以前作成したURL取得内容の振り返りもあるので、URL取得部分のみで動作確認するコードを作成しました。

# ログイン処理確認コード

Sub getURLtest()
 'オブジェクト設定
 Dim objIE As InternetExplorer
 Set objIE = CreateObject("Internetexplorer.Application")
 objIE.Visible = True
 Dim htmlDoc As HTMLDocument
 'URL設定
 Dim Domain As String 'Web操作ドメイン
 Dim OpenPage As String '操作URL
 Domain = "https://protected-fortress-61913.herokuapp.com/"

 'URLを開いてオブジェクト取得
 OpenPage = Domain '開くURLを設定
 objIE.navigate OpenPage 'IEでURLを開く
 Call WaitResponse(objIE) '読み込み待ち
 Debug.Print objIE.document.URL 'URL取得

End Sub

 

Sub WaitResponse(objIE As Object)
 Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE
  DoEvents
 Loop
End Sub

主に2つのプロシージャで構成されています。

  1. getURLtest:URL表示確認用
  2. WaitResponse:ブラウザ読み込み状況確認

2は今までのVBA作成の過程で作成した物を流用しています。

 

動作内容としては、指定のURLへアクセスして、ブラウザロード完了後にURLを取得しています。

この状態で動作確認します。まずはトップページにアクセスしてみました。

f:id:Fippiy:20190630140109j:plain

デバッグ

トップページURLが取得できました。

 

同様に、ログインページとログイン後の書籍一覧ページをについても確認します。

# ログイン処理確認コード

'1.トップページ
OpenPage = Domain '開くURLを設定
objIE.navigate OpenPage 'IEでURLを開く
Call WaitResponse(objIE) '読み込み待ち
Debug.Print objIE.document.URL 'URL取得


'2.ログインURL
OpenPage = Domain & "login" '開くURLを設定
objIE.navigate OpenPage 'IEでURLを開く
Call WaitResponse(objIE) '読み込み待ち
Debug.Print objIE.document.URL 'URL取得

 

'3.書籍一覧URL

OpenPage = Domain & "book" '開くURLを設定
objIE.navigate OpenPage 'IEでURLを開く
Call WaitResponse(objIE) '読み込み待ち
Debug.Print objIE.document.URL 'URL取得

  1. トップページ
  2. ログインページ
  3. 書籍一覧ページ

これらのページへアクセスしてURLを取得しました。トップページは先程作成した内容と全く同じです。

※本来繰り返し処理で書くべき所ですが、URLの確認するだけなので、そのままコピーしてURLだけ書き換えています。

この状態でURL取得確認してみると…

f:id:Fippiy:20190630140628j:plain

デバッグ

2と3は同じ結果になりました。

現時点ではまだログインする前なので、書籍一覧ページにアクセスしてもログインできていない為、ログインページが返されていることが分かります。

 

同じ条件でログインした状態でもう一度ためします。

f:id:Fippiy:20190630140917j:plain

デバッグ

ログイン状態でためした結果、想定通りにURLが取得できました。ログイン済みであれば~/loginアクセス時に自動的にログイン後のページに移動するので、bookが取得できています。

URL取得方法と、ログイン状況に対しての返り値が確認できました。

後は今までに作成したVBAにこの処理を追加してやれば、状況に応じてログイン処理も実施してくれるようにできそうです。

 

ログイン処理を行う

URLが確認できたところで、実際にVBA動作でログイン操作を試します。

f:id:Fippiy:20190630142717j:plain

ログイン画面

ログインをするにはログイン画面でメールアドレスとパスワードを入力してログインボタンをクリックする必要があります。

この操作には以前作成したフォームに入力する動作とボタンを押す動作を作成してやれば実現できる…と考えています。

こちらも、実際にVBAコードを作成してログインできることを確認します。

 

まずは、入力フォームとボタンを指定できるように、クラス名を確認します。

# ログインフォームHTML

<form action="https://protected-fortress-61913.herokuapp.com/login" method="post">
 <div class="form-group">
  <div class="form-group__lavel">

   <lavel>メールアドレス</lavel>

  </div>
  <input name="email" class="form-group__input" type="text" value="">
 </div>
 <div class="form-group">
  <div class="form-group__lavel">

   <lavel>パスワード</lavel>

   <span class="form-group__pass">

    <a class="form-group__pass--color" href="~/password/reset">

      パスワードを忘れた場合

    </a>

   </span>

  </div>
  <input name="password" class="form-group__input" type="password">
 </div>
 <div class="form-group">
  <input class="form-group__submit" type="submit" value="ログイン">
 </div>
</form>

今まで主にクラス名を使ってHTML要素を指定していました。

しかし、今回は同じクラス名が登場するため、name属性も利用することにしました。

# ログインフォーム処理

'URLを開いてオブジェクト取得

OpenPage = Domain & "login" '開くURLを設定
objIE.navigate OpenPage 'IEでURLを開く
Call WaitResponse(objIE) '読み込み待ち
ResponseURL = objIE.document.URL '読み込み後のURL取得
Debug.Print ResponseURL 'デバッグ確認

'ログインURL設定
Dim LoginURL As String
LoginURL = Domain & "login"

'ログイン画面時はログイン処理
If ResponseURL = LoginURL Then
 Set htmlDoc = objIE.document 'objIEで読み込まれているHTMLドキュメントをセット
 'フォーム入力
 htmlDoc.getElementsByName("email")(0).Value = "test"
 htmlDoc.getElementsByName("password")(0).Value = "test"
 'htmlDoc.getElementsByClassName("form-group__submit")(0).Click
End If

If文を利用し、表示された画面のURLがログインページURLであるか確認を行い、フォームに入力を行うコードを追加しました。

f:id:Fippiy:20190630150708j:plain

フォーム入力

インプットエリア指定さえできれば、あとは入力してログインするだけです。この画面の確認の為にクリック処理はコメントアウトしていました。

 

ログイン後の確認を実装する

後は、ログインボタンクリック後にログインできていることを確認すればログイン処理自体は完成です。

確認せずにログイン後の処理ができるようにしても、ログインに失敗していると意図した動作にならないためです。

では、どうやってログインできていることを確認するか?

 

ここで、ログインに失敗したケースについての表示を確認します。

先程フォーム入力までは完成したので、ログインボタンクリックの動作まで実施します。

f:id:Fippiy:20190630151034j:plain

ログイン失敗

ボタンクリックまで動作することは確認できました。

しかし、メールアドレスではなく"test"という文字を試験的に表示させていただけの為、実際にはログインは失敗しています。

ログイン失敗時の上記画面は…ログイン画面が表示されたままです。ログイン失敗のメッセージが表示されています。

つまり、ログイン失敗時は同じURLのまま。ログイン成功時は他のページに移動しているという方法でログイン完了を確認することにしました。

 

ログインボタンクリック後にURLを確認する

ログインまでは出来ているので、ログイン後のURLをもう一度確認する処理を入れ、結果によってログイン後の処理を行うのか、ログイン失敗したことをユーザに通知して終了するかを作成すればよさそうです。

# ログイン処理(ログイン後URL判定追加)

'ログイン画面時はログイン処理
If ResponseURL = LoginURL Then
 Set htmlDoc = objIE.document 'objIEで読み込まれているHTMLドキュメントをセット
 'フォーム入力
 htmlDoc.getElementsByName("email")(0).Value = "test@test.com"
 htmlDoc.getElementsByName("password")(0).Value = "********"
 htmlDoc.getElementsByClassName("form-group__submit")(0).Click

 'ログイン結果確認
 Call WaitResponse(objIE) '読み込み待ち
 ResponseURL = objIE.document.URL '読み込み後のURL取得
 Debug.Print ResponseURL 'デバッグ確認
 If ResponseURL = LoginURL Then
  Debug.Print "ログイン失敗"
 Else
  Debug.Print "ログイン成功"
 End If
End If

ログインボタンクリック後のWebページ情報をResponseURL=objIE.document.URLとしてURLを取得します。

そしてこのURLがログインページURLと同じか確認します。

同じであれば、ログイン画面のままなのでログイン失敗の判定をします。URLが変わっていれば正常にログインできたとみなすことで判定させることにしました。

この状態で動作確認します。

ここでデバッグ情報としては

  1. ログインページURLであることの確認
  2. ログイン後のページURLを確認
  3. 判定結果

これらを出力させるようにしています。

 

まずは、失敗パターンから

f:id:Fippiy:20190630154202j:plain

デバッグ

ログイン失敗時はログインページのままなのでURLは同じです。そして、ログイン失敗というテキストが表示されています。

 

そして正常ログインできた場合も確認します。

f:id:Fippiy:20190630154426j:plain

デバッグ

ログインが完了すると、書籍一覧ページへ遷移するのでURLが変わっています。URLが変わっている=ログイン成功として処理できています。

 

これでログインページの判断とログイン処理、そしてログインができたかどうかの確認までができました。

後は、この処理を今までに作成したVBAコードを動作させる前に追加してやれば、ログイン確認をしてから各種処理まで行えるようになります。

仕組みができたので、次から組み込みできるようにしていきます。