適材適所

パソコン作業の自動化・効率化のための情報を発信するブログ(VBA,PowerShellなど)

WinHTTPとVBAでウェブサイトのリンク一覧を取得する

この記事では

WinHTTPでスクレイピングしてリンクのURL一覧を作ってみる

その3ではWinHTTPを使うためのHTTPの説明をしました。 今回からWinHTTPの実践的な使い方に入っていきたいと思います。

スクレイピングの目的は色々ありますが、いくつかこんなことができるよ的なサンプルを作っていきたいと思います。

その第一段として「WinHTTPを使って対象のページ上のリンク一覧をワークシートに書き出す」というものを作ってみようと思います(そんな需要はあるかわかりませんが・・・)。

次のコードを実行すると、「url」変数に指定されたウェブページにあるリンクの文字列とリンク先URLをアクティブなシートに出力します。

コード

実行前に参照設定を行います。
Microsoft WinHTTP Services, version○
Microsoft HTML Object Library

Sub WinHTTP_Sample()
   Dim req As WinHttp.WinHttpRequest: Set req = New WinHttp.WinHttpRequest
   Dim url As String:url = "https://www.yahoo.co.jp/"
   req.Open "GET", url
   req.Send

   If req.Status <> 200 Then
      MsgBox "レスポンスエラー"
      Exit Sub
   End If

   Dim html As Object: Set html = New HTMLDocument
   html.Write req.ResponseText
   Dim wrtRow As Long: wrtRow = 1
   Dim a As HTMLAnchorElement
   For Each a In html.getElementsByTagName("a")
      Cells(wrtRow, 1).Value = a.innerText
      Cells(wrtRow, 2).Value = a.href
      wrtRow = wrtRow + 1
   Next a

End Sub

コードの解説

2行目の

   Dim req As WinHttp.WinHttpRequest: Set req = New WinHttp.WinHttpRequest

は「req」という変数名でオブジェクトを準備しています。参照設定を行っているので、データ型をそのまま指定できます。

4行目

   req.Open "GET", url

urlへのHTTP接続のための準備をするようなイメージでしょうか。 引数は3つあります。 1つ目は、HTTPの動詞です。GET や POSTがメインとなることでしょうか。 2つ目は、URLを指定します。 3つ目は、開き方の指定です。「同期」or「非同期」のどちらかです。
同期モードは、次の「Send」メソッド実行時にサーバからの応答を全部受信したら制御が戻ってきます。つまり通信の状態をこちら側で管理する必要がなくなります。
Falseが同期、Trueが非同期です。省略値はFalseの同期です。基本は省略値でいいと思います。

5行目

   req.Send

サーバに向けてリクエストを送信します。
引数はBodyです。POSTメソッドでパスワード等を送信する際に指定することができます。
Openのところで同期モードで設定したので、通信の制御は不要です。

7~10行目

   If req.Status <> 200 Then
      MsgBox "レスポンスエラー"
      Exit Sub
    End If

レスポンスコードを調べます。
レスポンスコードは正常の場合200です。
200以外の場合は処理を終了します。

12~13行目

   Dim html As Object: Set html = New HTMLDocument
   html.Write req.ResponseText

HttpRequest#ResponseTextプロパティに、生のHTMLが入っています。 今回は、これをHTMLDocumentにパースしてもらい、扱いやすくします。 生のHTMLを正規表現で抽出した方が処理は速いので、どちらを選択するかは要求されるもの次第になります。

HTMLDocumentの書き方はなぜこうなるのかはわからず・・・。

16~21行目

   For Each a In html.getElementsByTagName("a")
      Cells(wrtRow, 1).Value = a.innerText
      Cells(wrtRow, 2).Value = a.href
      wrtRow = wrtRow + 1
   Next a

aタグのテキストとaタグのhref(リンク先)をシートに出力してます。 getElementsByTagNameの使い方は下記記事で言及しています。

www.tekizai.net

おわりに

WinHTTPでリンクの一覧を取得するサンプルを作ってみました。 こんな感じでWinHTTPを使うことで、ブラウザに依存せずにスクレイピングをすることができます。

要求をオープンして送る。返ってきたものを処理する。これがWinHTTPでスクレイピングする際の基本形になります。 この基本さえ押さえてしまえば、あとはウェブページの動きを分析して処理を組み立てることができます。

次回もWinHTTPを使ったサンプルを作ってみたいと思います。

ここまでお読みいただき、ありがとうございました。

www.tekizai.net

参考サイト

IWinHttpRequest::Open method - Win32 apps | Microsoft Docs VBAでのHTMLDocument VBAでHTMLの解析をしたいと思っています。 … - 人力検索はてな