路線検索をWebサービスとして使ってしまう

■日本のJR・私鉄・第3セクターをふくむすべての路線名と駅名のデータを何とか入手する方法はないものかといろいろ考えていた。もちろん商用目的ではなく、単に個人的に調べものをしたいだけだ。市販の路線検索のパッケージソフトを購入しても、中に入っている生データを取り出すことはできないだろうし、単に路線名・駅名一覧が知りたいだけなのにパッケージソフトを買うのもバカらしい。
そこで思いついたのが、路線検索サービスを提供しているポータルサイトに検索データを投げて、その検索結果かえってくるHTML文書を解析することで、路線名・駅名のデータファイルを作れないかということだ。
ただ、これをやるためには「自動化Webブラウザ」のようなプログラムを作る必要がある。つまり、特定のWebサイトに向かって次々とURLでリクエストを投げて、その結果をテキストファイルで読み取るといったプログラムでなければならない。
インターネットを調べてみた結果、これを実現するのに便利なActiveXオブジェクトが存在することが分かった。こちらのYU-TANG’s MS-Access DirectoryというWebサイトにある「Webページをダウンロードする方法~ MSXML 編~」というページをご参照頂きたい。
「MSXML2.XMLHTTP」というActiveXオブジェクトを生成すると、このオブジェクトがミニWebブラウザのような役割を果たしてくれる。ただしリクエストの結果をUnicodeに変換しなければ正しく読み取ることができないので、StrConv()関数でUnicodeに変換してやる必要がある。つまり、StrConv()関数が利用できる開発環境でないとダメということだ。
StrConv()関数は、Windowsに無料で付属しているWindows Scripting Hostでは残念ながら利用できない。したがって、Microsoft Officeをお持ちの方であれば、Excelのマクロを作成するためのVisual Basic for Applicationsがいちばん手軽な開発環境になる(もちろんVisual Studioがあれば言うことなしだ)。
Excelを起動して[Alt]+[F11]キーでVisual Basicエディタを起動し、メニューの「挿入」→「標準モジュール」をクリックして、今開いているブックにVisual Basicのプログラムをマクロとして記述できるようにする。
プログラムを入力するスペースに下記のVisual Basicのコードをコピー&貼付けして[F5]キーで実行すると、「C:WINDOWSTEMPEKI.CSV」というファイル名で、路線名・駅名一覧のCSVファイルが生成される。
ここで利用しているのは、@niftyが提供している「路線検索」サービスである。このサービスに「路線名から検索する」コーナーがあるのだが、このコーナーの「駅時刻表案内」検索の部分が、地域→路線名→駅名と絞り込むようになっている。
この部分のプログラムをURLをつかって次々と呼び出せば、路線名一覧や駅名一覧が表示される。表示されたHTMLを解析して、路線名と駅名部分のみを抽出すれば、CSVデータできるというわけだ。
たとえば「http://www.nifty.com/oyakudachi/webapp/timetable_support_line?an=-1」というURLをリクエストすると、全国の全鉄道の路線名一覧が返ってくる。さらに個々の路線名に付与されているコードで、「http://www.nifty.com/oyakudachi/webapp/timetable_support_station?sf=路線名コード」というURLをリクエストすると、その路線の駅名一覧が帰ってくる。
下記のプログラムはこのような理屈をプログラム化したものだ。Webで公開されているサービスを、いわばWebサービスのような感覚で利用して結果を受け取り、受け取ったHTMLファイルを解析して必要なデータを抽出するという感じだ。
ただ、Excelさえあれば「MSXML2.XMLHTTP」でHTTPのリクエストをじゃんじゃん投げることができるとなると、一定のVisual Basicのプログラミングスキルがある人なら、様々なWebサイトに対して自動的に大量のリクエストを投げるプログラムを書けてしまうことになる。当然のことながら悪意で特定のWebサイトに大量のリクエストを投げると、不正アクセス防止法には抵触せずとも、民法で処罰される可能性があるので決してやらぬよう。
また、Javaの実行・コンパイル環境がインストールされている端末なら、Javaを使えばもっとエレガントなプログラムに書き換えられるに違いないが、おそらく人数的にまだJavaプログラマよりも多いであろうVisual Basicプログラマのために、ここではVisual Basic版のみを記載した。
Option Explicit
Const ROSEN_URL = “http://www.nifty.com/oyakudachi/webapp/timetable_support_line?an=-1”
Const EKI_URL = “http://www.nifty.com/oyakudachi/webapp/timetable_support_station?sf=”
Const CSV_FILENAME = “C:WINDOWSTEMPEKI.CSV”
Sub GetRosen()
Dim oHttp As Object
Dim aRosen As Variant
Dim aEki As Variant
Dim aData As Variant
Dim I As Integer
Dim J As Integer
aRosen = GetDataArray(ROSEN_URL)
Open CSV_FILENAME For Output As 1
For I = 0 To UBound(aRosen)
aData = Split(aRosen(I), “,”)
aEki = GetDataArray(EKI_URL & aData(0))
For J = 0 To UBound(aEki)
Print #1, aData(0) & “,” & aData(1) & “,” & aEki(J)
Next
Next
Close #1
End Sub
Function GetDataArray(sURL As String) As Variant
Dim oHttp As Object
Dim aLines As Variant
Dim sLine As String
Dim sBuf As String
Dim I As Integer
Dim bFound As Boolean
Dim sRes() As String
Dim iIdx As Integer
iIdx = 0
Set oHttp = CreateObject(“MSXML2.XMLHTTP”)
oHttp.Open “GET”, sURL, False
oHttp.Send
aLines = Split(StrConv(oHttp.responseBody, vbUnicode), Chr(10))
For I = 0 To UBound(aLines)
sLine = aLines(I)
‘ 値一覧の途中である場合
If bFound And InStr(sLine, “<option value=”) > 0 Then
sBuf = Replace(sLine, “<option value=”””, “”)
sBuf = Replace(sBuf, “</option>”, “”)
sBuf = Replace(sBuf, “”” selected>”, “,”)
sBuf = Replace(sBuf, “””>”, “,”)
‘ コード「-1」はダミー選択肢と見なして無視する
If Left(sBuf, 2) <> “-1” Then
ReDim Preserve sRes(iIdx) As String
sRes(iIdx) = sBuf
iIdx = iIdx + 1
End If
End If
‘ 値一覧の場所の開始点
If (Not bFound) And _
InStr(sLine, “name=””sf”””) > 0 And _
InStr(sLine, “<select “) > 0 Then bFound = True
‘ 値一覧の場所の終了点
If bFound And _
InStr(sLine, “</select>”) > 0 Then Exit For
Next
GetDataArray = sRes
End Function