AccessのVBAでYahoo!路線情報からHTMLを取得して運賃を取得してみる

VBAでHTMLを取得する

今回はAccessのフォームでYahoo!路線情報から運賃を取得するところまでを実践してみましょう。
このケースではインターネットエクスプローラーオブジェクトを利用してHTMLを取得する方法を説明します。
尚、今回はVBAの知識だけでは無く、HTMLに関する最低限の知識も必要になります。その為、少し長い記事になりますがご了承ください。

動作イメージ

出発と到着を指定して検索ボタンをクリックするとYahoo!路線情報を検索します。その後、結果ページのHTMLを取得して区間と運賃をフォームに表示します。
動作イメージは以下の通りです。

VBAでHTMLを取得する

※今回はWebページを表示せず結果のみ取得します。
※今回取得する結果は最初の3経路までとします。

フォームデザイン

フォームのデザイン及び各コントロール名は以下の通りで作成します。

フォームデザイン

サンプルコード

検索ボタンのイベントプロシージャは以下の通りです。

'******************************************
'HTMLを取得する
'******************************************
Private Sub cmd検索_Click()
Dim s出発 As String
Dim s到着 As String
Dim w_URL As String
Dim objIE As Object
Dim strHtml As Variant
Dim strSearch As Variant
Dim wPosition As Long
Dim wLen As Long
Dim wStartPoint As Long
Dim wEndPoint As Long
Dim i As Integer

'入力漏れがある場合は処理しない。
    If Nz(Me!txb出発, "") = "" Or _
            Nz(Me!txb到着, "") = "" Then Exit Sub

'文字コードをUTF-8に変換
    s出発 = UrlEncodeUtf8(Me!txb出発)
    s到着 = UrlEncodeUtf8(Me!txb到着)

'Yahoo!運賃検索URLを作成する
    w_URL = "http://transit.loco.yahoo.co.jp/search/result?from=" _
                & s出発 & "&to=" & s到着


'objIEオブジェクトを作成します
    Set objIE = CreateObject("InternetExplorer.Application")
    
'インターネットエクスプローラは非表示にする
    objIE.Visible = False
    
'指定したURLをセットします
    objIE.Navigate w_URL
    
'ページの読み込みが終わるまで待機する
    Do Until objIE.Busy = False
    '一旦処理を待機する(200ミリ秒)
        Sleep 200
    Loop

'BodyのHTMLを取得する
    strHtml = objIE.Document.Body.InnerHtml
    
'区間を取得する
    '最初の<h2>をセット
    strSearch = "<h2>"
    '文字数を取得
    wLen = Len(strSearch)
    '区間の開始位置を取得
    wStartPoint = InStr(strHtml, strSearch) + wLen
    
    '区間の終わりのタグ<span class="departure">をセット
    strSearch = "<span class=" & "" & "departure" & "" & ">"
    '区間の終了位置を取得
    wEndPoint = InStr(strHtml, strSearch)
    '区間をテキストボックスにセットする
    Me!txbKukan = Mid(strHtml, wStartPoint, wEndPoint - wStartPoint)
    
'クリアする
    wEndPoint = 1
    Me!txbRoot = Null
    
'検索結果1ページ目(最大3経路)の運賃を取得する
    For i = 1 To 3
    '[安]マークのタグ<span class="route-fare-on">をセット
        strSearch = "<span class=" & "" & "route-fare-on" & "" & ">"
        wLen = Len(strSearch)
        wStartPoint = InStr(wEndPoint, strHtml, strSearch) + wLen
        
        '[安]マーク料金(route-fare-on)を取得する
        If InStr(wEndPoint, strHtml, strSearch) <> 0 Then
            strSearch = "</span>"
            wEndPoint = InStr(wStartPoint, strHtml, strSearch)
            If Nz(Me!txbRoot, "") <> "" Then
                Me!txbRoot = Me!txbRoot & vbCrLf & _
                    "経路" & i & ":[安]" & _
                    Mid(strHtml, wStartPoint, wEndPoint - wStartPoint)
            Else
                Me!txbRoot = Me!txbRoot & "経路" & i & ":[安]" & _
                    Mid(strHtml, wStartPoint, wEndPoint - wStartPoint)
            End If
        Else
    '[安]マークが付いていない無い料金(route-fare-off)を取得する
            strSearch = "<span class=" & "" & "route-fare-off" & "" & ">"
            wLen = Len(strSearch)
            wStartPoint = InStr(wEndPoint, strHtml, strSearch) + wLen
        
            If InStr(wEndPoint, strHtml, strSearch) <> 0 Then
                strSearch = "</span>"
                wEndPoint = InStr(wStartPoint, strHtml, strSearch)
                If Nz(Me!txbRoot, "") <> "" Then
                    Me!txbRoot = Me!txbRoot & vbCrLf & _
                        "経路" & i & ":" & _
                        Mid(strHtml, wStartPoint, wEndPoint - wStartPoint)
                Else
                    Me!txbRoot = Me!txbRoot & "経路" & i & ":" & _
                        Mid(strHtml, wStartPoint, wEndPoint - wStartPoint)
                End If
            End If
        End If
    Next i

    Set objIE = Nothing

End Sub

尚、運賃検索用のURLの作成に関する情報は前回のエントリー[Access2010のフォームにホームページを表示する方法~第2回(Yahoo!JAPANロコの路線検索を利用)]をご参考下さい。

標準モジュールに処理を待機させるためのAPIを設定する

Option Compare Database
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

VBAのポイント解説

  1. IEオブジェクトを使う準備をします
    サンプルコード30行目でIEオブジェクトを作成しています。
  2. 検索用URLをセットします
    36行目でIEオブジェクトにNavigateプロパティを使い検索用URLをセットします。
  3. ページの読み込みが終わるまで待機する
    39行目から42行目までIEが検索結果を取得するまで処理を待機します。
  4. BodyのHTMLを取得する
    45行目で検索結果ページのBody部のHTMLをDocument.Body.InnerHtmlを利用して取得します。
  5. 区間をソースコードから抽出する
    47行目から60行目までで区間のテキストを取得しています。区間はHTMLのソースコードを見ると最初のh2タグspanタグに囲まれている事が分かります。

    区間を取得

    サンプルソースではこのタグの位置をInStr関数を使って取得し、Mid関数で区間を抜き取っています。

  6. 運賃をソースコードから抽出する
    67行目以降で最初の検索結果ページの3経路の運賃を取得していますが、運賃の表示で最安値の場合とそうでない場合、使われているspanタグのクラス(route-fare-onとroute-fare-off)が異なりますので、それぞれ参照するようにしなければいけません。

    運賃の取得

    区間同様に運賃の位置をInStr関数を使って取得し、Mid関数で抜き取ります。

以上、今回はIEオブジェクトを使ってHTMLを取得する方法について説明しました。
サンプルソースではYahoo!路線情報からHTMLソースを取得しましたが、Yahoo!側のサイト改変などにより内部構造が変わった場合は正常に動作しなくなる可能性も高いです。
そのような場合は、VBAも修正する必要がありますのでご了承ください。

関連エントリー

HTMLソースを取得するならXMLHTTPオブジェクトを使う方法がおすすめ!
IEオブジェクトを使わずにXMLHTTPオブジェクトを使ってYahoo!路線情報のHTMLソースを取得する方法について説明しています。

今回のサンプルファイルは以下のリンクからダウンロード可能です。