Yahoo路線検索スクリプト
しばらくプログラムネタを書いていなかったので、無理矢理なんか作ってみた。
よく使うWebサービスをPowerShellから使えるようにすると便利なので、Yahoo路線検索をPowerShellから呼び出せるようにしてみた。
Get-Transit.ps1
param([string]$from="津", [string]$to="名古屋", [DateTime]$date=[DateTime]::Now, [string]$type="ARR", [Switch]$charge, [Switch]$air) if($from.Length -eq 0 -or $to.Length -eq 0 -or $args[0] -eq "-?") { $commandName = [IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name) Write-Host -foregroundColor Yellow @" Name: $commandName Description: Yahoo路線検索を使って、指定した駅から駅の路線を検索します。 Usage: $commandName [[-from] <string>] [[-to] <string>] [[-date] <DateTime>] [[-type] <string>] [[-charge] <Switch>] [[-air] <Switch>] -from <string> 出発駅 -to <string> 到着駅 -date <DateTime> 探索日時と時間 -type <string> 探索方法(DEP(出発時刻指定) or ARR(到着時刻指定) or LST(終電) or NON(指定なし)) -charge <Switch> 有料特急を利用するかどうか -air <Switch> 空路を利用するかどうか "@ exit 1 } [void]([Reflection.Assembly]::LoadWithPartialName("System.Web")) $siteEncoding = [Text.Encoding]::GetEncoding("EUC-JP") # Yahoo路線検索サイトのエンコード $queryParams = @{ val_htmb="result"; from=[Web.HttpUtility]::UrlEncode($from, $siteEncoding); # 出発駅 p=[Web.HttpUtility]::UrlEncode($to, $siteEncoding); # 到着駅 sort=0; num=0; val_yymm=$date.ToString("yyyyMM"); val_dd=$date.ToString("dd"); val_hh=$date.ToString("HH"); val_m1=$date.ToString("mm")[0]; val_m2=$date.ToString("mm")[1]; valtimekb=$type; val_search=[Web.HttpUtility]::UrlEncode("探索", $siteEncoding); } Write-Debug $queryParams # 空路を利用する if($air) { $queryParams.Add("val_dsmask_air", "AIR") } # 有料特急を利用する if($charge) { $queryParams.Add("val_dsmask_charge", "CHARGE") } $webReq = [Net.HttpWebRequest]::Create( "http://transit.yahoo.co.jp/search?" + [string]::Join("&", ($queryParams.GetEnumerator() | % { "{0}={1}" -f ($_.Key, $_.Value) })) ) $webReq.Method = "GET" $webReq.Referer = "Mozilla/4.0 (compatible; MSIE 6.0; Windows XP)" $webRes = $webReq.GetResponse() $sr = New-Object IO.StreamReader($webRes.GetResponseStream(), $siteEncoding) $content = $sr.ReadToEnd().Replace("`n", "").Replace("`r", "") $sr.Close() $webRes.Close() $ptrn = New-Object Text.RegularExpressions.Regex( '経路[0-9]</div>(?<head>.*?)<table.*?>(?<body>.*?)view_switchers', "IgnoreCase" ) $headPtrn = New-Object Text.RegularExpressions.Regex(( 'start.">(?<start>.*?)..</span>' + # 出発時間 '.*?reach.">(?<reach>.*?)..</span>' + # 到着時間 '.*?result_lapse.">(?<lapse>.*?)</div>' + # 時間 '.*?result_distance.">.{3}(?<dist>.*?)</div>' + # 距離 '.*?result_passage.">.{3}(?<passage>.*?)</div>' + # 運賃 '.*?result_connection.">.*?>(?<con>.*?)</span>' + # 乗り換え '.*?result_pass.">.{4}(?<pass>.*?)</div>' # 定期代 ), "IgnoreCase") $bodyPtrn = New-Object Text.RegularExpressions.Regex(( '<em>(?<name>.*?)</em>' + '(.*?<td nowrap="nowrap"><small>(?<time>.*?)</small>' + '.*?<td><small>(?<desc>.*?)</small>|)' ), "IgnoreCase") function escape([string]$value) { [Web.HttpUtility]::HtmlDecode(($value -replace "<.*?>", "")).Trim() } [string]::Join([Environment]::NewLine, (& { @" <?xml version="1.0" encoding="utf-8"?> <transit> "@ $ptrn.Matches($content) | % { $headInfo = $headPtrn.Match($_.Groups["head"].Value) $bodyInfo = $bodyPtrn.Matches($_.Groups["body"].Value) $startTime, $reachTime, $lapseTime = (escape $headInfo.Groups["start"].Value), (escape $headInfo.Groups["reach"].Value), (escape $headInfo.Groups["lapse"].Value) $distance, $passage, $connection, $pass = $headInfo.Groups["dist"].Value, (escape $headInfo.Groups["passage"].Value), $headInfo.Groups["con"].Value, (escape $headInfo.Groups["pass"].Value) @" <item> <startTime>$startTime</startTime> <reachTime>$reachTime</reachTime> <lapseTime>$lapseTime</lapseTime> <distance>$distance</distance> <passage>$passage</passage> <connection>$connection</connection> <pass>$pass</pass> <routes> "@ $bodyInfo | % { $name = $_.Groups["name"].Value $time = $_.Groups["time"].Value $desc = (escape $_.Groups["desc"].Value) @" <route> <name>$name</name> <time>$time</time> <description>$desc</description> </route> "@ } @" </routes> </item> "@ } @" </transit> "@ }))
使い方
例えば、5/31の12:00に到着時刻指定で津→名古屋への路線を検索する場合(有料特急を使う)
PS > Get-Transit 津 名古屋 "2008/5/31 12:00:00" ARR -charge
出力
<?xml version="1.0" encoding="utf-8"?> <transit> <item> <startTime>10:59</startTime> <reachTime>11:53</reachTime> <lapseTime>54分(乗車50分、徒歩3分、ほか1分)</lapseTime> <distance>66.5km</distance> <passage>片道1,850円(乗車券980円 特別料金870円)</passage> <connection>0</connection> <pass>1か月22,260円 3か月63,450円 6か月120,210円</pass> <routes> <route> <name>津</name> <time>10:59〜11:49</time> <description>3駅 近鉄名阪乙特急</description> </route> <route> <name>近鉄名古屋</name> <time>11:50〜11:53</time> <description>徒歩</description> </route> <route> <name>名古屋</name> <time></time> <description></description> </route> </routes> </item> <item> <startTime>10:47</startTime> <reachTime>11:40</reachTime> <lapseTime>53分(乗車49分、徒歩3分、ほか1分)</lapseTime> <distance>66.5km</distance> <passage>片道1,850円(乗車券980円 特別料金870円)</passage> <connection>0</connection> <pass>1か月22,260円 3か月63,450円 6か月120,210円</pass> <routes> <route> <name>津</name> <time>10:47〜11:36</time> <description>3駅 近鉄名伊乙特急</description> </route> <route> <name>近鉄名古屋</name> <time>11:37〜11:40</time> <description>徒歩</description> </route> <route> <name>名古屋</name> <time></time> <description></description> </route> </routes> </item> <item> <startTime>10:47</startTime> <reachTime>11:55</reachTime> <lapseTime>1時間8分(乗車57分、徒歩3分、ほか8分)</lapseTime> <distance>73.4km</distance> <passage>片道2,190円(乗車券1,320円 特別料金870円)</passage> <connection>2</connection> <pass>1か月33,880円 3か月96,580円 6か月180,740円</pass> <routes> <route> <name>津</name> <time>10:47〜11:36</time> <description>3駅 近鉄名伊乙特急</description> </route> <route> <name>近鉄名古屋</name> <time>11:38〜11:41</time> <description>徒歩</description> </route> <route> <name>名鉄名古屋</name> <time>11:42〜11:45</time> <description>名鉄名古屋本線急行・中部国際空港行</description> </route> <route> <name>金山(愛知県)</name> <time>11:50〜11:55</time> <description>1駅 JR東海道本線・岐阜行</description> </route> <route> <name>名古屋</name> <time></time> <description></description> </route> </routes> </item> </transit>
結果はXML形式の文字列として返ってくる。ここからDOMオブジェクトにするなり、別のオブジェクトに加工するなり自由。このスクリプトはこれ単体で使うという感じではなく、他のと組み合わせて使う感じで書いた(Webアプリから使うため用)。
例:DOMオブジェクトにしてテーブル形式で整形
PS > ([xml](Get-Transit 津 名古屋 "2008/5/31 12:00:00" ARR -charge)).transit.item | ft startTime reachTime lapseTime distance passage connection pass routes --------- --------- --------- -------- ------- ---------- ---- ------ 09:56 11:07 1時間11分(... 66.5km 片道980円 0 1か月22,260... routes 09:56 11:16 1時間20分(... 68.4km 片道1,150円 2 1か月31,090... routes 09:43 10:53 1時間10分(... 66.5km 片道980円 0 1か月22,260... routes
ところでYahoo路線検索のサイトに「 無断転載、複写、加工を禁ず」って書いてあるんだけど、これもまずいのかな?まずかったら消しますので、言ってください。