こんにちは、blueです。
今回はSeleniumでJavaScriptを使う理由について説明します。
皆さんは「Selenium-VBAで書くことができるのになぜJavaScriptで書く必要があるのか?」というところについて疑問を持たれたことはいないでしょうか?
そこで今回私が自分なりの考えを書くことにします。
私も最初はSelenium-VBAでスクレイピングを行っていました。
ただ何か月かするとこの方法のみでは安定しないということがわかってきたので、JavaScriptを勉強するようになりました。
結果的にJavaScriptを勉強することによって安定するようになってきたのでその内容について説明します。
考え方としては正しくない部分もあるかもしれませんが、皆さんのスクレイピングがより安定すればうれしく思います。
今回のサンプル
今回のコードサンプルはYahooのメールのログイン画面を使います。
Selenium-VBAでの書き方については以下を参考にしてください。
【Selenium-VBA】Yahooメールへのログイン方法をわかりやすく説明する
JavaScriptのメリット
最初に結論です。メリットは以下2つになります。
- ユーザー操作(イベント)が安定する
- 情報取得がしやすくなる
以降で1つずつ説明します。
JavaScriptの書き方、コードについては以下の記事を参照ください。
ユーザー操作(イベント)が安定する
1つ目の例としてボタンのクリックをあげます。
Seleniumで「ログイン」のボタンをクリックするコードは以下になります。
Driver.FindElementByCss("#btnSubmit").Click
私がSeleniumを扱っているうえでよく起こるエラーが以下になります。
- 要素が取得できない
- うまくクリックできずに止まる
前者はSeleniumを扱っている以上仕方ないと感じます(もしかしたらJavaScriptの方が安定するのかもしれないですがよくわかりません)
一方後者は以下のような状況でよく起こっています。
- クリック以外のイベントが実装されている
- href=のようなリンクが張られている
これはSeleniumの性質によるものと考えています。
SeleniumはWebDriverを使ってブラウザに送信することでユーザー操作を実現しています。
ただし、Seleniumはクリック操作をお願いしているだけなのでマウスを持って行った際に起こるイベントやリンクと干渉しているのではないかと思います。
実際要素が現れるまで十分待っても動いてくれないときがありました。
一方JavaScriptでは、この事象はおこらなくなります。
なぜならJavaScriptはClickイベントを直接発火させているからです。
具体的なコードと対象のイベントは以下になります。
Driver.ExecuteScript ("document.querySelector('#btnSubmit').click();")
実際私はClickイベントはJavaScriptにすることで安定するようになっているので間違っていないように思います。
Submitやmousoverのイベントでも同じことがいえると思います。
もう一つの例が情報の入力になります。
Seleniumの場合はSendKeysメソッドになります。
コードは以下です。
Driver.FindElementByCss("#username").SendKeys ("ユーザー名")
Driver.FindElementByCss("#passwd").SendKeys ("パスワード")
ただこちらも実際はコマンドを一度ブラウザに送信して入力処理を実行しているようです。
その為、Seleniumでは長文になると処理が遅くなる気がします。
一方JavaScriptの場合は問題ありません。
なぜならJavaScriptはプロパティに直接代入しているからです。
具体的なコードとプロパティは以下になります。
Driver.ExecuteScript "document.querySelector('#username').value='ユーザー名';"
Driver.ExecuteScript "document.querySelector('#passwd').value='パスワード';"
ブラウザへの入力もJavaScriptにお願いしたほうが安定するように思います。
情報取得しやすくなる
これも具体的な例としてTextメソッドを上げます。
Dim a As String
a=Driver.FindElementByCss("#inpUsernameBox").Text
SeleniumではHTML内の要素の値をTextメソッドにより取得できます。
ただここで取得できるのはHTMLに記載されているもののみとなります。
(以下の「上」の赤枠内のみ)
JavaScriptによって動的に生成された値はHTML内に書かれないことがあるのでこの方法ではうまく取れません。
一方JavaScriptの場合はHTMLからの情報も動的生成された情報も以下の方法で取得することができます。
(先ほどの図の上と下の赤枠両方の情報が取得できる)
Dim a As String
a = Driver.ExecuteScript("return document.querySelector('#inpUsernameBox').innerHTML;")
a = Driver.ExecuteScript("return document.querySelector('#inpUsernameBox').textContent;")
JavaScriptを理解するとHTML, JavaScript両方の情報が取得しやすくなるので使えるとよいと思います。
(なお細かく言うとSeleniumでもAttributeメソッドを使って以下のように取得することができます。
どうしてもSeleniumでという方はこちらをどうぞ)
Dim a As String
a=Driver.FindElementByCss("#inpUsernameBox").Attribute("textContent")
~2022/08/11追記~
JavaScriptの場合は要素の後ろに隠れて触れないものであったり、画面上に見えていない要素でも取得することができます。
これはJavaScriptがブラウザではなくHTMLを直接操作していることによるものです
上記のClickイベントが安定するのも同じ理由だと考えられます。
今回のまとめ
今回はSeleniumでJavaScriptを使う理由について説明しました。
- ユーザー操作(イベント)が安定する
- 情報取得がしやすくなる
どちらも最近のWebがJavaScriptからも構成されていることによるものです。
JavaScriptで作られているものであればJavaScriptで安定するのは自然なことなので、これを機会に勉強されるとよいと思います。
なお今回JavaScriptの勉強に使った書籍とサイトを紹介しておきます。
書籍は何冊か買っていますが一番わかりやすかったので、もし興味がありましたら購入くださいませ。
Selenium-VBAでのWebスクレイピングに関する記事はこちらをどうぞ
【ExcelVBA‐Selenium】【永久保存版】スクレイピングに必要なSeleniumのインストール方法教えます
【Selenium-VBA】Yahooメールへのログイン方法をわかりやすく説明する
ChromeでのWebスレイピングをできる限りわかりやすく説明する(Excel VBA)
【ExcelVBA‐Selenium】Chrome driverのバージョンエラーが出た時の対処法(2021/10/7更新)
【Selenium-VBA】Seleniumを用いたスクレイピングでテーブル情報を取得する1
【Selenium-VBA】スクレイピングをするのに必要なHTMLについて説明します1
【Selenim-VBA】起動済みのChromeを用いてSeleniumによるスクレイピングを行う
【Selenium-VBA】JavaScriptを使ってスクレイピングをしてみる1
【VBA】SeleniumBasicにおけるクラス、メソッド、プロパティ一覧(日本語版)
Web-APIを用いたデータ取得に関する記事はこちらをどうぞ
【VBA】Web APIを使ってデータを取得する(OpenWeatherMap)1
【VBA】Web APIを使って時間別天気予報を取得する(気象庁API)
【VBA】Web APIを使ってLINE通知を行う(LINE Notify)1
コメント