VBAでブラウザを操作して作業を自動化してみよう -ウェブスクレイピングツール編③-


< 前回の記事

今回で初回のウェブスクレイピングツール編は最後になります。

前回から自分自身で作り上げたという方はぜひ答え合わせをして見て下さい。プログラミング全般に言えることですが、実装の方法は一つではありません。最初の内は動けばそれで良いと思います。

店舗名、料理種別を取得する

サイトのHTMLソースを確認して下さい。

前回店舗のデータが含まれている「li」タグ内のブロックを見つけましたが、今度は店舗名が記載されているタグを見つけましょう。

はい、ありました。

どうやら店舗名は<a>タグ、料理種別は<span>タグでそれぞれ囲まれている様です。それでは前回と同じ要領で目的のタグを取得していきましょう。

前回までのコードに、以下の変数宣言を追加して下さい。

Dim objAnchorTags As Object
Dim objAnchor As Object
Dim sRestaurantName As String
Dim sFoodKind As String
Dim sKeyword As String

IF判定の処理の中に、「li」タグを取得した以下の処理を記述します。

Set objAnchorTags = objListItem.getElementsByTagName(“a”)
For Each objAnchor In objAnchorTags
    sClassName = “”
    On Error Resume Next
    sClassName = objAnchor.className
    On Error GoTo 0
Next

If InStr(sClassName, “list-rst__rst-name-target cpy-rst-name”) > 0 Then
    sRestaurantName = Trim(objAnchor.innerText)
End If

うーん・・・似たようなコードを何度も書きたくないですね。無駄に長くなって非常に見辛い。関数化しても良いんですが、この店舗名と種別の表示はそれぞれブロックの一番上にありますよね。

じゃあこうしましょう。

sRestaurantName = Trim(objListItem.getElementsByTagName(“a”)(0).innerText)

これは上に書いたループの処理と全く同じ結果を返します。出てくる場所が決まっているのであれば、(n)※n=任意の番号と指定することで○番目のデータの値をこの1行で取得することが可能です。

「タグがたくさんあって、何番目に出てくるか分からない」「レイアウトの仕様が頻繁に変更される」といった場合は頻繁にメンテナンスしなければいけませんので、この方法は使わない様にしましょう。

 
 
この方法を用いて料理種別の値も取得しましょう。

sFoodKind = Trim(objListItem.getElementsByTagName(“span”)(0).innerText)

これで完了です。ブレークポイントを指定するなどして、値が取れているか確認してみましょう。

検索キーワードの取得

検索キーワードの場所を確認しましょう。

ありましたね。

「li」タグにちゃんと検索キーワードだと識別できる様なクラス名が設定されているので、そのまま「li」タグを抽出 ⇒ class名判定で取得という流れで良いと思います。

ではいつも通りキーワードのタグを取得するための変数宣言を行います。

Dim objLIChildTags As Object
Dim objLIChild As Object

以前宣言した「objListItemTags」、「objListItem」も統一するために名前を変えておくと良いかもしれません。

検索キーワード取得の処理を以下の様に記述して下さい。

Set objLIChildTags = objLI.getElementsByTagName(“li”)
For Each objLIChild In objLIChildTags
    sClassName = “”
    On Error Resume Next
    sClassName = objLIChild.className
    On Error GoTo 0
    
    ‘キーワードはカンマ区切りで格納
    If InStr(sClassName, “list-rst__search-word-item”) > 0 Then
        sKeyword = IIf(sKeyword = “”, Trim(objLIChild.innerText), _
                        sKeyword & “,” & Trim(objLIChild.innerText))
    End If
Next

※IIfとは

追加し終わったらブレークポイントを設定し、正しく取得できているかどうかを確認してみましょう。

データの貼り付け

後はデータをシート上に貼り付けるだけです。

貼り付け行を管理する変数「lRow」を宣言し、以下の処理をIF内の最後の部分に記述しましょう。

Cells(lRow, 1).Value = sRestaurantName
Cells(lRow, 2).Value = sFoodKind
Cells(lRow, 3).Value = sKeyword
lRow = lRow + 1

念のため、IF文の最初の箇所に各変数の初期化処理も書いておきましょう。

 
 
お疲れ様でした!これでスクレイピングツールは無事完成のはずです。

実行してみると以下の様にエクセル上にデータが出力されると思います。

構成は違えど考え方は一緒ですので、ぜひご自身のサイトなどで試してみて下さい。

また、今回は全ての処理を一つの関数内に書きましたが、何度も使う様な処理は共通化する癖をつけると後々役立つと思います。

次回のツールではデータ取得だけではなく、フォームへの入力、ボタン押下といった処理も行ってみたいと思います。

今回のコード

参考までに今回のVBAコードを記載します。

Option Explicit

Const READYSTATE_COMPLETE = 4
Const ROW_RESTAURANT_NAME = 1
Const ROW_FOOD_KIND = 2
Const ROW_SEARCH_KEYWORD = 3

Sub main()
    Dim objIE As InternetExplorer   ‘IEオブジェクト
    Dim objLITags As Object         ‘全liタグを格納するオブジェクト
    Dim objLI As Object             ‘抽出したliタグを格納するオブジェクト
    Dim objLIChildTags As Object
    Dim objLIChild As Object
    
    Dim sClassName As String        ‘クラス名を格納
    Dim sRestaurantName As String   ‘店名
    Dim sFoodKind As String         ‘料理種別
    Dim sKeyword As String          ‘特徴(検索キーワード)
    Dim lRow As Long                ‘行カウンタ
    
    lRow = 1
    
    ‘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 objLITags = objIE.document.getElementsByTagName(“li”)
    For Each objLI In objLITags
        ‘クラス名の取得
        sClassName = “”
        On Error Resume Next
        sClassName = objLI.className
        On Error GoTo 0
        
        ‘指定のクラス名が含まれていた場合にデータ取得処理を行う
        If InStr(sClassName, “list-rst is-blocklink js-bookmark js-open-newtab-rd”) > 0 Then
            sRestaurantName = “”
            sFoodKind = “”
            sKeyword = “”
            
            ‘店舗名を取得
            sRestaurantName = Trim(objLI.getElementsByTagName(“a”)(0).innerText)
            
            ‘料理種別を取得
            sFoodKind = Trim(objLI.getElementsByTagName(“span”)(0).innerText)
            
            ‘検索キーワードを取得
            Set objLIChildTags = objLI.getElementsByTagName(“li”)
            For Each objLIChild In objLIChildTags
                sClassName = “”
                On Error Resume Next
                sClassName = objLIChild.className
                On Error GoTo 0
                
                ‘キーワードはカンマ区切りで格納
                If InStr(sClassName, “list-rst__search-word-item”) > 0 Then
                    sKeyword = IIf(sKeyword = “”, Trim(objLIChild.innerText), _
                                    sKeyword & “,” & Trim(objLIChild.innerText))
                End If
            Next
            
            ‘シート上に出力
            Cells(lRow, ROW_RESTAURANT_NAME).Value = sRestaurantName
            Cells(lRow, ROW_FOOD_KIND).Value = sFoodKind
            Cells(lRow, ROW_SEARCH_KEYWORD).Value = sKeyword
            lRow = lRow + 1
        End If
    Next
End Sub

※食べログサイトの仕様変更などにより、そのままコピーしても使用出来ない場合があります。その場合は現在のサイトを参考に適宜修正を行って下さい。

関連記事と広告

シェアする

  • このエントリーをはてなブックマークに追加

フォローする