こんにちは、blueです。
SeleniumBasicで少しスクレイピングができるようになってくると
・スクレイピングが安定しないんだけどどうして? ・特定の場所でいつもエラーが起こるんだけどどうして?
と思うことが多くなってこないでしょうか?
これはSeleniumの速度やWebブラウザの構成によるものなのですが、よくわからずとりあえずWaitメソッドをいれておいてというようなこともあるかと思います。
そこで今回はSelenium-Basicで適切な待機処理を入れる方法について説明します。
この記事を読めば各コードに対して適切な待機処理を入れる方法を知ることができるようになりますので是非読んでいってください。
なお今回の内容は以下の書籍を参考にしています。
Seleniumに関する内容が一通り入った書籍です。残念ながらVBAを使った書籍ではないですが慣れてきたら他の言語からでも読み解くことはできます。
クローリング全般に関する内容が入った書籍です。Seleniumというよりかはクローリングの手法が多く書かれていて勉強になります。Seleniumは後半に10数ページほど書かれています。
なぜエラーが起こるのか?
そもそもなぜエラーが起こるのかについてまずは説明します。
SeleniumはWebDriverを使ってブラウザにコマンドを送信することでユーザー操作を実現しています(Wikipedia)
このことからSeleniumはページの読み込み中は待機して、読み込みが終わるまでは次の操作をしないようになっています。
その為IEより安定しやすいといった話も出ています(IEは読み込み待ちしないので完了待ちのコードを書かないといけません)。
しかし、ページ内の動的な処理(JavaScriptなど)に対しては待機しません。
その為その後のコードで要素が見つからずにエラーが出たりすることになります。
対策としてはこれらに対して待機処理を行うのですが、手法としては2種類あるのでそれぞれについて説明します。
対策
Seleniumにおける待機処理については以下2種類が存在します。
- Implicit Wait(暗黙的待機)
- Explicit Wait(明示的待機)
それぞれについて以降説明します。
Implicit Wait(暗黙的待機)
プログラム内のすべてのFindElement(s)に対して要素が見つかるまでの待機時間を設定するのがImplicit Waitです。
以下は1000ミリ秒の待機時間を設定しています。
Driver.Timeouts.ImplicitWait = 1000
WebDriverのTimesoutsプロパティに対して要素が見つかるまで指定時間待機するImplicitプロパティを設定しています。
コードとしては一度これを書いてしまえば以降はすべての要素判断において待ち時間が設定されます。
また要素が見つかった場合は待機することなく次の処理に進んでくれます。
ただこの待機処理は要素の取得にしか使えないので属性の変化を待つ場合などには使えません。
Explicit Wait(明示的待機)
プログラム内の個別のコードごとに指定した条件を満たすまで待機する処理を入れるのがExplicit Waitです。
明示的待機については以下のようなものがあります。
- Driver.Waitメソッド
- Driver.Wait●●●メソッド
- (おまけ)Driver.IsElementPresentメソッド
3つ目は待機処理でなく、存在確認なのですがVBAと組み合わせて待機処理が作れるのでここに入れておきます。
Driver.Waitメソッド
WebDriverを指定した時間待機させるコードです。
具体的なコードは以下になります。
Driver.Wait 1000
これは一番簡単な方法となります。
ただ冒頭にも触れた通り、指定時間止まるだけなのでとりあえずの対応になります。
Driver.WebElement.Wait●●●メソッド
WebElementクラスには指定した条件が満たされるまで待機するメソッドとしてWebElement.Wait●●●メソッドが存在します。
代表的なものとしては以下があります。
Name | Description |
WaitAttribute | 属性待ち |
WaitCssValue | CSS プロパティを待ちます。 |
WaitNotAttribute | 別の属性で待機する |
WaitNotCssValue | 別の CSS プロパティを待ちます。 |
WaitNotElement | 要素が欠落するのを待つ。(SearchContextから継承) |
WaitNotText | 別のテキストを待ちます |
WaitRemoval | Web 要素が DOM から削除されるのを待ちます。 |
WaitSelection | 要素が選択されるかどうかを待機する。 |
WaitText | テキストを待ちます |
具体例を2つ挙げます。
要素内のテキストが”hello”になるまで待つコードは以下になります。
Dim elm As WebElement
Set elm=Driver.FindElementById("Id名").WaitText("hello",2000)
WaitTextメソッドは第一引数に文字列、第二引数に秒数を記載します。
また戻り値はWebElementになるのでオブジェクトとして変数を宣言します。
秒数以内に条件を満たせばWebElementが、満たさなければNothingが返ります。
要素内のtextContentプロパティの値が”friend”になるまで待つコードは以下になります。
Dim elm As WebElement
Set elm = Driver.FindElementByID("Id名").WaitAttribute("textContent", "friend", 10000)
WaitTextメソッドは第一引数に属性名、第二引数に属性値、第三引数に秒数を記載します。
こちらも同様で条件を満たせば要素が返ります。
Driver.IsElementPresentメソッド
WebDriverクラスには要素の存在可否を判断するIsElementPresentメソッドが存在します。
これだけだと存在するかどうかを判断するだけですが、VBAのDo~Loopの中に入れることで待機処理に使うことができます。
このコードについては以下の記事の「Webページの要素の存在判定」を参考ください。
今回のまとめ
今回はSeleniumBasicで適切な待機処理を入れる方法について説明しました。
暗黙的待機と明示的待機両方使いこなせるようになればより安定したスクレイピングができるようになります。
ぜひ使い分けて使ってみてください。
今回の内容は以下の書籍を参考にしています。
Seleniumに関する内容が一通り入った書籍です。残念ながらVBAを使った書籍ではないですが慣れてきたら他の言語からでも読み解くことはできます。
クローリング全般に関する内容が入った書籍です。Seleniumというよりかはクローリングの手法が多く書かれていて勉強になります。Seleniumは後半に10数ページほど書かれています。
コメント