【VBA】netkeibaのオッズをスクレイピングする


以前の記事「netkeibaをスクレイピングする記事」の補足です。
以前紹介したツール(従来ツール)では、netkeibaからオッズ値を取得することが出来ませんでした。
今回、操作性をあまり損なわずにオッズ値を取得する方法を調べたので、ここに補足します。



従来ツールの課題

netkeibaのオッズ値は動的生成されたものが後からWebページ内に挿入される仕様になっているため、従来ツールのように単にHTTPリクエストを送信するやり方(静的HTMLコンテンツを取得・解析するやり方)では、オッズ値を拾うことができませんでした。
ただしこのやり方の利点である「Excelさえあればスグ使える」「ブラウザレスで直接サーバーへ情報を取りに行くのでサクサク動く」という手軽さも結構大事なポイントだったので、この操作性を損なわないままオッズ値を取得する方法はないかな…と考えた時に、及第点というか妥協点を見つけたので紹介します。

解決策

結論から言うと、クラウドベースでヘッドレスブラウザ機能を提供してくれるスクレイピングAPIを使ってオッズ値を取得します。
操作性を損なわずに(余計なインストール等不要で)オッズ値を無料取得できますが、一方で以下のようなデメリットもあります。
①事前にAPIの利用申請が必要。(Web上でアカウント作成する手間が掛かる)
②APIの無料利用枠に上限がある。(1ヶ月あたり大体1000回まで利用可)
③APIの処理に時間が掛かる(最大60秒位)。

これらのデメリットを許容できる人は、今回のカスタマイズを試してみて下さい。なお、スクレイピングAPIと一口に言っても「ScraperAPI」「Apify」「WebScrapingAPI」と色々あります。基本的な性能は大体同じなので正直拘りは無いですが、今回は「ScrapingAnt」というスクレイピングAPIを使って実装する例を紹介していきます。

スクレイピングAPIの利用登録(ScrapingAntの例)

ScrapingAntを使うには、事前にWebサイトで利用登録が必要です。
まず、ScrapingAntの Webサイトを開き、「Sing up for Free Plan」ボタンから無料アカウントを作成します。(メールアドレスのみで作成可)

図1:ScrapintAntの無料アカウント登録手順

アカウント登録が完了するとAPI Keyが発行されます。これはAPIを呼び出す際に必要なパラメーターなので、控えておきます。
ダッシュボード画面からいつでも確認可能。
ここではAPI tokenとある部分の値(赤線部分)がそれに該当します。

図2:ScrapingAntのダッシュボード画面(アカウント作成後に表示される画面)


VBAコードの追加手順

アカウント登録ができたら、次に以下のVBAコードを追加しましょう。

VBAコードその1

'-----(Module1の「WebScraping()」プロシージャ内に追記、挿入位置は下記画像参照のこと)-----
 Call getOdds(URL, sh)
'----------

VBAコードその2

'-----(Module1の末尾に追記)-----
'Proc① ScrapingAnt APIの結果からオッズを抽出し、シートへ書き出す
Private Sub getOdds(ByVal URL As String, ByVal sh As Worksheet)
    Dim HTML As Object
    Dim tag As Object
    Dim Ctag As Object
    Dim Odds() As Variant 'Double
    Dim OddsCnt As Integer
    Set HTML = CreateObject("htmlfile")
    HTML.body.innerHTML = getOddsResponse(URL)
    OddsCnt = 0
    For Each tag In HTML.getElementsByTagName("table")
      If InStr(tag.className, "RaceTable01 ShutubaTable") > 0 Then
        For Each Ctag In tag.getElementsByTagName("td")
            If InStr(Ctag.className, "Txt_R") > 0 Then
                ReDim Preserve Odds(OddsCnt + 1)
                Odds(OddsCnt) = Ctag.innerText
                OddsCnt = OddsCnt + 1
            End If
        Next
      End If
    Next
    If OddsCnt = 0 Then Exit Sub
    sh.Range("J6").Resize(OddsCnt - 1).Value = Application.WorksheetFunction.Transpose(Odds)
End Sub

'Proc② ScrapingAnt APIを呼び出す
Private Function getOddsResponse(ByVal URL As String) As String
    Dim API_Key As String
    Dim API_EndPoint As String
    Dim Req As Object
    API_Key = "*******"
    API_EndPoint = "https://api.scrapingant.com/v2/general"
    URL = API_EndPoint & "?url=" & URLEncode(URL) & "&x-api-key=" & API_Key & "&proxy_country=JP"
    Set Req = CreateObject("MSXML2.ServerXMLHTTP")
    Req.setTimeouts 5000, 5000, 5000, 60000 'タイムアウト設定(コネクション5秒、送信5秒、受信5秒、レスポンス60秒)
    Req.Open "GET", URL, False
    Req.send
    If Req.Status = 200 Then
        getOddsResponse = Req.responseText
    Else
        Debug.Print "リクエスト失敗。ステータスコード: " & Req.Status
    End If
    Set Req = Nothing
End Function

'Proc③ URLをパーセントエンコードする
Function URLEncode(ByVal Text As String) As String
    Dim i As Long
    Dim Char As String
    Dim EncText As String
    EncText = ""
    For i = 1 To Len(Text)
        Char = Mid(Text, i, 1)
        Select Case Asc(Char)
            Case 48 To 57, 65 To 90, 97 To 122, 45, 46, 95, 126
                EncText = EncText & Char
            Case Else
                EncText = EncText & "%" & Right("0" & Hex(Asc(Char)), 2)
        End Select
    Next
    URLEncode = EncText
End Function
'----------

これらを、従来ツール(.xlsm)に追加していきます。

【VBAコードの追加手順】
まずは、従来ツール(.xlsm)のVBE(VisualBasicEditor)を立上げます。
従来ツールのExcel上でAlt+F11キーを押してVBEを立上げたら、画面左側のプロジェクトエクスプローラーから「標準モジュール>Module1」を選択してダブルクリックします。すると、画面右側のコードウィンドウにVBAコードが表示されます。

図3:VBEの立上げ&Module1の表示方法

~追記する部分は2か所~
●1か所目
Module1の「WebScraping()」プロシージャの中に、上記VBAコードその1を追加します。
(追加する位置は、下記画像を参照のこと)

図4:Module1の「WebScraping」プロシージャ内に、上記「VBAコードその1」を書き加える

●2か所目
Module1の一番下(最下部までスクロールして末尾)に、上記VBAコードその2を追加します。
(追加する位置は、下記画像を参照のこと)

図5:Module1の一番下に、上記「VBAコードその2」を書き加える

このとき、Proc②の「API_Key = "*******"」の値(*******の部分)を、各自のAPI Keyに置き換えてください。
※先の手順で控えておいたAPI Keyのことです。
 図2の赤線部分がご自身のAPI Keyなので、これを*******の部分へ忘れず書き込みます。

以上でカスタマイズ完了。
従来ツールにオッズ取得機能が追加されました。


使用時の注意点

冒頭にも書きましたが、スクレイピングAPI(今回の例では「ScrapingAnt」というAPIサービス)を介してオッズ取得している都合上、スクレイピングAPIの制約に左右されます。
どのスクレイピングAPIであっても、大抵は無料利用枠に上限が設けてあるので、その上限回数以上のリクエストは実行できません。ScrapingAntでは1000回/月まで無料利用可能で、それ以上は意図したレスポンスが返ってこない(エラーメッセージが返ってくる)ためオッズ取得できないことに注意してください。
またスクレイピングAPIからレスポンスが返ってくるまでに結構時間が掛かる(タイムアウト60秒)事があるので、一長一短あると思います。


以下、処理概要を記載。

ヘッドレスブラウザについて

ヘッドレスブラウザとは、ユーザーインターフェイス(UI)を持たないブラウザを指します。Webページを読込んで、JavaScriptを実行できて、コンテンツをレンダリングする役割は通常のブラウザと同じです。ただ違うのは、UIが無いためバックグラウンドで実行される点です。UIが無いという事はユーザー操作のための画面表示が不要という事です。
ヘッドレスブラウザを使う事で、通常のHTTPリクエストでは取得できない動的に生成されたコンテンツも取得できるようになります。ブラウザのこうした処理機能だけを都合よく呼び出して使えるイメージです。
ヘッドレスブラウザで代表的なのはPuppeteerやHeadless Chrome辺りですが、これらはローカルマシンにインストールする必要があるので今回の候補から外しました。(手軽さという観点から大きく外れるため)

ScrapingAnt APIについて

そこで、ヘッドレスブラウザの機能をクラウドベースで無料提供してくれるスクレイピングAPIを使う事にしました。今回記事ではスクレイピングAPIの一つである「ScrapingAnt」を使って実装。
ScrapingAntって何ぞや?と思いChatGPTに聞いてみたら、いい感じの回答が返ってきたので引用します。

ヘッドレスブラウザを利用したWebスクレイピングをサポートするプラットフォームです。具体的には、ScrapingAntのAPIを使用することで、以下のようなヘッドレスブラウザの機能を活用することができます。
JavaScriptの実行:ヘッドレスブラウザを使用してJavaScriptで動的に生成されたコンテンツを取得することができます。これにより、通常のHTTPリクエストではアクセスできないデータも取得可能です。
ページのレンダリング:ヘッドレスブラウザによってページを完全にレンダリングし、表示されたコンテンツをスクレイピングできます。
自動化された操作:フォームの送信やボタンのクリックなど、ユーザーがブラウザで行う操作を自動化して実行できます。

ScrapingAntはこれらの機能をバックエンドで提供し、ユーザーが簡単にWebデータを抽出できるようにしています。ユーザーはScrapingAntのAPIを介してリクエストを送信し、必要なデータを取得するだけで、ヘッドレスブラウザの設定や管理を気にする必要がありません。

ChatGPTより抜粋

つまり、バックエンド側でヘッドレスブラウザを使用してレンダリングし、必要なデータを取得して返してくれる、とういものです。我々ユーザーはAPIエンドポイントへリクエスト送信するだけで目的の結果が得られます。

ScrapingAntのFree Planでは毎月10,000クレジットがユーザーに割り振られて、各自のダッシュボードからクレジット残数が確認できます。APIコールする(エンドポイントへリクエスト送信する)度にこのクレジットを消費していく訳ですが、どんなレスポンス形式を要求するかに依って、消費クレジット数が変わってきます。
今回の目的は動的生成されたオッズ値を取得することなので、レスポンス形式に「ヘッドレスブラウザ機能」を要求する必要があります。なのでAPIドキュメントにある通り、消費クレジット数(API credits cost)は1コール辺り10です。
つまり、無料プランで使用可能なAPIコール回数は1000回分/月となります。

レスポンス形式の要求は、APIエンドポイントに続けてURLクエリパラメータ「?」と区切り文字「&」を使って繋げて書きます。
ヘッドレスブラウザ機能「&browser=true」はデフォルト値trueなので省略可能。プロキシ設定「&proxy_country=JP」を書いておけばOKです。

この記事が気に入ったらサポートをしてみませんか?