SeleniumBasicでダイアログボックスのハンドル  usage_alert

リファレンス

 usage_alertでは、ブラウザのダイアログボックスの利用方法を紹介しています。ダイアログボックスをアラート型オブジェクトとしてキャッチし、処理します。ダイアログボックスは、ブラウザ操作中に出現してくる確認画面や、入力ボックスのことで、JavaScrioptで制御されています。以下、ダイアログボックスのサンプルです。

出典:https://www.tagindex.com/javascript/window/alert1.html
  • 利用目的は業務効率化です。(テスト自動化ではありません)
  • ブラウザはGoogleChromeが対象です。(EdgeやFirefoxは対象外)
  • 原文のVBAでは現在エラー発生する場合が多いため、修正を加えてます。
Examples.xlsmの保存場所(ここをクリック)

 Examples.xlsmが保存されている場所は、SeleniumBasicがインストールされているサブフォルダ内になります。SeleniumBasicのインストール完了時に保存フォルダを確認することができます。ただ、大体以下フォルダのどちらかにファイル保存されています。

  • C:\Program Files\Seleniumbasic\Examples\Excel
  • shell:Local AppData\SeleniumBasic\Examples\Excel
目次

ダイアログボックスのキャッチ

 Examplesの内容に多少アレンジを加えてコード入力しました。結構ごちゃごちゃ書かれていますので、まずは必要な項目だけを抜き出してみました。
スクレイピングで参照したホームページは、ここです。
 ページに変遷した後、ダイアログボックスを表示させ、「OK」ボタンをクリックするところまで実行します。

Private Sub Simple_Handle_DialogBox()
    Dim driver As New ChromeDriver
    driver.Get "https://www.tagindex.com/javascript/window/confirm.html"
    ' ダイアログを表示
    driver.FindElementByCss("#content > section.overview > figure > p > input[type=button]").Click
    'dlgオブジェクトにダイアログボックスを代入
    Dim dlg As Alert: Set dlg = driver.SwitchToAlert
    driver.Wait 2000    '2秒待つ
    dlg.Accept  '「OK」ボタンをクリック
    Stop
    driver.Quit
End Sub

 7行目でダイアログボックスを表示させた後、Alert型の変数にダイアログボックスに移したドライバーを代入します。
 8行目でダイアログボックスの出現を確認するため、2秒間一時停止しています。
 9行目でダイアログボックスの「OK」ボタンをクリックするため、"Accept"を入力しています。キャンセルを選択したい場合は、"Dismiss"を入力します。

 元々のコードにアレンジを少し加えたコードを以下に記載します。
結果は、上のSimple_Handle_DialogBoxのコードと変わりありません。

Private Sub Handle_DialogBox()
On Error GoTo ErrHandle
    Dim Assert As New Selenium.Assert
    Dim driver As New ChromeDriver
    driver.SetCapability "unexpectedAlertBehaviour", "ignore"
    driver.Get "https://www.tagindex.com/javascript/window/confirm.html"
    ' ダイアログを表示
    driver.FindElementByCss("#content > section.overview > figure > p > input[type=button]").Click
    'dlgオブジェクトにダイアログボックスを代入
    Dim dlg As Alert: Set dlg = driver.SwitchToAlert(Raise:=False)
    Assert.False dlg Is Nothing, "アラートが存在しません。"
    Assert.Equals "アラートの表示", dlg.Text
    Dim flg As Boolean: flg = IsDialogPresent(driver)
    If dlg Is Nothing Then Stop
   driver.Wait 2000    '2秒待つ
    dlg.Accept  '「OK」ボタンをクリック
    driver.Quit
    Exit Sub

ErrHandle:
    Debug.Print Err.Description
    On Error GoTo 0
Stop
    driver.Quit
End Sub

Private Function IsDialogPresent(driver As WebDriver) As Boolean
    On Error Resume Next
    Dim T As String: T = driver.title
    IsDialogPresent = (26 = Err.Number)
End Function

エラーキャッチの構文紹介

 上記Handle_DialogBoxのエラー構文が何を意味しているのか確認、検証するため、一つ一つの役割に分解して構文を紹介します。

ダイアログボックスが存在しない状態でキャッチをしようとした場合_1

 ダイアログボックスが出現する前にSwitchToAlertメソッドでドライバーをダイアログボックスに移そうとすると、存在しないダイアログボックスをキャッチしようとするので、エラーが発生します。
 エラー例をいくつか紹介します。エラーハンドルでエラーボックスを回避する代わりにイミディエイトウィンドウにエラー文を出力する様にしています。

Private Sub Alerts_ErrTest1()
On Error GoTo ErrHandle
    Dim driver As New ChromeDriver
    driver.Get "https://www.tagindex.com/javascript/window/alert1.html"
    Dim dlg As Alert: Set dlg = driver.SwitchToAlert  'ここでエラー発生
    driver.Quit
    Exit Sub
ErrHandle:
    Debug.Print Err.Description
    driver.Quit
End Sub

5行目の時点でダイアログボックスにドライバーを移そうとした時にエラーが発生します。

ダイアログボックスが存在しない状態でキャッチをしようとした場合_2

Private Sub Alerts_ErrTest2()
On Error GoTo ErrHandle
    Dim Assert As New Selenium.Assert
    Dim driver As New ChromeDriver
    driver.Get "https://www.tagindex.com/javascript/window/alert1.html"
    Dim dlg As Alert: Set dlg = driver.SwitchToAlert(Raise:=False) 'Raise:=False←エラーを上げない
    Assert.False dlg Is Nothing, "アラートが存在しません。"  'ここでエラー
    driver.Quit
    Exit Sub
ErrHandle:
    Debug.Print Err.Description
    driver.Quit
End Sub

 本来なら、Alerts_ErrTest1と同じタイミングで6行目の時点でエラーが発生するはずですが、Raise:=Falseの引数を入力することにより、エラー発生しない様にしています。
 上記例では、7行目でエラーが発生します。7行目に記載されているAssertは、SleniumBasic独自のインスタンスで、VBAのdebug.Assertと似たような使い方です。3行目でインスタンス生成しています。(原文ではPrivateで宣言しています。)
SeleniumBasicのドキュメントを参照すると、以下構成でした。

Dim input As Boolean
Dim failmessage As String
Assert.False(input, failmessage)

 Assert.Falseメソッドは、inputにFalseを入力すれば、エラーを出さずにそのまま通過していきます。上記例では、dlg Is Nothing = True の論理式になり、Falseではないのでエラー発生しています。

ダイアログボックスが存在しない状態でキャッチをしようとした場合_3

Private Sub Alerts_ErrTest3()
    Dim driver As New ChromeDriver
    driver.Get "https://www.tagindex.com/javascript/window/alert1.html"
    Dim dlg As Alert: Set dlg = driver.SwitchToAlert(Raise:=False) 'Raise:=False←エラーを上げない
    Dim flg As Boolean: flg = IsDialogPresent(driver)
    If dlg Is Nothing Then Stop  'ここでストップ
    driver.Quit
End Sub

Private Function IsDialogPresent(driver As WebDriver) As Boolean
    On Error Resume Next
    Dim T As String: T = driver.title
    IsDialogPresent = (26 = Err.Number)
End Function

 上記例では、IsDialogPresent関数により、ダイアログボックスの存在が確認できなければ、6行目でストップする構文になっています。関数の内容は、ダイアログボックスが存在したらTrueを返し,無ければ Falseを返します。Falseの場合、ドライバーのタイトルも取得する様になっています。Trueの場合はdriverがNothingとなるので、On Error Resume Nextでエラー回避しています。
 13行目の比較演算子が見慣れない式ですが、論理構造は以下ページで詳しく解説されています。

ダイアログボックスのメッセージが予期していた文字列と異なる場合

Private Sub UnexpectedAlertMessage()
On Error GoTo ErrHandle
    Dim Assert As New Selenium.Assert
    Dim driver As New ChromeDriver
    driver.Get "https://www.tagindex.com/javascript/window/alert1.html"
    driver.FindElementByCss("#content > section.overview > figure > p > input[type=button]").Click
    Dim dlg As Alert: Set dlg = driver.SwitchToAlert(Raise:=False) 'Raise:=False←エラーを上げない
    Assert.Equals "ほげ", dlg.Text  'ここでエラー発生
    driver.Quit
    Exit Sub
ErrHandle:
    Debug.Print Err.Description
Stop
    driver.Quit
End Sub

 8行目のAssert.Equalsでダイアログボックスのメッセージ内容が予期していた文字列(”ほげ”)になっているかチェックしています。Assert.Equalsメソッドは、SeleniumBasicのドキュメントを参照すると、以下構成でした。

Dim expected As Object
Dim input As Object
Dim failmessage As String
Assert.Equals(expected, input, failmessage)

 expected = input の場合、エラーを出さずに通過させます。
上記例では、expected = ”ほげ” 、 input = dlg.Text("アラートの表示")により
”ほげ” <> "アラートの表示" となり、エラー発生しています。failmessageは省略可能ですので、特に入力はありませんでした。

予期せぬアラートが出た場合

 「予期せぬアラート」とはどの様なものかというと、スクレイピング途中で出現する離脱防止ポップアップ等の事を言います。ポップアップが出た状態で新たにdriver.Getをすると予期せぬアラートになる様です。 スクレイピング途中でポップアップが出てこない事を前提にコードを書いていると、ポップアップを回避できず、予期せぬアラートとしてエラー発生します。
 今回は、ダイアログボックスを出現させた状態で新たにdriver.Getし、ページ変遷を実行した時に予期せぬアラートを模擬的に出現させました。

Sub UnexpectedAlert()
    On Error GoTo ErrHandle
    Dim driver As New ChromeDriver
    driver.SetCapability "unexpectedAlertBehaviour", "accept"   
    driver.Get "https://www.tagindex.com/javascript/window/confirm.html"
    driver.FindElementByCss("#content > section.overview > figure > p > input[type=button]").Click
    Dim dlg As Alert: Set dlg = driver.SwitchToAlert(Raise:=False)
    driver.Get "https://www.tagindex.com/javascript/window/alert1.html"  'ここでエラーが発生(「OK」ボタンはクリックする)
    Exit Sub
ErrHandle:
    Debug.Print Err.Description
    On Error GoTo 0
Stop
    driver.Quit
End Sub

 4行目でdriver.Get(5行目)より前に予期せぬダイアログボックスが出現した場合の事前設定をしています。設定種類は、"accept"、"dismiss"、"ignore"の3種類です。
 "accept"  ⇒ 予期せぬアラート出現時に「OK」をクリックする。
 "dismiss" ⇒ 予期せぬアラート出現時に「キャンセル」をクリックする。
 "ignore"  ⇒ 予期せぬアラート出現時に無視する。(検証できませんでした。。)
 現在のChromeでは、上記3種類どれを選んでもエラーは発生します。ですので、"ignore"を選択してもどの道エラーが発生するので、現在は"ignore"を利用する意味は無い状態かと思われます。
 8行目でエラーが発生するので今回は、ErrHandleでエラー内容を出力する構文にしていますが、実運用では、"On Error Resume Next"でエラー回避すれば良いかと思います。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

VBAを中心とした自動化、効率化の手法を紹介しています。現在は、SeleniumBasicのexamplesを紹介しています。その内、SeleniumBasic以外の手法も掲載したいと思っております。

目次