スクレイピングで要素が見つからない…ページロード完了判定はステータス判定だけでは不確実!

Excel VBAでスクレイピングのコードを書いたりするのだが、ページが完全にロードされていない状態でDom操作などしようとすると、「要素が見つかりません」のエラーや、オートメーションエラーなどが発生する。

だから、通常は、ページロードのステータスをチェックして、完了のステータスになったら次のブラウザ操作処理などを行う。 例えば、IEオブジェクトを扱っている場合、次のようなコードがよく紹介されている。

Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE
    DoEvents
Loop

読み込み完了したらループを抜けるというロジック。 だけど、ループを抜けてもオートメーションエラーが発生することって、少なからずある。

ステータスが読み込み完了になっているにも関わらず、実際には完了していない・・・ステータスが嘘をついていることがある。 嘘というと語弊があるかもしれないが、とにかくステータスだけで判断すると、後続の処理でエラーが出ることがある。

また、チャタリングと言われる現象が生じることもあるそうだ。

チャタリングとは、スイッチ機構やリレー機構などにおいて、オン・オフの接点が切り替わる際に、オン・オフが細かく繰り返される現象のことである。
https://japan.zdnet.com/glossary/exp/%E3%83%81%E3%83%A3%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0/

ページロードの場合は、ステータスが切り替わる際に、細かくステータスが繰り返し変わるような、不安定な状態が一時的に生じるってことだろう。

さて、上記の対策だが、まずはチャタリング対策としては、上記コードでループを抜けた後に1秒待ってみる。待機後はステータスが安定しているだろうと予測してのことだ。

そして必須の対策としては、上記のようなステータス判定に加えて、操作したいHTML要素が出現しているかチェックすることだ。

例えば、HTMLドキュメントのテキスト内で、操作したい要素を特定できるようなキーワードで文字列検索し、ヒットするまでループで待機させる。id属性やclass属性などをキーワードにして。

DOM操作で要素が存在するかをチェックする方法もある。 例えば objIE.document.getElemntsbyClass(“xxx”)のカウントが1以上になるまでループで待機するなど。 この方法は上のキーワード検索よりも簡単にチェックできるが、エラーになることがある。よって、万全を期すならキーワード検索するしかない。

これらの対策でエラーが出た場合は、そこで単純に処理を終了させるのではなく、何度かリトライすることだ。こうすれば、要素の出現を待つだけでよくて、ページロードのステータス判定は要らないかもしれない。(この方法は試したことないが)

上で説明した対策はとても泥臭いものだが、ブラウザ操作自体が非常に不安定であり、スクレイピングではこんな方法が必要になってくると思っている。