開発
VBAでieを操作してWEBサイトから情報収集をしちゃおう♪をしてみて気がついた!
Tomoko Saito
WEBサイトに掲載されている情報を一気に収集しようと考えて、VBAソースがネット上に落ちていたのでありがたく流用してみたのですが、ページロード完了待ち動作が期待通りに動いてくれず、自分なりの方法を採用しました。原因を調べていたところ同じ個所でつまずいている人も多いようでしたので、アップします。
今回VBAでWEBサイト上の情報を収集するために〔InternetExplorer object〕と〔DOM〕の2つを利用しました。
■InternetExplorer objectとは
Internet Explorerの操作をおこなうオブジェクトです。
ieを起動する。検索フォームに文字を入力する。ボタンをクリックする。といったブラウザの操作が行えるので、これを利用すれば目的のページにたどり着いて情報を表示することができます。
■Document Object Model (DOM) とは
HTML文書やXML文書をアプリケーションから利用するためのAPIです。
JavascriptユーザはDOMはおなじみかもしませんがVBAからも利用できます。HTMLの要素(<p><img>)などを部品としてメソッドやプロパティをアプリケーションから操作することができるので、表示されているWEBページのhtmlから必要な情報を取得したり変更できたりします。
さてさっそくソースコードです。
今回は「ieを起動→googleを表示→フォームに検索ワードを入力→検索ボタンクリック」までとします。
_____________________________________
Declare Sub Sleep Lib “kernel32” (ByVal dwMilliseconds As Long)
Option Explicit
_____________________________________
Private Sub GoogleSearch()
‘—————————————————-
‘ googleの検索窓に チョコレート と入力して検索する
‘—————————————————-
Dim objIE As Object
‘IE起動
Set objIE = CreateObject(“InternetExplorer.Application”)
objIE.Visible = True
‘Googleを開く
objIE.navigate “http://www.google.co.jp/”
‘1.5秒待つ
Sleep (1500)
‘IEが表示完了するまで待つ
Call IeWait(objIE)
‘検索窓に「チョコレート」と入力
objIE.document.forms(0).Item(“q”).Value = “チョコレート”
‘1秒待つ
Sleep (1000)
‘ 検索ボタンをクリック
objIE.document.getElementById(“gbqfb”).Click
‘IE終了しない
‘objIE.Quit
‘Set objIE = Nothing
End Sub
_____________________________________
Private Function IeWait(ByRef objIE As Object)
‘—————————————————-
‘ ページロードの待ち受け処理
‘—————————————————-
Do While objIE.document.readyState <> “complete”
DoEvents
Loop
End Function
_____________________________________
本題です。
期待通りの動作をしなかったページロードの待ち受け処理ですが、多くのサイトでは下記コードになっていました。
********************************************************
Do While objIE.Busy = True Or objIE.readyState <> 4
DoEvents
Loop
********************************************************
このコードで起きる問題としては、ループを抜けたのに次のDOMオブジェクト操作が行えない。ページロード途中にループを抜けてしまう。等です。
そこでこの部分【readyState】てなんぞや?と調べた結果が下記です。
■InternetExplorer object readyStateプロパティ
0=READYSTATE_UNINITIALIZED
Default initialization state.
1=READYSTATE_LOADING Object is currently loading its properties.
2=READYSTATE_LOADED Object has been initialized.
3=READYSTATE_INTERACTIVE Object is interactive, but not all of its data is available.
4=READYSTATE_COMPLETE Object has received all of its data.
ふーむ別に悪くない気もします。
が、調べていくとこれはie=ブラウザ動作を判定しているので、HTML文書の動作判定とは異なり、思ったような判定結果が得られない場合があるらしい。ということが分かってきました。
というわけでInternetExplorer objectで判定するのをやめて、DOMで判定することにしました。
■DOM readyState Property
文書の読み込み状況を示す文字列を返す
uninitialized – まだロードがスタートしていない
loading – ロード中
Interactive – ロード中であっても、操作可能である
complete – 完全にロードされた
Do While objIE.Document.readyState <> “complete”
DoEvents
Loop
今のところこれで期待通りの動作(ページロードが完了まで待つ)をしてくれています。
もしかしたらJavascriptユーザには当たり前の知識だったのかもしれませんね。
良い勉強になりました。
まだSleep使ってるあたりが美しくないなぁと思うのですが、Sleep無しではVBAの処理のほうが早すぎるのか、オブジェクトが存在しませんエラーになってしまいます。時間があったら改善したいと思います。