見出し画像

Edge自動操作のためのHTML分析のポイント(後編)

後編ということで、「〇〇したい時はこう書く」的なTipsを残しておきます。

ここで紹介するのは小技的なTips集です。
単体ではあまり意味がないので、複数組み合わせて使ってください。
例えば、会員サイトへログインする操作ならば、「①ログインページへ移動→②ページ読み込み待機→③ログインフォームの部品特定→④ユーザーとパスワードの入力→⑤ログインフォームの送信」という5つの処理を組み合わせて実現可能です。
VBA実装の助けになれば幸いです。
※前回記事はこちら


ページ全般

既に開いているWebページに対して何らかの処理を加える方法まとめ。
前回記事でも説明しましたが、以下、対象WebページのDOMオブジェクトが生成されている前提とします。

●ページの移動

オブジェクト.Location = "任意のURL"

オブジェクトに続けて「.Location=" "」と書くことで、オブジェクトのLocationプロパティを変更できます。Locationプロパティが書き換わると、指定されたURLページへ画面が移動します。
※一昔前のInternetExplorer時代においては「Navigation」メソッドがページ
 移動の定番でしたが、ブラウザ切替(InternetExplore→Edge)に伴い、 
 DOMオブジェクトのデータ型が変わったので、もう使えなくなりました。

●ページの読み込み待ち

ページの読み込み待ちは、ブラウザ操作を自動化する上で必須テクニックです。読み込み未完了のまま処理を進めるとエラーが出ますし、読み込み時間は回線状況やサーバー混雑状況によって変わるので、状況に応じて待機する処理を加えた方が動作が安定します。
ということでページタイトルに着目してページ読み込み状況を判定する方法2つを紹介します。
※一昔前のInternetExplorer時代に定番だった「Busy」や「ReadyState」
 プロパティはもう使えなくなりました。

方法①

Dim Title As String
Title = "Webページのタイトル"
Do
 On Error Resume Next
 For Each Elem In オブジェクト.getElementsByTagName("head")
  If Elem.title = Title Then
   Exit Do
  End If
 Next
 On Error GoTo 0
 DoEvents
Loop
Debug.Print "ページ読み込み完了"

Webページのタイトル名の切替わり状況から、ページ読込みが完了したかどうかを判断する方法です。
Webページのタイトル名は通常ブラウザのタブ部から確認できますが、HTMLコードではヘッダー(<head>タグ内)の<title>タグに値が設定されています。
ページが読み込みまれていない内は<head>タグが見つからずエラーが出続けるので、処理が中断しないようOn Error Resume Nextで防止します。
DoEvents(またはSleep関数)による待機処理を挟んで、これをページ読み込みが完了するまでDo Loop文でひたすらループします。

方法②

Dim Title As String
Title = "Webページのタイトル"
Do
 DoEvents 'またはSleep関数による待機
Loop While InStr(GetWinText(hWnd), "Webページの") = 0
Debug.Print "ページ読み込み完了"

'-----------サブルーチン処理----------
Function GetWinText(hWndTarget As Variant) As String
 ’別記事で紹介。
End Sub
'-----------サブルーチン処理(おわり)----------

ウィンドウのキャプション名の切り替わり状況から、ページ読み込み状態を判断する方法です。
こちらはWin APIを使って、新しいWebページのウィンドウキャプション名が見つかるまで判定を繰り返すというアプローチです。
個人的にはこっちの方が安定しているかな、という印象。
実装するときはこちらのサブルーチン部分をコピペして下さい。

ただし方法①②どちらも、何かの拍子でページ読み込みが完了しないと、永遠に抜け出せない無限ループに嵌るので要注意。対策としては…

Dim TimeOutCnt As Long
TimeOutCnt = 0
Do
 '上記の「ページ読み込み待ち」の処理
 TimeOutCnt = TimeOutCnt + 1
 If TimeOutCnt5 Then
  Debug.Print ”タイムアウトしました。処理中断します。"
  End
 End If
 DoEvents "またはSleep関数による待機
Loop

このように、最大待ち時間(タイムアウト時間)を設定しておくことをお勧めします。
因みに、これら①②の処理完了後、更に100ミリ秒くらい待機処理を入れておくのが吉。ページ読み込みが完了しても、ブラウザがアイドル状態(操作受付状態)になるまで僅かにタイムラグが生じる場合があるので。

●ページコンテンツのロード待ち

Do
 On Error Resume Next
  For Each button In オブジェクト.getElementsByTagName("input")
   If button.Type = "submit" And button.Value = "確認" Then
     Exit Do
    End If
 Next
  On Error GoTo 0
 DoEvents 'またはSleep関数による待機
Loop
Debug.Print "ページコンテンツのロード完了"

指定する要素は何でも良いですが、新しいページ内の何かしらの要素が見つかるまで待機する方法です。
新しいページの要素が見つかった=ページコンテンツがロードされた、という考え方。
無限ループ回避のため、タイムアウト時間の設定もお忘れなく。

●指定時間だけ待機

Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr)
'-----------メイン処理-----------
Sub Sample()
 Sleep 1000
End Sub
'-----------メイン処理(おわり)-----------

または
Applicatoin.Wait (Now + TimeValue("00:00:01"))

Win APIのSleep関数を使うことで、任意の時間〇〇ミリ秒(1/1000秒)だけ処理を一時休止できます。
VBAのWaitメソッドでも同じことが出来ますが、後者は全体的にフリーズした印象になりがちで使い勝手が悪いです。
Win APIのSleep関数を使いましょう。
なお、「ページの読み込み待ち」や「コンテンツのロード待ち」で紹介したようにループ処理内で待機させる場合でも、DoEventsによる待機より、Win APIのSleep関数による待機の方がCUP負荷が少ないです。
積極的にSleep関数を使いましょう。

●新規ページを開く

参考までに、URLを指定して新規ページを開くコードも載せときます。
ただし以下①と②どちらも「単にページを開くだけ」なので、WebページのDOMオブジェクトは未生成である点に注意してください。もし続けてページ操作したい場合はDOMオブジェクトを生成してください。

方法①

Dim URL As String
URL = "任意のURL"
Shell "C:\Program FIles (x86)\Microsoft\Edge\Application\msedge.exe " & URL, vbNormalFocus

Shell関数で、ブラウザのプログラムファイルを指定して実行する方法。
第二引数で、起動したブラウザのフォーカス状態を指定します。

方法②

Dim URL As String
Dim ProcessName As String
Dim strCom As String
URL = "任意のURL”
ProcessName = "msedge.exe"
strCom = "cmd.exe /c start " & ProcessName & " " & URL
CreateObject("Wscript.shell").Run strCom, 0, True

コマンドプロンプトから、ブラウザのプロセス名を指定して実行する方法。Wscript.shellのrunメソッドでコマンドを実行します。第一引数にコマンド文を、第二引数にコマンドプロンプトの可視設定(0で非表示)を、第三引数に同期有無(Trueで同期処理)を指定。

●ページを閉じる

Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As LongPtr, ByVal wParam As LongPtr, lParam As LongPtr) As LongPtr
Const WM_CLOSE = &H10
'-----------メイン処理-----------
Sub Sample()
 Call SendMessage(hWnd, WM_CLOSE, 0, 0)
End Sub
'-----------メイン処理(おわり)-----------    

Win APIのSendMessage関数を使って、ウィンドウを閉じます。
第一引数に指定するウィンドウハンドルには、ブラウザの最上位ウィンドウを指定します。
ブラウザの最上位ウィンドウですが、これは例えば、Win APIのGetWindowText関数などを使って(キャプション名をキーワードに検索をかけて)取得可能です。

●ウィンドウを最前面に表示

Declare PtrSafe Function SetForegroundWindow Lib "user32" (ByVal hWnd As LongPtr) As LongPtr
'-----------メイン処理-----------
Sub Sample()
 Call SetForegroundWindow(hwnd)
End Sub
'-----------メイン処理(おわり)-----------

Win APIのSetForegroundWindow関数を使って、ウィンドウを最前面に表示します。引数に指定するウィンドウハンドルには、ブラウザ(Microsoft Edge)の最上位ウィンドウを指定します。

●新しいウィンドウで開いたページの読み込み待ち

Dim Title As String
Title = "Webページのタイトル"
Do
 Call Get_Internet_Explorer_Server_hWnd(Title)
Loop While hIES = 0
Debug.Print "ページ読み込み完了"

'-----------サブルーチン処理----------
Sub Get_Internet_Explorer_Server_hWnd(ByVal Title As String)
 ’別記事で紹介。
End Sub
'-----------サブルーチン処理(おわり)----------

新しいウィンドウで開いたWebページを操作する場合、改めてDOMオブジェクトの生成が必要になります。
DOMオブジェクトが生成したタイミング(上記例では変数IESにウィンドウハンドルが代入された時点)で、新しいウィンドウのページ読み込みが完了したと判断するアプローチ方法です。
実装するときはこちらのサブルーチン部分をコピペして下さい。


ログイン関係

ログインといえば大抵は、「ユーザー名・パスワードの入力」と「ログイン情報送信(ログインボタン押下)」の2操作になるでしょう。
ログイン関係の操作方法まとめ。

●ユーザー名の入力(テキストボックスへ文字入力)

オブジェクト.getElementsByName("textbox")(0).value = "ユーザー名"

または
オブジェクト.getElementById("mail_address").value = "ユーザー名"

または
オブジェクト.getElementsByTagName("input")(0).value = "ユーザー名"

または
オブジェクト.getElementsByName("mail_address")(0).value="ユーザー名"

または
オブジェクト.getElementsByClassName("mail_address")(0).value="ユーザー名"

テキストボックスを見つける方法は何通りかあります。状況に応じて最適解を見つけてください。代表的なのを5パターン書きました。
getElementByIdメソッドだけ戻り値が単数形、その他メソッドは全て戻り値が複数形(コレクション)なので続けてインデックス番号による指定が必要です。戻り値が複数形だったら、For Eachステートメントと組み合わせて特定しても良いでしょう。
テキストボックスを特定したら、そのvalueプロパティの値を変えることで文字入力が可能です。
なお同様に、そのinnerTextプロパティの値を変更でも文字入力可能です。
(もしvalueプロパティでの入力が上手くいかないときは、innertextプロパティの方も試してみて。)
パスワードの入力も同じ要領で文字入力できますね。

●ログインボタンの押下

方法①

'(ログイン情報を入力した状態で)

Dim form As Object 'HTMLFormElement
Set form = オブジェクト.forms("Login")
form.submit

ログインフォーム(ログイン情報の入力エリア)が<form>タグ内に全て入っている様なHTML構成であれば、<form>要素をサーバーへ送信する挙動を再現することでログインできます。(できないこともあります。)
この方法を使えるなら、後からVBAコードを見直したときに分かりやすいのでおすすめ。

方法②

'(ログイン情報を入力した状態で)

Dim button As Object 'HTMLButtonElement
For Each button In オブジェクト.getElementsByTagName("input")
 If button.Type = "submit" And button.Value = "次へ" Then
  button.Click
  Exit For
 End If
Next

getElementsByTagNameメソッドで要素のコレクションを取得し、その中から要素をひとつづつ取り出して、属性値を検証していくアプローチ方法。
ログイン情報を扱うときは、<input>タグや<form>タグがよく使われている印象です。
ログインボタンが見つかったら、Clickメソッドでマウスクリックを再現します。
ログインボタンを特定できたけどClickメソッドが効かない!って時は…

button.Focus
CreateObject("Wscript.Shell").SendKeys "{ENTER}"

で無理やり突破もできます。
「button.Focus」でログインボタンに焦点を当てたうえで、{Enter}キーを送り込むと、大抵はボタン押下を再現できます。


コンテンツ関係

ここからは、ページ内のコンテンツを操作する際の汎用的なテクニックをまとめます。

●ハイパーリンクのクリック

方法①

Dim anchor As Object 'HTMLAnchorElement
On Error Resume Next
For Each anchor In オブジェクト.getElementsByTagName("A")
 If anchor.innerText = "シングルサインオン" Then
  anchor.Click
 End If
Next
On Error GoTo 0
End If

リンクは、HTML内では<a>タグで表現されます。
<a>タグ要素のコレクションの中から、innerTextプロパティの値が一致するかどうかで、目的のリンクを特定するアプローチ方法です。
name属性やvalue属性など活用しやすい特徴が<a>タグの中にあれば良いのですが、中には属性がほとんど付いてない<a>タグを見かける事もあるでしょう。そんな時はinnerTextで判断するコレが使えます。
ただし、HTML内の全ての<a>タグにinnerTextが設定されているとは限らないので、On Error Resume Nextでエラー回避します。

方法②

Dim anchor As Object 'HTMLAnchorElement
On Error Resume Next
For Each anchor In オブジェクト.getElementsByTagName("A")
 If anchor.innerText = "表示" And InStr(anchor.href, "任意のキーワード") > 0 Then
  anchor.Focus
  CreateObject("Wscript.Shell").SendKeys "{ENTER}"
  Exit For
 End If
Next
On Error GoTo 0

これは方法①の派生形です。
一つのHTML内にinnerText="表示”の属性値を持つ<a>タグが複数あった場合、更に判定条件文「InStr(anchor.href, "任意のキーワード") > 0」を追加することでハイパーリンクを特定します。
InStr関数を使って、第二引数で指定したキーワードが第一引数(リンク先URL)に一部でも含まれていたら対象リンクだと判断するアプローチ方法です。

●プルダウンリストの選択

Dim OpSelect As Object 'HTMLSelectElement
Set OpSelect = オブジェクト.getElementById("material")
OpSelect.Value = "アルミ"

プルダウンリストを選択する動作を再現するには、Valueプロパティに値を指定すればOK。

●チェックボックスの入力

方法①

Dim OpInput As Object 'HTMLInputElement
Set OpInput = オブジェクト.getElementById("check1")
OpInput.Checked = True

チェックボックスは<input>タグのtype="checkbox"であることが殆どです。
checkedプロパティを参照して、値がTrueでチェック有、Falseでチェック無です。
例えば次のように条件指定すれば、確実にチェックを入れられます。
「If OpInput.Checked = False Then OpInput.Click」

方法②

オブジェクト.getElementsByName("rememberMe")(0).Click

これはログイン画面で出てくる「サインイン状態を維持する」のチェックボックスに✔を入れる動作を再現したもの。

●ラジオボタンの選択

方法①

Dim OpInput As Object 'HTMLInputElement
Set OpRadio = オブジェクト.getElementById("rad1")
OpRadio.Click

ラジオボタンは<input>タグのtype="radio"であることが殆どです。
複数の選択肢の中から一つだけを選ばせるようなシチュエーションでラジオボタンが採用されます。

方法②

Dim OpInput As Object 'HTMLInputElement
For Each OpRado In オブジェクト.getElementsByName("city")
 If OpRadio.Value = "tokyo" Then
  OpRadio.Click
  Exit For
 End If
Next

これは方法①の派生形です。
Name属性値が共通するラジオボタンを一括で取得し、その中から目的の一つを特定し、クリック動作を再現しています。

●フレーム内の要素を操作

「今どきフレームで分割されたWebページなんてあるの?」と思いきや、これが意外とあります。社内の業務システムって、存外古臭いです…。
ということでフレーム内の要素を操作する方法。

Dim html_frame As Object 'HTMLDocumnt
Set html_frame = オブジェクト.frames("list").Document
html_frame.getElementsByName("banngou")(0).Value = "123456789"
html_frame.getElementsByName("go")(0).Click

HTML内のフレームの中から、更にHTMLを取得するイメージです。
上記例では「オブジェクト.frames("list").Document」で、HTML内にあるname属性の値が"list”であるフレームを取り出してドキュメントプロパティを参照し、左辺へ代入しています。
こうすることで、フレーム内のHTML情報を取り出し、更に操作することが出来ます。

●テーブルの操作

表形式の<table>タグが使われている場合の操作方法です。
スクレイピング等の情報取得の例を紹介します。

Dim td As Object
Dim Data() As Strig
ReDim Data(4,3)
For Each td In オブジェクト.getElementsByTagName("table")
 On Error Resume Next
 If td.getElementsByTagName("td")(0).innerText = "通し番号" Then '目的のテーブルかどうかを判別
  Data(0,0) = td.getElementsByTagName("td")(0).innerText '通し番号(見出し)
  Data(1,0) = td.getElementsByTagName("td")(0).innerText '見積番号(見出し)
  Data(2,0) = td.getElementsByTagName("td")(0).innerText '仕掛担当(見出し)
  Data(3,0) = td.getElementsByTagName("td")(0).innerText 'ステータス(見出し)
  Data(0,1) = td.getElementsByTagName("td")(0).innerText '同様(データ1)
  Data(1,1) = td.getElementsByTagName("td")(0).innerText '同様(データ1)
  Data(2,1) = td.getElementsByTagName("td")(0).innerText ’同様(データ1)
  Data(3,1) = td.getElementsByTagName("td")(0).innerText '同様(データ1)
  Data(0,0) = td.getElementsByTagName("td")(0).innerText '同様(データ2)
  Data(1,1) = td.getElementsByTagName("td")(0).innerText '同様(データ2)
  Data(2,2) = td.getElementsByTagName("td")(0).innerText '同様(データ2)
  Data(3,3) = td.getElementsByTagName("td")(0).innerText '同様(データ2)
 End If
 On Error Goto 0
Next
Dim oSheet As Worksheet
Set oSheet = Sheets.Add(After:=Sheets(Sheets.Count))
oSheet.Range("A1").Resize(Uboud(Data,2), Ubound(Data)).Value = Application.WorksheetFunction.Transpose(Data)

1つのHTML内に複数の<table>タグが存在する想定です。目的のテーブルかどうかを判別するために、If文でテーブルの1要素目のinnerTextが任意の文字列(「通し番号」か否か)かをチェックします。違う場合はエラーが出るのでOn Error Resume Nextでエラー時の処理を継続。
目的のテーブルを見つけたら、あとは淡々と二次元配列に値を格納して情報取得(スクレイピング)するだけです。
上記例では、二次元配列を新規シートへ書き出しています。

キーストロークの再現

キーストロークの再現は、何かと使う頻度が高いです。
例えば、本来時間を掛けてJavaScriptを紐解く必要のある自動化処理でも、キーストロークを1発送信すれば、それだけで解決(関門突破)する状況も多くあります。労力対効果が高いということで、キー送信についてのまとめ。

●キー送信の方法

方法①

Application.Sendkeys "ABC123"
Application.Sendkeys "{ENTER}"
Application.Sendkeys "{TAB}{TAB}{TAB}"

ApplicationオブジェクトのSendKeysステートメントを使ったキー送信方法。
誤動作が多いのでこれは非推奨。
アクティブなウィンドウにのみ送信可能。

方法②

CreateObject("Wscript.Shell").SendKeys "ABC123"
CreateObject("Wscript.Shell").SendKeys "{ENTER}"
CreateObject("Wscript.Shell").SendKeys "{TAB}{TAB}{TAB}"

WshShellオブジェクトのSendKeysメソッドを使ったキー送信方法。
迷ったらコレ。
アクティブなウィンドウにのみ送信可能。

方法③

Declare PtrSafe Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Const VK_A = &H41
Const VK_RETURN = &HD
Const VK_TAB = &H9
Const KEYEVENTF_KEYUP = &H2
'-----------メイン処理-----------
Sub Sample()
  keybd_event VK_A, 0, 0, 0 'Aを押す
  keybd_event VK_A, 0, KEYEVENTF_KEYUP, 0 'Aを離す
 
 keybd_event VK_RETURN, 0, 0, 0 ’Enterを押す
 keybd_event VK_RETURN, 0, KEYEVENTF_KEYUP, 0 'Enterを離す

 keybd_event VK_TAB, 0, 0, 0 'tabを押す(第二引数&HFも試す)
 keybd_event VK_TAB, 0, KEYEVENTF_KEYUP, 0 'tabを離す(第二引数&H8Fも試す)
End Sub
'-----------メイン処理(おわり)-----------   

Win APIのkeybd_event関数を使って、1文字づつキー送信する方法。Windows内部で認識されるキーストロークを合成していく方法のため、キー押下時の再現率が高いです。
{Shift}+{Ctrl}+{a}などのキー同時押しも再現しやすいです。
アクティブなウィンドウにのみ送信可能。

方法④

Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As LongPtr, ByVal wMsg As LongPtr, ByVal wparam As LongPtr, ByVal lParam As LongPtr) As LongPtr
Declare PtrSafe Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As LongPtr, ByVal wMapType As LongPtr) As LongPtr
Const WM_CHAR = &H102
Const VK_R = &H52
'-----------メイン処理-----------
Sub Sample()
 Dim lParam As LongPtr
 lParam = 1 + MapVirtualKey(VK_R, 0) * (2 ^ 16)
  PostMessage hWnd, WM_CHAR, VK_R, lParam
End Sub
'-----------メイン処理(おわり)-----------  

Win APIのPostMessage関数を使って、指定したウィンドウハンドルに対して、1文字づつキー送信する方法。
非アクティブな(背面に隠れた)ウィンドウに対してもキー送信が可能。
Webページが新しいウィンドウで次々と開かれる様なシチュエーションでは、事故率を減らすため有効な方法です。
詳細はこちら

●キー送信の活用場面

どんな場面でキー送信が効果的なのか考えてみます。
場面1 「強引にマウス右クリックを再現したいとき。」
要素を特定したのにClickメソッドが効かず押下処理を実行できないシチュエーションにおいて有効な方法。Focusメソッドでボタン等の要素をアクティブにした上で、{ENTER}キーを1回送信することで、右クリック(押下)の挙動を高確率で再現できます。

場面2 「キー入力を強要するログインフォームを突破したいとき」
ログインフォームの中には、不正アクセス防止のため「キー入力を検知」する機能を備えたWebページが存在します。キー入力を伴わないIDやパスワード送信を不正アクセスと見做す安全機能ですが、自動化する上では邪魔でしかないので、当たり障りのないキーを1回送信して「キー入力を検知」させます。
この安全機能(JavaScript)を解読するよりも、とりあえずキー1回送信するだけの方が労力対効果が高いので、私は割とよく使います。
ログインフォーム(例えばパスワードを入力する<input>タグなど)をFocusメソッドでアクティブにした上で、{TAB}キー辺りを1回送信したのち、ログインボタンを押下すれば突破可能。


やや複雑な流れの自動化

●経過状況をイミディエイトウィンドウへ出力する

ブラウザ自動操作において、経過状況をリアルタイムで観測することは大事です。途中エラーで止まったときに、どこまで正常に動いていて、どこで躓いたのか確認しやすくなります。
また、VBEのイミディエイトウィンドウと、自動操作しているブラウザを1つの画面に並べて表示させれば、リアルタイムで観測可能です。

VBEとブラウザを、画面2分割して表示。

リアルタイムで観測していると、「この部分はもっと待機時間を長くとろう」とか、「Webページのこの操作は挙動不安定だから、別のアプローチを考えよう」とか、柔軟な発想がしやすくなります。
要所要所で、進捗状況をイミディエイトウィンドウへ出力させる等の対策を入れた方が捗ります。
 ・「Debug.Print "ページ読み込み完了"」
 ・「Debug.Print "ログイン情報送信完了"」
 ・「Debug.print "タイムアウトしました。処理中断します"」など

●リダイレクト状況を正確に追いかける

リダイレクト中のページ読み込み待機時間は、極力無駄がないようにしたいですね。待機時間が短すぎるとエラーが出て処理が止まってしまい、長すぎると効率低下します。
Webページに依っては、複数回リダイレクトした後に目的の画面が表示される事もあるので、アイデアを載せておきます。
(リダイレクト中の待ち時間が5~10秒くらい掛かるページも存在します)

Debug.Print "Edge立上げ完了"

オブジェクト.URL = "目的のページのURL"
Debug.Print "ページ移動開始"

TimeOutCnt = 0
Do 'リダイレクト(1回目)
 Sleep 1000
Loop While InStr(GetWinText(hWnd), "サインイン") = 0 'キャプション名が「***サインイン」に変わるまで待つ
Debug.Print "リダイレクト通過1"
    
Do 'リダイレクト(2回目)
 Sleep 1000
Loop While InStr(GetWinText(hWnd), "https://*****.okta.com/sso/***") = 0 'キャプション名が「https://*****.okta.com/sso/***」に変わるまで待つ
Debug.Print "リダイレクト通過2"

Do 'リダイレクト(3回目)
 Sleep 1000
Loop While InStr(GetWinText(hWnd), "サインイン") = 0 'キャプション名が「***サインイン」に変わるまで待つ
Debug.Print "リダイレクト通過3"

'目的のページが新しいウィンドウで開かれる
Debug.Print "処理完了"

上記例では、ウィンドウのキャプション名の変化からリダイレクト状況を判断しています。
 ・1回目「***サインイン」→
 ・2回目「https://*****.okta.com/sso/***」→
 ・3回目「***サインイン」→
とキャプション名が変化する毎に待機処理のループを設けています。
この例では1回目と3回目のキャプション名が同じなので厄介ですが、観測セクションを3分割することで、きちんとリダイレクト状況を追うことが出来ました。
実装するときはこちらのサブルーチン部分をコピペして下さい。


以上、Tips集でした。
Webページの構成は様々で、自動化したい操作も人それぞれです。汎用的だと思われる手法をここに纏めたつもりですが、気付いたことがあれば適宜加筆していきたいと思います。

この記事が気に入ったらサポートをしてみませんか?