VBAでスクレイピング
Excel VBAでスクレイピングするための基本を纏めたい、そんなモチベーションから記事です。
基本の流れ
VBAの構文としては下記の6つのステップを覚えておけば何とかなる気がしています。
あとは、プログラミングの前や作業の中で、実際に目的のWebサイトにアクセスしてブラウザの開発モードを駆使して、目的の情報がどのようなタグやどのような属性名の中にあるか分析することが大事だと思います。
(Javascriptの絡みでボタンを押せないパターンがあるので(.clickメソッド、.Submitメソッドが効かない)、その方法について別記事を後ほど作成しようと思います。)
6つのステップ
-
IEオブジェクト作成
Dim objIE As InternetExplorer
Set objIE = CreateObject("InternetExplorer.Application")
-
IEオブジェクト.NavigateメソッドでURLにアクセス
objIE.Navigate "http://hogehoge.co.jp"
-
IEを待ってあげる(ページ取得の時間)
Do While objIE.Busy = True Or objIE.ReadyState <> 4
-
DoEvents
Loop
-
DOMを取得する。
- 例えば下記はHTMLのClass名で取得する例。他にもtag名やID名で取得できる。配列として帰ってくるので単体を取得する場合は添え字(1)などを付けて取得するか、For Eachで要素すべてにアクセスする。
-
Dim ojbDOM as Object
(またはas HTMLDocument) objDOM = objIE.Document.getElementsByClassName("クラス名")(1)
-
- 例えば下記はHTMLのClass名で取得する例。他にもtag名やID名で取得できる。配列として帰ってくるので単体を取得する場合は添え字(1)などを付けて取得するか、For Eachで要素すべてにアクセスする。
-
DOMを検索して目的の情報を取得する。
- 例えば
<li class="クラス名">うんこ</li>
の「うんこ」という文字列を取得する場合は、objDOM.innerText
で取得できる。他にも下記を使って目的の情報にアクセスする。- タグを含めたDOMを取得する。
-
objDOM.innerHtml
、objDOM.outerHtml
-
- タグとタグに挟まれたテキストを取得する。
-
objDOM.innerText
,objDOM.outerText
-
- タグを含めたDOMを取得する。
- 例えば
-
(オプション)認証等の為にhtmlのテキストボックスに値(うんこ)をセットしてSubmitボタンを押す場合
Dim objtag As Object
objtag In objIE.Document.getElementsByTagName("input")(0)
objtag.Value = "うんこ"
objtag In objIE.Document.getElementsByTagName("input")(1)
objtag.click
事前準備
VBE参照設定 → 「MicroSoft Internet Controls」
これでIEのクラスが利用できる。
コードサンプル
基本のプロシージャ、そこから呼ばれるIEを操作するプロシージャ、あとIEをウェイトする関数を2つ、以上に分けてサンプルを書きました。
下記のコードの流れをざっくり謂うと
-
「うんこ」というキーワードを検索
-
検索結果ページの"Product__titleLink"というクラス名を持ったhtmlタグをすべて取得しアクティブシートの1列目に取得したinnerHTMLを列記していく。
以上の流れです。実際には、innerHTMLで取得できる内容はタグと属性と要素との集まりなので、実際に業務で必要になる情報の多くは、mid関数やinstr関数等を使って加工する必要があるかと思います。今回は、サンプルということでそこまではやりません。
Const MYURL = "http://hogehoge.co.jp"
Const SEARCH_WORD = "うんこ"
Sub スクレイピング()
Dim objIE As InternetExplorer
Dim url As String
Dim ws As Worksheet
Set ws = ActiveWorksheet
'IE起動
Set objIE = CreateObject("InternetExplorer.Application")
Call access(objIE,MYURL,ws)
objIE.Visible = True
objIE.Quit
Set objIE = Nothing
End Sub
`URLにアクセスする。
Sub access(ByRef objIE As Object, ByVal url As String, ByVal ws As WorkSheet)
Dim objtag, objsubmit As Object
Dim MyRow As Long
objIE.Navigate url
Call IEWait(objIE) 'IEを待機
Call WaitFor(3) '3秒停止
'yschspというテキストボックスを検索して、検索ワードをセットする。
For Each objtag In objIE.Document.getElementsByTagName("input")
If InStr(objtag.outerHTML, """HOGEHOGE""") > 0 Then
objtag.Value = SEARCH_WORD
Exit For
End If
Next
'検索ボタンを押す
For Each objsubmit In objIE.Document.getElementsByTagName("input")
If InStr(objsubmit.outerHTML, """検 索""") > 0 Then
objsubmit.Click
Call WaitFor(3)
Exit For
End If
Next
For Each objtag In objIE.Document.getElementsByClassName("Product__titleLink")
MyRow = ws.Cells(Rows.Count,1).End(xlUp).Row + 1
ws.Cells(MyRow, 1).Value = objtag.innerHTML
Next
End Sub
'IEを待機する関数
Function IEWait(ByRef objIE As Object)
Do While objIE.Busy = True Or objIE.ReadyState <> 4
DoEvents
Loop
End Function
'指定した秒だけ停止する関数
Function WaitFor(ByVal second As Integer)
Dim futureTime As Date
futureTime = DateAdd("s", second, Now)
While Now < futureTime
DoEvents
Wend
End Function
終わり
以上です。
冒頭でも書きましたが、clickメソッドが使えなかったケースへの対応や、DOMを加工してほしい情報を切り取る手法などについては、後ほど別記事を作成予定です。もし宜しければ そちらもご覧ください。