エクセルバージョン
マイクロソフト365
エクセルでwebスクレイピングする場合は、前回のサイトをを表示する①で解説した2通りのどちらかの方法ではInternet Explorerオブジェクトを作成します。
前回少しご紹介した下記の参照設定を必ず設定してください。
Microsoft HTML Object Library
Httpリクエストで高速スクレイピングをしたい場合はこちら
Menu
繰り返し処理(ForEach)
webスクレイピングでHTMLの目的の場所を探しだすには、エクセルの繰り返し処理で検索して取得やクリックをしていきます。
そしてスクレイピングに必要な繰り返し処理がForEachになります。
【使用例】
1 2 3 4 | 'ForEachを使用してリンクを全取得する例 For Each element In objIE.document.Links 'ForEachの繰り返し処理でリンクを検索 Debug.Print element.innerText 'リンクを書きだす Next |
目的の場所を探す
下記4つのメソッドで引数を指定してHTMLの目的の要素や属性を絞り込みます。
ちなみにこちらはジャバスクリプトで、DOMツリー操作をするためのDocumentオブジェクトのメソッドなります。
参照設定をすることによりエクセルVBAでも使用できるのでこれらを使用して取得が可能になるという仕組みになっております。
③getElementsByClassName(“クラス属性値”)
その他にもありますがこの4つでほぼ全て取得できます。
①getElementsByTagName(”タグ名(要素名)“)
その名のとおりタグ名(要素名)を指定して目的のタグ名(要素名)を探します。
【例】<a href=”https://dailyrecords.blog/”>デイレコ</a>
HTMLのaの部分です。通常はaタグと呼ばれます。
【使用例1】
デイレコ (←左のようなaタグを検索してリンク文字(innerText)にデイレコが含まれていたらリンクをクリックする例)instr関数を上手く利用します。
1 2 3 4 5 6 7 | 'タグ名を指定してリンククリック時の使用例 For Each element In objIE.document.getElementsByTagName("a") 'aタグを繰り返し探す If InStr(element.innerText, "デイレコ") > 0 Then 'リンクにデイレコがあったら実行 element.Click 'リンクをクリックする Exit For End If Next |
【使用例2】
Like演算子でワイルドカードを使用したパターン検索でも簡単にクリックできます。
1 2 3 4 5 6 7 | 'Like演算子でパターン検索してaタグをクリックする例 For Each element In objIE.document.getElementsByTagName("a") 'aタグを探す If element.innerText Like "*デイレコ*" Then 'デイレコが含まれていたら element.Click 'クリックする Exit For End If Next |
②getElementsByName(“name属性値”)
HTMLのname属性値を指定して目的のname属性値を探します。
【例】<input type=”text” name=”Email” >
HTMLのnameの部分です。nameが属性、Emailが属性値です。
【使用例】(name属性値がEmailだったらsample@google.comと入力する例)
1 2 3 4 5 | 'name属性値のEmailに書き込む例 For Each Attr In objIE.document.getElementsByName("Email")'name属性値Emailを探す Attr.Value = "sample@google.com" '見つかったら値を書き込む Exit For Next |
【結果】←みたいな感じで書き込めます。
③getElementsByClassName(”class属性値”)
HTMLのclass属性値を指定して目的のclass属性値を探します。
【例】<li class=”price”>¥100</li>
HTMLのclassの部分です。この場合はclassが属性、priceが属性値です。
【使用例】(classの属性値がpriceの文字をセルA1に書き込む例)
1 2 3 4 5 | 'クラス属性値がpriceだったらセルA1に文字を書きだす例 For Each Attr In objIE.document.getElementsByClassName("price") 'priceを探す Range("A1") = Attr.innerText '見つかったら文字のみセルA1に書き出す Exit For Next |
【結果】セルA1に¥100が書き込まれます。
④getElementById(”id属性値”)
HTMLのid属性値を指定して目的のid属性値を探します。
探し方は②や③と一緒でgetElementByIdに変更するだけです。
取得
・innerText(要素(タグ)を含まない文字のみを取得)
・outerText(要素(タグ)を含まない文字のみを取得)
・innerHtml(要素内のHTMLと文字を取得)
・outerHtml(要素と要素内のHTMLと文字を取得)
※こちらはjavascriptのプロパティになります。
取得サンプル
全pタグの文字のみを取得してA列に1行ずつ書き出します(innerText)
1 2 3 4 5 6 7 | 'pタグの文字を取得して1行ずつ書きだす Dim i As Integer i = 1 For Each element In objIE.document.getElementsByTagName("p") Cells(i, 1) = element.innerText i = i + 1 Next |
全pタグのタグも含めた文字を取得してA列に1行ずつ書き出します(outerHTML)
1 2 3 4 5 6 7 | 'Pタグのタグも含めた文字を全取得してセルに1行ずつ書き込む Dim i As Integer i = 1 For Each element In objIE.document.getElementsByTagName("p") Cells(i, 1) = element.outerHTML i = i + 1 Next |
全aタグのリンクを取得しながら動的配列(ReDim Preserve)に格納してB列に1行ずつ書き出します(outerText)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 'リンクを全取得、配列に格納後B列に書出し Dim i, aryNum As Integer Dim aryAtag() As Variant 'Aタグのリンクを取得して配列に格納 For Each element In objIE.document.getElementsByTagName("a") ReDim Preserve aryAtag(i) aryAtag(i) = element.outerText i = i + 1 Next i = 1 '配列に格納されたリンクをB列に1行ずつ書出し For aryNum = 0 To UBound(aryAtag) Cells(i, 2) = aryAtag(aryNum) i = i + 1 Next |
UBoundで配列の最大個数(インデックスの最大値)を取得
書込み(valueメソッド)
テキストボックスに書き込む
<input type=”text” class=”testBox”>
1 2 3 4 5 6 7 | 'テキストボックスに書き込む例 For Each element In objIE.document.getElementsByClassName("testBox") 'testBoxを探す If element.getAttribute("type") = "text" Then 'type属性値がtextだったら処理 element.Value = "デイレコへようこそ" 'テキストボックスに書き込む Exit For End If Next |
【結果】←みたいな感じで書き込めます。
パスワードに書き込む
1 2 3 4 5 6 | For Each element In objIE.document.getElementsByName("testPass") 'nameがtestPassを探す If element.getAttribute("type") = "password" Then 'type属性値がpasswordだったら処理 element.Value = "TESTPASSWORD" 'パスワード入力画面に書き込む Exit For End If Next |
【結果】←みたいな感じで書き込めます。
※実際の場面では●●●●●になります。
クリック(clickメソッド)
送信ボタン
1 2 3 4 5 6 7 | 'type属性がsubmitでname属性値が送信だったらクリックする例 For Each element In objIE.document.getElementsByName("送信") 'nameが送信を探す If element.getAttribute("type") = "submit" Then 'typeがsubmitだったら element.Click 'クリックする Exit For End If Next |
ラジオボタン
男<input type=”radio” name=”gender” value=”male”>
女<input type=”radio” name=”gender” value=”female”>
1 2 3 4 5 6 7 | '男にチェックをする For Each element In objIE.document.getElementsByTagName("input") If element.Value = "male" Then element.Click Exit For End If Next |
【結果】 男 女←みたいな感じで選択します。
1 2 3 4 5 6 7 | '女にチェックをする For Each element In objIE.document.getElementsByTagName("input") If element.Value = "female" Then element.Click Exit For End If Next |
【結果】 男 女←みたいな感じで選択します。
1 2 | '男にチェックをする objIE.document.getElementsByName("gender")(0).Click |
【結果】 男 女←みたいな感じで選択します。
1 2 | '女にチェックをする objIE.document.getElementsByName("gender")(1).Click |
【結果】 男 女←みたいな感じで選択します。
チェックボックス
1 2 3 4 5 6 7 | 'バナナにチェックをする For Each element In objIE.document.getElementsByName("fruit") If element.Value = "banana" Then element.Click Exit For End If Next |
【結果】 りんご バナナ みかん ←みたいな感じで選択します。
1 2 | 'みかんにチェックをする objIE.document.getElementsByName("fruit")(2).Click |
【結果】 りんご バナナ みかん ←みたいな感じで選択します。
1 2 3 4 5 6 | '全てにチェックする② Dim aryFruit(2) As Variant '←の配列数だけ変えればOK Dim aryNum As Integer For aryNum = LBound(aryFruit) To UBound(aryFruit) objIE.document.getElementsByName("fruit")(aryNum).Click Next |
【結果】 りんご バナナ みかん ←みたいな感じで選択します。
今回ご紹介した取得、書込み、クリック方法は一例で、まだまだ沢山やり方が存在します。ですので実際の場面ではHTMLの中身によって柔軟に対応すればいいかと思います。
どのサンプルコードがよいのかというのは特別ないので、ご自身の得意となる方法を発見していろいろ試してみてくださいねヾ ^_^♪
サイトが表示されるまで待つ
サイトの読み込みが完了しないときちんとした情報が取得できないので、下記の二つのプロパティのうちどちらかで読込待ちをします。
・busyプロパティ
・readyStateプロパティ
busyプロパティ
true : 読込中
false : 読込完了
【使用例】(trueの間は読込待ちをする例)
1 2 3 4 | '読み込み待ち Do DoEvents Loop While objIE.Busy |
readyStateプロパティ
状態 | 値 | 詳細 |
READYSTATE_COMPLETE | 4 | 読込完了 |
READYSTATE_INTERACTIVE | 3 | インタラクティブ |
READYSTATE_LOADED | 2 | 初期化 |
READYSTATE_LOADING | 1 | 読込中 |
READYSTATE_UNINITIALIZED | 0 | デフォルトの初期化状態 |
【使用例】(読込中は読込待ちをする例)
1 2 3 4 | '読み込み待ち Do DoEvents Loop While objIE.readyState = READYSTATE_LOADING |
時間指定で待機する
時間指定で読み込み待ちしたい場合は、下記のメソッドで待機できます。
その他の取得プロパティ
【使用例】(リンクを全取得とjavascriptを全取得する例)
1 2 3 4 5 6 7 8 9 | 'リンクを取得 For Each obj In objIE.Document.Links Debug.Print obj.outerHTML Next 'javascriptを取得 For Each obj In objIE.Document.Scripts Debug.Print obj.outerHTML Next |
サーバーにhttpリクエストでスクレイピング
下記のようにIEオブジェクトを使用せずにもスクレイピングが可能です。
MSXML2ライブラリーのXMLHTTP60オブジェクトを使用して、サーバーに直接httpリクエスト(要求)を送信することで、IEを開かなくてもHTMLテキストを読み込むことができます。
サーバーからのresponseTextはHTMLテキストのままなので、HTMLDocumentオブジェクトを作成してDOMツリー操作をできるようにします。
実行する場合は下記2つを参照設定します。
ツール → 参照設定
参照設定が終わったら下記をコピペして早速試してみましょう(^^♪
IEオブジェクトを作成するよりはるかにスピードが速いのが特徴です!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | Option Explicit Const URL As String = "https://dailyrecords.blog" 'URLを記述します Sub httpTest() Dim objHttp As New MSXML2.XMLHTTP60 Dim objDoc As New MSHTML.HTMLDocument Dim element As MSHTML.IHTMLElement 'サーバーにHTTPリクエスト送信 objHttp.Open "GET", URL, False objHttp.send '読込待ち Do DoEvents Loop While objHttp.Status <> 200 'DOM操作をできるようにする objDoc.body.outerHTML = objHttp.responseText 'pタグの文字のみを抜き出す For Each element In objDoc.getElementsByTagName("p") Debug.Print element.outerText Next 'オブジェクト変数解除 Set objHttp = Nothing Set objDoc = Nothing End Sub |
まとめ
スクレイピングはHTMLも若干理解が必要ですが、慣れればそんなに難しくないので、挫折しないように少しずつ覚えていきましょう!
以上です。