VBAプログラム開発、スクレイピング・データ要素を充実させる【3】書籍詳細ページからテキストデータを収集する
詳細ページURLの収集が完了し、専用ワークシートに集約ができました。
今回は、詳細ページから必要な情報を取得できるようにします。
必要な情報が取得出来るようになれば、集約したURLと組み合わせることで、全情報の詳細情報を一度に収集できるようになる…という流れです。
今回の目的
詳細ページから必要な情報を収集し、ワークシートに表示する
なぜやるか
- 詳細ページからデータ取得をできるようにすることで、より多くの情報をExcelワークシートへ保存できるようにするため
- 保存した情報を全URLに対応させる為の準備として作成するため
やりたいこと
- 詳細ページのHTMLから必要な情報を確認する
- 欲しいテキストデータを取得する
やったこと
- HTML表示を確認する
- テキストデータを取得する
実施内容
詳細ページのデータを入手する
HTMLから取得情報を確認する
詳細ページURLは取得できたので、詳細ページからの情報を取得できるようにします。
まずは、詳細ページでのHTML要素を確認して、何をどう取得するかを確認していきます。
左側に画像、右側にテキストが並んでいます。
この情報を全て取得してExcelワークシートで保存できるようにします。
# HTML
<div class="books-list">
<div class="books-list__title bookpage-color">詳細</div>
<div class="book-detail">
<div class="book-detail__picture">
<img src="https://cover.openbd.jp/9784797398892.jpg">
</div>
<div class="book-detail__document">
<h3 class="document-index">書籍情報</h3>
<div class="document-content">
<div class="document-content__label">タイトル</div>
<div class="document-content__column">
1冊ですべて身につくHTML & CSSとWebデザイン入門講座
</div>
</div>
<div class="document-content">
<div class="document-content__label">シリーズ</div>
<div class="document-content__column"></div>
</div>
<div class="document-content">
<div class="document-content__label">ISBN</div>
<div class="document-content__column">9784797398892</div>
</div>
<div class="document-content">
<div class="document-content__label">著者名</div>
<div class="document-content__column">Mana/著</div>
</div>
<div class="document-content">
<div class="document-content__label">出版社</div>
<div class="document-content__column">SBクリエイティブ</div>
</div>
<div class="document-content">
<div class="document-content__label">出版日</div>
<div class="document-content__column">20190318</div>
</div>
<div class="document-content">
<div class="document-content__label">登録日</div>
<div class="document-content__column">2019-05-19 18:40:40</div>
</div>
<div class="document-content">
<div class="document-content__label">編集日</div>
<div class="document-content__column">2019-05-19 18:40:40</div>
</div>
<h4 class="document-index">書籍詳細</h4>
<div class="document-content">
<div class="document-content__column">
日本で2年間グラフィックデザイナーとして働いた後...
</div>
</div>
</div>
</div>
</div>
ビュー画面部分のHTMLです。(一部省略)
"book-detail"配下に全ての情報が入っています。
さらに細かくみると、book-detail__picture内に画像があり、book-detail__document内のdocument-contentとして各テキスト要素が入っています。
今までは書籍一覧からこういった情報を取得していましたが、今回はこちらの情報を取得できるようにします。
データ取得は書籍一覧で取得した方法と同じです。クラス名の指定が変わってくるので、上記のHTMLにあわせていきます。
テキストデータを取得する
まずは、テキストデータのみを取得します。
詳細ページURLまで取得した後に続く処理をcallで呼び出せるようにして、詳細ページ取得のVBAを新規追加します。
# Sub getBookdatasDatail() [URL取得後]
'取得した詳細ページURLから詳細ページ情報を取得する
Call getDetailBookdata(SWSheet, DWSheet, objIE)
# 詳細ページデータ取得用の新しいプロシージャ
Sub getDetailBookdata(SWSheet As Worksheet, DWSheet As Worksheet, _
objIE As InternetExplorer)
'詳細ページURLから詳細内容を取得
'データ取得URL
Dim OpenPage As String
Dim htmlDoc As HTMLDocument 'HTML全体
Dim DocContent As HTMLDivElement 'HTMLコンテンツ処理
Dim i As Long
Dim DocLavel As HTMLDivElement 'ラベル情報
Dim DocColumn As HTMLDivElementt 'column情報
i = 1
'詳細ページを開いて中のデータを取得
'テスト用に最初のURLだけ実施
OpenPage = DWSheet.Cells(1, 1).Value
objIE.navigate OpenPage 'IEでURLを開く
Call WaitResponse(objIE) '読み込み待ち
Set htmlDoc = objIE.document 'objIEで読み込まれているHTMLドキュメントをセット
'詳細ページHTMLからデータ取得
'document-contentを取得
For Each DocContent In htmlDoc.getElementsByClassName("document-content")
SWSheet.Cells(i, 1).Value = DocContent.innerHTML
Set DocLavel = DocContent.getElementsByClassName("document-content__label")(0)
Set DocColumn = DocContent.getElementsByClassName("document-content__column")(0)
If i <> 9 Then SWSheet.Cells(i, 2).Value = DocLavel.innerHTML
SWSheet.Cells(i, 3).Value = DocColumn.innerHTML
i = i + 1
Next DocContent
'詳細ページURL全取得で終了
End Sub
動作確認がまず必要と考えていたので、取得しているURLの1件目のみを対象としました。
取得済みの詳細ページURLから対象のページを開いて取得するテキスト要素が入っていたdocument-contentをForEachによる繰り返しで取得しました。
全て同じクラス名で設定しているので、これで全データ取得ができます。
1列目に取得したHTML全体、2列目と3列目にはdocument-content内の各クラスを取得しました。
まずはこれでワークシートに表示してみました。
詳細ページのHTMLから指定したデータが取得できました。
ポイントとしては、最後9行目の詳細テキストについては、ラベルという名前のクラスがない為、そのまま全部書き出そうとするとエラーとなりました。
そのため、If i <> 9 Thenとして9行目だけラベル出力をしないようにしました。データ出力の一時確認用でしたので、エラーを回避する為に記載しました。※後に削除するので暫定対処
レコード単位化する
データを取得して表示できることを確認しました。
ところで、最終的に表示させたい表のイメージはこちらです。
この図は一覧表示のデータを取得した時のものですが、この表のイメージで詳細ページの全データを取得しようとしています。
つまり、詳細ページで取得した情報で欲しいのは3列目に表示された、書籍情報だけです。
HTMLやラベルは不要です。そして、データの表示方向も異なっているので、修正します。
# 詳細ページデータ取得(主な変更点のみ抜粋)
Sub getDetailBookdata(SWSheet As Worksheet, DWSheet As Worksheet, _
objIE As InternetExplorer)
Dim j As Long '列処理
j = 1 '列方向初期値をセット
'詳細ページHTMLからデータ取得
'document-contentを取得
For Each DocContent In htmlDoc.getElementsByClassName("document-content")
Set DocColumn = DocContent.getElementsByClassName("document-content__column")(0)
SWSheet.Cells(2, j).Value = DocColumn.innerText
j = j + 1
Next DocContent
'詳細ページURL全取得で終了
End Sub
行方向ではなく、列方向へとデータを展開するのでiからjに変更しました。iのままでも使えますが、後ほど行方向も必要となるので、変更しています。
そして、表示の必要がないHTMLとラベル名は削除しました。
出力チェック用の為、対象となる詳細ページURLは1件のままになっています。
これで出力を確認します。
レコードを意識した出力となりました。
一覧表示データから出力していたのは、画像・タイトル・詳細テキストだけでしたが、著者名や出版日などにも対応できるようになりました。
出力が確認できたので、テスト用の1件表示から全件対応にすれば、全書籍の詳細データを取得する形にだいぶ近づきます。
次の記事で全件対応化をする予定です。