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

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

VBAプログラム開発、スクレイピング・データ要素を充実させる【3】書籍詳細ページからテキストデータを収集する

詳細ページURLの収集が完了し、専用ワークシートに集約ができました。

今回は、詳細ページから必要な情報を取得できるようにします。

必要な情報が取得出来るようになれば、集約したURLと組み合わせることで、全情報の詳細情報を一度に収集できるようになる…という流れです。

今回の目的

詳細ページから必要な情報を収集し、ワークシートに表示する

なぜやるか

  • 詳細ページからデータ取得をできるようにすることで、より多くの情報をExcelワークシートへ保存できるようにするため
  • 保存した情報を全URLに対応させる為の準備として作成するため

やりたいこと

  • 詳細ページのHTMLから必要な情報を確認する
  • 欲しいテキストデータを取得する

やったこと

  • HTML表示を確認する
  • テキストデータを取得する

実施内容

詳細ページのデータを入手する

HTMLから取得情報を確認する

詳細ページURLは取得できたので、詳細ページからの情報を取得できるようにします。

まずは、詳細ページでのHTML要素を確認して、何をどう取得するかを確認していきます。

f:id:Fippiy:20190615144647j:plain

詳細ページビュー

左側に画像、右側にテキストが並んでいます。

この情報を全て取得して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 &amp; 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内の各クラスを取得しました。

まずはこれでワークシートに表示してみました。

f:id:Fippiy:20190618093752j:plain

詳細情報取得

詳細ページのHTMLから指定したデータが取得できました。

ポイントとしては、最後9行目の詳細テキストについては、ラベルという名前のクラスがない為、そのまま全部書き出そうとするとエラーとなりました。

そのため、If i <> 9 Thenとして9行目だけラベル出力をしないようにしました。データ出力の一時確認用でしたので、エラーを回避する為に記載しました。※後に削除するので暫定対処

 

レコード単位化する

データを取得して表示できることを確認しました。

ところで、最終的に表示させたい表のイメージはこちらです。

f:id:Fippiy:20190615105002j:plain

一覧情報から取得していたワークシート

この図は一覧表示のデータを取得した時のものですが、この表のイメージで詳細ページの全データを取得しようとしています。

つまり、詳細ページで取得した情報で欲しいのは3列目に表示された、書籍情報だけです。

f:id:Fippiy:20190618093752j:plain

詳細情報取得

 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件のままになっています。

これで出力を確認します。

f:id:Fippiy:20190618102952j:plain

詳細ページデータ出力

レコードを意識した出力となりました。

一覧表示データから出力していたのは、画像・タイトル・詳細テキストだけでしたが、著者名や出版日などにも対応できるようになりました。

 

出力が確認できたので、テスト用の1件表示から全件対応にすれば、全書籍の詳細データを取得する形にだいぶ近づきます。

 

次の記事で全件対応化をする予定です。