VBAでブラウザを操作して自動化ツールを作ってみよう -ウェブスクレイピングツール編①-の続きとなります。
今回からは、実際に対象ページの操作を行います。
多少HTMLの知識も必要になりますので、本文を読まれる前に基礎的な内容は理解しておくことをおすすめします。
操作対象ページのソースを確認する
操作対象のページを開いて下さい。(https://tabelog.com/tokyo/)
ページ上で右クリックを行い、「ソースの表示」をクリックします。すると、以下のウィンドウが表示されます。
おぉ・・・これは初めて知った(笑)見えない所も凝ってていいですね!
昔流行りましたよね。遊び心があってこういうの好きです。
話は戻りますが、今回取得するデータは「店舗名」、「料理種別」、「検索キーワード」の3つです。
実際に表示されているページを確認してみると、以下の様にお店ごとにブロックで区切られていることが分かると思います。
これを目安に、HTMLソース上でもどの範囲が1つのブロックになっているのか調べてみましょう。探すコツは「ブロックの境目に共通して出現しているタグ」を探すことです。「divやlist、struct」といったタグが使用されている場合が多いです。
ブロック要素を取得する
今回のページでは、この「li」タグでお店の情報が分けられている様ですね。各店舗のデータはこの<li>~</li>の範囲内に含まれていますので、liごとにデータを分割しましょう。
まずは前回までのVBAに以下の変数宣言を追加します。
・Dim objListItemTags As Object
・Dim objListItem As Object
次に、IE遷移待機処理の後に以下のコードを記述します。
・Set objListItemTags = objIE.document.getElementsByTagName(“li”)
・For Each objListItem In objListItemTags
・Next
現時点で以下のソースになっていれば問題ありません。
Sub main() Dim objIE As InternetExplorer ‘IEオブジェクト Dim objListItemTags As Object ‘全liタグを格納するオブジェクト Dim objListItem As Object ‘抽出したliタグを格納するオブジェクト ‘IEの起動 Set objIE = CreateObject(“InternetExplorer.Application”) objIE.Visible = True objIE.Navigate2 “https://tabelog.com/tokyo/” ‘遷移処理待機 Do While objIE.Busy Or objIE.readyState <> READYSTATE_COMPLETE DoEvents Loop Set objListItemTags = objIE.document.getElementsByTagName(“li”) For Each objListItem In objListItemTags Next End Sub |
目的はまず「li」タグごとにデータを分けて扱うことですので、「getElementsByTagName」メソッドを使用して抽出した全ての「li」タグデータを「objListItemTags」に格納します。
「objListItemTags」には<li>~</li>の範囲で区切られたデータが、要素ごとのコレクションとして格納されています。これを、For~Eachを使って一範囲ずつ操作していきます。
目的のブロックを判別する
さて、<li>~</li>タグごとに抽出はできましたが、店舗データが含まれているものかどうかはどうやって判断すれば良いでしょうか。HTMLソースに戻り、タグの内容をもう一度確認してみましょう。
<li>タグ内に「class」、「data-detail-url」、「data-rst-id」といった要素が含まれているのが分かると思います。
「data-rst-id」は食べログ上でお店ごとに割り振られているID番号だと思いますので、この番号で調べてもそのお店かどうかしか判定できません。「data-detail-url」も同様ですね。
「class」の内容を見ると、どのお店の<li>タグにも同じ内容が設定されています。このクラスが設定されているものが店舗情報が記載されているブロックだとみて良いでしょう。では早速判定処理を書いていきます。
以下の変数宣言を追加して下さい。
・Dim className As String
For Each ~ Next内に以下の処理を記述して下さい。
For Each objListItem In objListItemTags ‘クラス名の取得 className = “” On Error Resume Next className = objListItem.className On Error GoTo 0 ‘クラス名が一致した場合にデータ取得処理を行う If Instr(className, “list-rst is-blocklink js-bookmark js-open-newtab-rd”) > 0 Then End If Next |
まずはclassNameの値を初期化します。続いて「objListItem.className」と記述してクラス名の値を格納します。(id要素であれば「.id」、nameは「.name」といった形で、そのタグに記載されている様々な要素の値を取得することができます。)
クラス名を取得する処理の前後に「On Error」とありますが、これはクラス名取得の際に発生したエラーを無視するためのものです。
クラス名は必ず記載されているものではありません。「class」要素の無いものに「.className」を使用すると、エラーが出て処理が止まってしまいます。そのエラーをあえて無視するために「On Error~」処理を記述しています。
最後にクラス名の判定を行っています。指定したクラス名に一致した場合のみ、処理を行う様にしています。
次はいよいよ目的のデータ取得を行います。
ここまでの技術を応用すれば完成させることができますので、「答えを見ずにやってみたい!」という方はぜひ挑戦してみて下さい。