みなさんこんにちは、ZeroTerasu(@ZeroTerasu)です。
今回は、VBAのライブラリである「WinHTTP」および「XMLHTTP60」を用いたスクレイピング手法について解説していきます。VBAを用いたスクレイピング手法では、「Selenium Basic」または「IE」を用いたスクレイピングがポピュラーと思いますが、ブラウザを使用しない分高速処理が期待できるのではと思い、今回試してみました。
スクレイピングするサイト
今回は、私のブログサイトのトップページの中の全ての「<a>タグの”テキスト”」と 「<a>タグの”リンク先”」の情報を取得して、エクセルシートに書き込むというスクレイピングを実行しました。
取得する情報
取得情報元 |
ZeroTerasu Blog |
取得情報例 |
<a href=”https://zeroterasu.com/blog/” class=”site-name site-name-text-link” itemprop=”url”> |
取得する情報1 | <a>タグのインナーテキスト (上記の例では、「ZeroTerasu Blog」) |
取得する情報2 | <a>タグのインナー”href”属性値 (上記の例では、「https://zeroterasu.com/blog/」) |
取得場情報数 | 本記事作成時点では、<a>タグ「119」個分 |
結果比較
操作方法 | WinHTTP | XMLHTTP60 | SeleniumBasic | IE |
実行時間(秒) | 3.472222306 | 3.472222306 | 6.944443885 | 6.944444613 |
・「WinHTTP」と「XMLHTTP60」はChrome・IEの約2倍速い
・「WinHTTP」と「XMLHTTP60」は同じ速度
・SeleniumBasic(Chrome)とIEはほぼ同じ速度
・SeleniumBasic(Chrome)とIE は毎回実行速度に大きくバラツキがある。
上記4番目の補足になりますが、ChromeとIEそれぞれ何回か実行してみましたが、実行する度に動作速度が変わりました。そのため、実行環境によっては、どちらの方が早いかの優劣が変わってくるものと思われます。
(サーバー側の処理速度に起因していると考えています。サーバーにアクセスが集中しているなど、速度が著しく遅い場合は、時間を空けてトライすべきかと考えます。※スクレイピング自体、サーバーに大きな負荷を掛ける処理になりますので、実行時にはサーバー負荷に十分ご配慮下さい。)
以下では、それぞれのメリット・デメリットおよびコード解説に進みます。
WinHTTP・XMLHTTP60のメリット・デメリット
WinHTTP・XMLHTTP60のメリット・デメリットをChrome・IEと比較してまとめました。
メリット | デメリット | |
WinHTTP・XMLHTTP60 | 高速処理 | JavaScript等から生成されるコンテンツの読み込みが不可。 |
SeleniumBasic(Chrome)・IE | JavaScript等から生成されるコンテンツの読み込みが可能。 |
ブラウザを使用するため、処理が遅い。 |
取得対象の情報が、JavaScript等によって動的に生成される情報であれば、WinHTTP・XMLHTTP60は使用できません。
しかし、動的生成コンテンツ以外の情報であれば、ブラウザを使用するスクレイピング方法に比べて2倍以上のスピードが期待できそうです。
参照設定
下記のライブラリを参照設定に追加します。
追加方法は、「VBE」→「ツール(T)」→「参照設定(R)」から下記の名称を探してチェックマークにチェックを入れてください。
Microsoft WinHTTP Services, version 5.1(WinHTTP)
Microsoft XML, v6.0(XMLHTTP60)
Miocrosoft HTML Object Library(どちらの場合も使用します。)

コード
下記に今回使用したコードを掲載します。
「WinHTTP」と「XMLHTTP60」は、いずれもリクエスト結果をhtmlに書き込んだ後に、1秒間待機させています。(そのほかの待機方法も試してみましたが、この方法以外に成功例がありませんでした。)
ブラウザ(ChromeおよびIE)を使用した場合との結果比較のために、ブラウザを使用した場合のコードも掲載いたします。
Sub WinHTTP_Sample()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.ActiveSheet
Dim begTime As Variant: begTime = Now()
ws.Cells(1, 2) = Format(begTime, "yyyy/mm/dd hh:mm:ss")
Dim req As WinHttp.WinHttpRequest: Set req = New WinHttp.WinHttpRequest
Dim url As String: url = "https://zeroterasu.com/blog/"
req.Open "GET", url
req.Send
Dim html As IHTMLDocument: Set html = New HTMLDocument
html.write req.ResponseText
Application.Wait(Now() + TimeValue("00:00:01"))
Dim inputRow As Long: inputRow = 2
Dim a As HTMLAnchorElement
For Each a In html.getElementsByTagName("a")
If IsNull(a.innerText) Then
Debug.Print inputRow - 1 & " 番目の<a>タグのテキストが見つかりませんでした。"
GoTo continue
End If
ws.Cells(inputRow, 1).Value = a.innerText
continue:
If IsNull(a.href) Then
Debug.Print inputRow - 1 & " 番目の<a>リンク先が見つかりませんでした。"
GoTo continue2
End If
ws.Cells(inputRow, 2).Value = a.href
continue2:
inputRow = inputRow + 1
Debug.Print inputRow
Next a
ws.Cells(1, 4) = Format(Now(), "yyyy/mm/dd hh:mm:ss")
End Sub
Sub XML_Sample()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.ActiveSheet
Dim begTime As Variant: begTime = Now()
ws.Cells(1, 2) = Format(begTime, "yyyy/mm/dd hh:mm:ss")
Dim req As XMLHTTP60: Set req = New XMLHTTP60
Dim url As String: url = "https://zeroterasu.com/blog/"
req.Open "GET", url
req.Send
Dim html As IHTMLDocument: Set html = New HTMLDocument
html.write req.ResponseText
Application.Wait(Now() + TimeValue("00:00:01"))
Dim inputRow As Long: inputRow = 2
Dim a As HTMLAnchorElement
For Each a In html.getElementsByTagName("a")
If IsNull(a.innerText) Then
Debug.Print inputRow - 1 & " 番目の<a>タグのテキストが見つかりませんでした。"
GoTo continue
End If
ws.Cells(inputRow, 1).Value = a.innerText
continue:
If IsNull(a.href) Then
Debug.Print inputRow - 1 & " 番目の<a>リンク先が見つかりませんでした。"
GoTo continue2
End If
ws.Cells(inputRow, 2).Value = a.href
continue2:
inputRow = inputRow + 1
Debug.Print inputRow
Next a
ws.Cells(1, 4) = Format(Now(), "yyyy/mm/dd hh:mm:ss")
End Sub
Sub SeleniumBasic_Sample()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.ActiveSheet
Dim begTime As Variant: begTime = Now()
ws.Cells(1, 2) = Format(begTime, "yyyy/mm/dd hh:mm:ss")
Dim dr As WebDriver: Set dr = New WebDriver
dr.AddArgument "--headless"
dr.Start "Chrome"
Dim url As String: url = "https://zeroterasu.com/blog/"
dr.Get url
Application.Wait Now() + TimeValue("00:00:01")
Dim inputRow As Long: inputRow = 2
For Each a In dr.FindElementsByTag("a")
ws.Cells(inputRow, 1).Value = a.Text
ws.Cells(inputRow, 2).Value = a.Attribute("href")
inputRow = inputRow + 1
Debug.Print inputRow
Next a
ws.Cells(1, 4) = Format(Now(), "yyyy/mm/dd hh:mm:ss")
End Sub
Sub IE_Sample()
Dim wb As Workbook: Set wb = ThisWorkbook
Dim ws As Worksheet: Set ws = wb.ActiveSheet
Dim begTime As Variant: begTime = Now()
ws.Cells(1, 2) = Format(begTime, "yyyy/mm/dd hh:mm:ss")
Dim ie As InternetExplorer: Set ie = New InternetExplorer
Dim url As String: url = "https://zeroterasu.com/blog/"
ie.navigate url
Do While ie.Busy = True Or ie.readyState < 4
DoEvents
Loop
Dim htmlDoc As HTMLDocument
Set htmlDoc = ie.document
Dim inputRow As Long: inputRow = 2
For Each a In htmlDoc.getElementsByTagName("a")
ws.Cells(inputRow, 1).Value = a.Text
ws.Cells(inputRow, 2).Value = a.getAttribute("href")
inputRow = inputRow + 1
Debug.Print inputRow
Next a
ws.Cells(1, 4) = Format(Now(), "yyyy/mm/dd hh:mm:ss")
End Sub
(おまけ)Microsoftドキュメント情報
今回使用した「WinHTTP」「XMLHTTP60」がそれぞれどのようなオブジェクトなのか気になったので、Microsoftドキュメントを確認してみました。
まずは、今回使用した2点のライブラリそれぞれのファイルを確認しました。(下記画像を参照下さい。)


WinHTTP参照先ファイル=「winhttpcom.dll」
XMLHTTP60参照先ファイル=「msxml6.dll」
このファイル名を手掛かりにして、Microsoftドキュメントを確認しました。
いずれのファイルも「dll(Dynamic Link Library)」ファイルです。
dllファイルは、ライブラリやモジュールのWindowsでの名称と考えて頂ければ理解しやすいかと思います(dll=Dinamic Link “Library”ですので普通に”ライブラリ”ですね。)。
ライブラリは、プログラムから呼び出されたときに実行される部品です。
DLL は、複数のプログラムで同時に使用できるコードとデータを含むライブラリです。
実際、WinHTTPはエクセル以外にもOutlook等でも使用されています。
Microsoft Windows HTTP Services (WinHTTP)ドキュメント:
クリックするとリンク先が別タブで開きます。
ドキュメントによると、「WinHTTPは、HTTPプロトコルを通じてHTTPサーバーにリクエストを送信するためのHTTPクライアントAPI」のようです。
IXMLHTTPRequestドキュメント:
クリックするとリンク先が別タブで開きます。
「 msxml6.dll 」ファイルの中に、「 XMLHTTP 」オブジェクトが実装されており、このオブジェクトを利用してHTTPリクエスト送信・レスポンス解析を実行しているといった内容が説明されています。
コメント