Fippiyのプログラム学習内容アウトプットBlog

日々の学習内容をアウトプットして振り返りを実施する。

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件取得して画面表示する…ところまでを実施していました。

今回は同じサイトのタイトルを全て取得してデータとして扱える様にします。

 

デバッグによるデータ情報を表示させる

前回のデータ取得結果はダイアログボックスに表示していました。

f:id:Fippiy:20190603174513p:plain

メッセージボックス

しかし、毎回この画面で表示確認しOKボタンを押す…のも面倒になるので、取得データの表示箇所を変更します。

MsgBox記述からDebug.Printに変更しました。

 

 'MsgBox htmlDoc.getElementsByClassName("list-book-title")(0).innerHTML
 ↓

 Debug.Print htmlDoc.getElementsByClassName("list-book-title")(0).innerHTML

こちらでVBAを実行すると、VBE内のイミディエイトに結果が表示されるようになります。

f:id:Fippiy:20190604143914j:plain

イミディエイト

 デバッグ時の変数内データ確認には有効な方法です。

 

全タイトルを取得する

いままでは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指定はできず、エラーとなりました。

f:id:Fippiy:20190604145108j:plain

エラー
要素毎に出力する

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としてイミディエイトへ出力します。

f:id:Fippiy:20190604145720j:plain

複数要素取得

これでHTMLとして取得したオブジェクト全体から対象クラスのテキストが取得できました。

 

取得データをワークシートに表示する

データ取得は行えるようになりましたが、現状ではデバッグ用のテキスト表示のみであり、実際にデータ保存して他に利用するまでには至っていません。

今回はExcelのワークシートにタイトル名を表示させることで保存出来るようにします。

データ出力用ワークシートを準備する

f:id:Fippiy:20190604150322j:plain

ワークシート

単純ですが、番号とタイトルを記載できるようにしておき、こちらにスクレイピングしたタイトル名を反映させます。

内容が分かるように予め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

デバッグから、テキスト表示先となるセル番地を指定する形にしました。

 

f:id:Fippiy:20190604150501j:plain

1件のスクレイピング

イミディエイトに表示していたテキストがワークシート上に表示されました。

 

全件のタイトル名をワークシートに表示させる

ここまでくれば、後は繰り返す手順を使えば順番に表示できそうです。

先程、イミディエイト出力で全データを繰り返して表示していました。

 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列に番号をそのまま表示できるようにしました。

f:id:Fippiy:20190604151439j:plain

スクレイピング結果

対象サイトからタイトル名だけを取得して、Excelで一覧表示できるようになりました。

 

次は、もう少し他の情報も扱えるようにしていきます。