VBAプログラム開発、スクレイピング【2】表示ページの対象データを取得する
VBAスクレイピングの準備ができましたので、指定したサイトのページ内の書籍情報を取得できるようにします。
まずは、表示したページ内の情報を取得します。
今回の目的
スクレイピングにより関連する全データを取得し、保存できるようにする
なぜやるか
データ取得方法を学習し、様々なデータ取得への足がかりとする。
表示だけでなく保存できる形式にし、多方面で扱えるデータ準備ができるようにする。
やりたいこと
やったこと
- Debug.Printによる結果表示をする
- For Eachによる要素処理を行う
- ワークシートにスクレイピングデータを表示する
- ワークシートに取得データを全て表示する
実施内容
データを確認しつつ、処理を変更する
前回は、まずスクレイピングできていることを確認しました。
# test
Sub test()
Dim objIE As InternetExplorer
Set objIE = CreateObject("Internetexplorer.Application")
objIE.Visible = True
objIE.navigate "https://protected-fortress-61913.herokuapp.com/book"
Call WaitResponse(objIE)
Dim htmlDoc As HTMLDocument
Set htmlDoc = objIE.document
MsgBox htmlDoc.getElementsByClassName("list-book-title")(0).innerHTML
End Sub
Sub WaitResponse(objIE As Object)
Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE
DoEvents
Loop
End Sub
タイトル名を1件取得して画面表示する…ところまでを実施していました。
今回は同じサイトのタイトルを全て取得してデータとして扱える様にします。
デバッグによるデータ情報を表示させる
前回のデータ取得結果はダイアログボックスに表示していました。
しかし、毎回この画面で表示確認しOKボタンを押す…のも面倒になるので、取得データの表示箇所を変更します。
MsgBox記述からDebug.Printに変更しました。
'MsgBox htmlDoc.getElementsByClassName("list-book-title")(0).innerHTML
↓
Debug.Print htmlDoc.getElementsByClassName("list-book-title")(0).innerHTML
こちらでVBAを実行すると、VBE内のイミディエイトに結果が表示されるようになります。
デバッグ時の変数内データ確認には有効な方法です。
全タイトルを取得する
いままでは1件のタイトルのみを取得していたので、表示ページの全タイトルが取得できるように対応させます。
Debug.Print htmlDoc.getElementsByClassName("list-book-title")(0).innerHTML
"list-book-title"に対して(0)指定でいままではデータを取得していました。取得データの0番目…つまりは初めのデータだけを取得していました。
0番目を削除することで、全データを対象にします。
Debug.Print htmlDoc.getElementsByClassName("list-book-title").innerHTML
0を削除することで、取得データ自体は"list-book-title"クラスの全データとなります。しかし、これでは同じクラスの全てのデータを取得することになります。
全データに対してinnerHTML指定はできず、エラーとなりました。
要素毎に出力する
1件のみ指定することでタイトル名は出力できていたので、複数の要素が含まれたオブジェクト…配列のような物ととらえ、順番にデータをとりだすことによって値を表示することにしました。
Dim Str As Object
For Each Str In htmlDoc.getElementsByClassName("list-book-title")
Debug.Print "出力:" & Str.innerHTML
Next Str
For Eachによって要素を順番に取り出して処理をおこなう形にしました。
htmlDoc.getElementsByClassName("list-book-title")
こちらが、"list-book-title"クラス名のHTMLオブジェクトを取得していました。この要素を一つずつStrというオブジェクト変数に格納しています。
そして、Debug.PrintにてStr.innerHTMLとしてイミディエイトへ出力します。
これでHTMLとして取得したオブジェクト全体から対象クラスのテキストが取得できました。
取得データをワークシートに表示する
データ取得は行えるようになりましたが、現状ではデバッグ用のテキスト表示のみであり、実際にデータ保存して他に利用するまでには至っていません。
今回はExcelのワークシートにタイトル名を表示させることで保存出来るようにします。
データ出力用ワークシートを準備する
単純ですが、番号とタイトルを記載できるようにしておき、こちらにスクレイピングしたタイトル名を反映させます。
内容が分かるように予め1行目にヘッダとして名前を記載しました。この下にスクレイピングしたタイトル名と取得した順序として番号を表示させます。
ワークシートにスクレイピングデータを表示する
Debug.Print htmlDoc.getElementsByClassName("list-book-title")(0).innerHTML
タイトル名を1件のみ取得していた時は、Debug.Printとして0番目の要素を指定していました。
ここからデバッグではなく、ワークシートに保存できるようにします。
Cells(2, 2).Value =
htmlDoc.getElementsByClassName("list-book-title")(0).innerHTML
デバッグから、テキスト表示先となるセル番地を指定する形にしました。
イミディエイトに表示していたテキストがワークシート上に表示されました。
全件のタイトル名をワークシートに表示させる
ここまでくれば、後は繰り返す手順を使えば順番に表示できそうです。
先程、イミディエイト出力で全データを繰り返して表示していました。
Dim Str As Object
For Each Str In htmlDoc.getElementsByClassName("list-book-title")
Debug.Print "出力:" & Str.innerHTML
Next Str
こちらの出力先をワークシートにし、なおかつ順番にセルを変更して表示できれば作成できそうです。
オブジェクト要素を順番に取り出し、ワークシートへ反映できるようにします。
Dim Str As Object
Dim i As Integer
i = 1
For Each Str In htmlDoc.getElementsByClassName("list-book-title")
Worksheets("スクレイピング").Cells(i + 1, 1).Value = i
Worksheets("スクレイピング").Cells(i + 1, 2).Value = Str.innerHTML
i = i + 1
Next Str
For Eachを利用して順番に要素を取り出し、表示先をセル番地指定して出力する形に変更しました。
予め番号を宣言しておき、データ出力後にi+1することで、次のデータは次の行へ移動します。
こうすることによって、連続するデータが順番にワークシート上に表示されます。
通し番号を表示する為に、併せてA列に番号をそのまま表示できるようにしました。
対象サイトからタイトル名だけを取得して、Excelで一覧表示できるようになりました。
次は、もう少し他の情報も扱えるようにしていきます。