前回の記事ではSeleniumを使ったChromeでのWebスクレイピングについて説明しました。
前回の記事はこちら
今回はスクレイピングを行っていくうえで必要なメソッドについて、備忘録的に上げていくことにします。
このサイトを使ってSleniumBasicに少しでも慣れていただければ幸いです。
VBAを使ったものではありませんが、Seleniumを勉強する為の基本的な書籍です。ブラウザやキー操作の基本的なコマンドは共通していますのでコードを書く際の参考になります。
VBAの書籍の中でSeleniumBasicを取り上げている数少ない書籍です。ページ数としては20ページほどですがとてもわかりやすく書かれています。またVBA全般を網羅した内容が書かれており、長く使用することができます。
なお参考までに以下にSelenium Basicで用いるクラス、メソッド、プロパティの一覧をまとめています。
合わせてお読みください。
ブラウザ操作
フレームの移動
表示しているサイトがフレーム構造(サイト内が枠で分割されている)になっている際は移動の際に適したフレームにフォーカスさせる必要があります。
フレーム間を移動するメソッドは以下の通りです。
- Driver.SwitchToFrame “フレーム名”
- Driver.SwitchToDefaultContent
これを行うことでフレーム内の要素を取得することができます。
また別のフレームに移動する際は一度親フレームに戻る必要があるので、SwitchToDefaultContentメソッドで元のフレームに戻るようにします。
ページ上のアラート(警告)画面に移行
操作している際にページ上にアラートが表示されることがあります。
これはJavaScriptによって作成される画面です。
アラートの要素はそのままでは取得できませんが、アラートにフォーカスを移すメソッドがあります。
- Driver.SwitchToAlert
以下はアラート画面のオブジェクトを取得し、画面上のテキストの取得と、受け入れるコードです。
Dim dlg As Alert
'アラート画面のテキストを取得する
driver.SwitchToAlert().text
'アラート画面を受け入れる
dlg.Accept
新しいタブを開く
新しいタブを開くにはJavaScriptを使って以下のように記述します。
- Driver.ExecuteScript (“window.open(‘URL’)”)
なおExecuteScriptの()内の文字列はVBAのコードなので”で囲いますが、JavaScriptの()内の文字列は’(シングルコーテーション)になります。
VBAとJavaScriptで異なりますのでご注意ください。
JavaScriptを使ったコードについてはこちらをどうぞ
要素の取得
条件に合うすべての要素の取得(FindElementsメソッド)
条件にマッチしたすべての要素を取得したい場合に使用します。
メソッドは以下の通り。FindElementにsがついていることがポイントです。
- FindElementsByTag
- FindElementsByName
以下ではTagがtableであるすべての要素を取得し、数を数えています。
Driver.FindElementsByTag("table").Count
FindElementsメソッドは条件に合う情報をまとめて取得してその中の要素を検索するときによく使います。
Excel VBAでいうWorksheetsコレクションのようなものです。
一意な情報を取得するFindElementメソッドより高度な取得方法になります。
数の取得
要素の数を取得する際にはCountメソッドを使用します。
メソッドは以下の通り。
- Driver.FindElementsBy〇〇〇(“”).Count
このコードはFindElementsの要素内でループさせるときによく使います。
テーブル要素の取得
(2022/03/24追記)
テーブル要素の取得については以下の記事を追加しました。
2回に分けて紹介していますのでこちらもご覧ください。
テーブル内の特定のテキストを取得する際の基本コードは以下になります。
Driver.FindElementsByTag("table")(1).Text
Driver.FindElementsByTag("table")(1).FindElementsByTag("td")(1).Text
テーブル内の情報を取得するにはHTML内でのTableの構成を理解する必要があります。
(2022/4/24追記)
HTMLについては以下の記事を追加しました。
ここでは気象庁の過去の天気のテーブルの一部もとに説明します。
HTMLでのテーブルの構造は以下のようになっています。
tableは「Table(テーブル)」です。テーブル一つ一つを意味します。
trは「Table Row(行)」の略です。表の行を意味します。
thは「Table Header(見出し)」の略です。ヘッダーを意味します。
tdは「Table Data(データ)」の略です。表のデータとなるセルを1つを意味します。
FindElementsByTag(“table”)でTagにTableが含まれる要素をすべて取得しています。
そのうちのテーブルの1番目を取得してHTMLにあたるインナーテキストを全取得します。
FindElementsByTag(“td”)で上記のテーブル内のTagにtdが含まれる要素をすべて取得しています。
そのうちの一番目を取得してインナーテキストを取得しています。
これを使う場面はテーブル内の特定の要素を取得したいときです。
以下はテーブル内に5月16日が含まれる要素を検索して取得、クリックするコードです。
Dim i As Long
For i = 1 To Driver.FindElementsByTag("tbody")(1).FindElementsByTag("td").Count
If Driver.FindElementsByTag("tbody")(1).FindElementsByTag("td")(i).Text Like "*5月16日*" Then
Driver.FindElementsByTag("tbody")(1).FindElementsByTag("td")(i).Click
Exit For
End If
Next i
この方法を使うとテーブル内の特定の情報のみを取得することが可能になります。
特定の要素へのマウスオーバー
マウスを上部に置くと表示されるようなドロップダウンメニューバーなどに使用します。
以下は私のWordPress内の投稿ボタンです。投稿の上にマウスを置くとリストが表示されます。
要素の中央にマウスを動かす場合はMoveToElementメソッドを使用します。
このメソッドはユーザー操作を実現するActions classの中に存在します。
- Driver.Actions.MoveToElement(WebElement)
WebElement内にはマウスオーバーする要素を記載します。
以下は要素の中央にマウスを動かすコードです。
Actionsに格納した内容を実行する際はPerformメソッドを使います。
Dim element As WebElement
Set element = Driver.FindElementBy〇〇〇("属性値")
Driver.Actions.MoveToElement(element).Perform
なお私が使っている感じではあまり安定しないように思います。
その場合は直接隠れた要素を取得する方が好ましいかと思います。
要素のテキストを取得
Textメソッド
各要素のインナーテキストを抜き出す際はTextメソッドを使います。
メソッドは以下の通り。
- Driver..FindElementBy〇〇〇(“”).Text
このコードはWeb上のインナーテキスト=表示されている情報を正確に取得できているかを見るうえで重宝します。
MsgBox 上記のコード
Debug.Print 上記のコード
とすることで取得したTextを確認することもできます。
なおTextメソッドで取得できないテキストも存在します。
以下の記事に書かれていますので参考にしてください。
要素内の属性値を取得
Attributeメソッド
各要素内の属性値を取得する際はAttributeメソッドを使います。
メソッドは以下の通り。
- Driver..FindElementBy〇〇〇(“”).Attribute(“属性”)
HTMLの要素には、属性というものが付いています。
具体的には以下のように表記されます。
<要素名 属性="属性値">
HTMLに関しての記事は以下をどうぞ。
この属性値にあたる部分を取得する際にAttributeメソッドを使用します。
Attributeメソッドの引数には属性を指定します。
なおJavaScriptによって各要素に付加されている属性、属性値も存在します。
これはデベロッパーツールのプロパティで見ることができます。
これらはJavaScriptでの処理によって生成されたものの為、HTML上には表示されません。
ただこれらも同様にAttributeメソッドで取得できます。
最近は動的に生成された情報も多いので、JavaScriptの理解も必要になります。
JavaScriptについて説明した記事はこちらをご覧ください。
Webページの要素の存在判定
表示しているサイト内に特定の要素が存在するかを判定するにはIsElementPresentメソッドを使います。
メソッドは以下の通り。
- Driver.IsElementPresent(myBy.Css(“〇〇〇”))
- Driver.IsElementPresent(myBy.XPath(“〇〇〇“))
- Driver.IsElementPresent(myBy.ID(“〇〇〇“))
〇〇〇・・・各属性の情報
検索した結果をTrue or Falseで返します。
引数のByはSeleniumのクラスで検索条件を指定するために使用します。myをつけているのは「プライベートで作った変数である」とわかりやすくするためです。
By.メンバー(引数)で指定した要素を検索条件とします。
メンバーとしては上にあるようにClass, xpath, Css, idなどがあり好きなものを指定することができます。
要素の読み込み完了まで待つ
要素の読み込みが完了するまで待つにはIsElementPresentメソッドを使って以下のように記載します。
Dim myBy As New By
Dim i As Long
'5秒待つプログラム
i = 0
Do Until i > 5
If Driver.IsElementPresent(myBy.Css(Path)) Then
Exit Do
End If
Driver.Wait 1000
i = i + 1
Loop
一つ上で説明したIsElementPresentメソッドで特定の要素が存在するかを判定し、存在する(True)までDo~Loopで処理します。
Seleniumにはもともと読み込み完了まで待つ機能がありますがページ内遷移など読み込み完了まで待たないケースがあります。
この不安定さをなくすために特定の要素が出てくるまで待つコードとして使用します。
また以下ではサブルーチン化しています(Driverはグローバル変数化しておいてください)。
*Css Selectorの場合
Sub CssConfirmation(ByVal Path As String)
Dim myBy As New By
Dim i As Long
i = 0
Do Until i > 10
If Driver.IsElementPresent(myBy.Css(Path)) Then
Exit Do
End If
Driver.Wait 1000
i = i + 1
Loop
End Sub
*XPathの場合
Sub XPathConfirmation(ByVal Path As String)
Dim myBy As New By
Dim i As Long
i = 0
Do Until i > 10
If Driver.IsElementPresent(myBy.XPath(Path)) Then
Exit Do
End If
Driver.Wait 1000
i = i + 1
Loop
End Sub
*IDの場合
Sub IDConfirmation(ByVal Path As String)
Dim myBy As New By
Dim i As Long
i = 0
Do Until i > 10
If Driver.IsElementPresent(myBy.ID(Path)) Then
Exit Do
End If
Driver.Wait 1000
i = i + 1
Loop
End Sub
その後要素確認が必要な個所の前で以下のようにCallステートメントで呼び出してやればよいです。
Call CssConfirmation("Cssパス")
Driver.FindElementByCss("Cssパス")
Call XPathConfirmation("XPathパス")
Driver.FindElementByCss("XPathパス")
Call IDConfirmation("ID名")
Driver.FindElementByID("ID名")
別で待機処理に関する記事も書いています。興味のある方はこちらもどうぞ
■ここでのまとめ
VBAをつかったWebスクレイピングはなかなか情報が少ないです。新しく学んだコードは上げていきますので少しでも役に立てれば幸いです。
VBAを使ったものではありませんが、Seleniumを勉強する為の基本的な書籍です。ブラウザやキー操作の基本的なコマンドは共通していますのでコードを書く際の参考になります。
VBAの書籍の中でSeleniumBasicを取り上げている数少ない書籍です。ページ数としては20ページほどですがとてもわかりやすく書かれています。またVBA全般を網羅した内容が書かれており、長く使用することができます。
↓困ったときは以下が頼りになります。私も利用させてもらってます😊。
SeleniumBasicのWebスクレイピングに関するまとめ記事はこちらをどうぞ
Web-APIを用いたデータ取得に関する記事はこちらをどうぞ
【VBA】Web APIを使ってデータを取得する(OpenWeatherMap)1
【VBA】Web APIを使って時間別天気予報を取得する(気象庁API)
【VBA】Web APIを使ってLINE通知を行う(LINE Notify)1
もしVBAの資格について興味がある方はこちらもどうぞ。資格取得までの流れを把握できます。
コメント