Rを使ってYahoo!乗換案内から運賃や所要時間,乗換回数を取得するコード書いた
(※追記あり)
数日前にスクレイピングという言葉を学び,とりあえずRでやってみた.まだまだ勉強途中なのでいろいろ間違ってるかもしれないし,計算速度もそんなに速くないのだけど,どなたか詳しい人ご教授ください.むしろもっと楽な方法があれば是非!
内容はYahoo!乗換案内に対して,出発駅と到着駅を与えることで,運賃,所要時間,乗換回数を取ってくるコードになっていて,複数提示されるうちの1番上を取ってきます.最終的にデータフレームに閉まって終了という内容です.途中のHTML解析部分はひどく手作業感が出ているので,正規表現などを使ってもう少しスマートな感じにしたいのですが,とりあえず動くことは動きます.こんなデータを取得したい需要は一部の分野にしかなさそうですが,そこはご愛敬.動かす場合は最初にRCurlのpackageをインストールする必要があります.計算速度は1000組合せで30分程度.うーむ.下の例では簡単のため,20組合せ駅にしてあります.
library(RCurl) #出発駅と到着駅ベクトル station1 <- c("渋谷","表参道", "外苑前", "青山一丁目", "赤坂見附", "溜池山王", "虎ノ門", "新橋", "銀座", "京橋", "日本橋", "三越前", "神田", "末広町", "上野広小路", "上野", "稲荷町", "田原町", "浅草", "渋谷") station2 <- c("品川","大崎", "五反田", "目黒", "恵比寿", "渋谷", "原宿", "代々木", "新宿", "新大久保", "高田馬場", "目白", "池袋", "大塚", "巣鴨", "駒込", "田端", "西日暮里", "日暮里", "鶯谷") hh <- length(station1) #URLエンコードしておく station3 <- numeric(hh) station4 <- numeric(hh) for(i in 1:hh){ station3[i] <- paste(c("",charToRaw(iconv(station1[i],"CP932","UTF-8"))),collapse="%") station4[i] <- paste(c("",charToRaw(iconv(station2[i],"CP932","UTF-8"))),collapse="%") } Cost.v <- numeric(hh) Time.in <- numeric(hh) Time.out <- numeric(hh) Transfer.v <- numeric(hh) #yahoo乗換案内から取ってくる system.time( for(i in 1:hh){ eval(parse(text=paste("txt <- getURL(\"http://transit.map.yahoo.co.jp/search/result?from=", station3[i], "&to=", station4[i], "&via=&shin=1&ex=1&al=1&hb=1&lb=1&sr=1&ym=201008&d=26&hh=12&m1=4&m2=5&type=1&ws=2&s=0&ost=0&ei=utf-8&x=0&y=0&kw=", station4[i], "\")",sep="",collapse=""))) ##抽出 a1 <- regexpr("<dl><dt>運賃:</dt><dd>片道<span class=\"route-fare-", txt) a2 <- regexpr("円</span><!--\n-->", txt) a3 <- regexpr("</span>時間:</dt><dd>", txt) a4 <- regexpr("</dd></dl>\n<!--heikin-->", txt) a5 <- regexpr("<dl><dt>乗り換え:</dt><dd><span class=\"route-transfer-", txt) a6 <- regexpr("</span></dd></dl>\n</div><!--end infomation2 -->", txt) #運賃 cost <- substr(txt, a1+46, a2) a10 <- regexpr("円", cost) if(regexpr("on", cost)==1){ Cost.v[i] <- substr(cost, 5, a10-1) if(regexpr(",", Cost.v[i])!=-1){ Cost.v[i] <- paste(substr(Cost.v[i],1,regexpr(",", Cost.v[i])-1), substr(Cost.v[i],regexpr(",", Cost.v[i])+1, 20), sep="") } }else{ Cost.v[i] <- substr(cost, 6, a10-1) if(regexpr(",", Cost.v[i])!=-1){ Cost.v[i] <- paste(substr(Cost.v[i],1,regexpr(",", Cost.v[i])-1), substr(Cost.v[i],regexpr(",", Cost.v[i])+1, 20), sep="") } } #所要時間 time <- substr(txt, a3+19, a4-1) a7 <- regexpr("分(乗車", time) Time.in[i] <- substr(time, 1, a7-1) if(regexpr("時間", Time.in[i])!=-1){ Time.in[i] <- as.numeric(substr(Time.in[i], 1, 1))*60 + as.numeric(substr(Time.in[i], 4, 10)) } a8 <- regexpr("分、ほか", time) a9 <- regexpr("分)", time) Time.out[i]<- substr(time, a8+4, a9-1) #乗換回数 transfer <- substr(txt, a5+50, a6-1) a11 <- regexpr("回", transfer) if(regexpr("on", transfer)==1){ Transfer.v[i] <- substr(transfer, 5, a11-1) }else{ Transfer.v[i] <- substr(transfer, 6, a11-1) } print(i) #どこまで進んだか見たいとき用 }) Cost.v <- as.numeric(Cost.v) Time.in <- as.numeric(Time.in) Time.out<- as.numeric(Time.out) Transfer.v <- as.numeric(Transfer.v) Data2 <- data.frame(Origin=station1, Destination=station2, Cost=Cost.v, Timein=Time.in, Timeout=Time.out, Transfer=Transfer.v)
結果は次のように表示されます.
Origin Destination Cost Timein Timeout Transfer 1 渋谷 品川 160 12 0 0 2 表参道 大崎 310 16 6 1 3 外苑前 五反田 310 17 6 1 4 青山一丁目 目黒 310 15 4 1 5 赤坂見附 恵比寿 290 14 4 1 6 溜池山王 渋谷 160 10 0 0 7 虎ノ門 原宿 290 18 4 1 8 新橋 代々木 210 20 4 1 9 銀座 新宿 310 20 6 1 10 京橋 新大久保 350 27 8 2 11 日本橋 高田馬場 190 15 0 0 12 三越前 目白 320 26 9 2 13 神田 池袋 320 20 5 1 14 末広町 大塚 320 22 7 1 15 上野広小路 巣鴨 210 17 8 1 16 上野 駒込 150 8 0 0 17 稲荷町 田端 310 13 5 1 18 田原町 西日暮里 290 13 5 1 19 浅草 日暮里 290 13 5 1 20 渋谷 鶯谷 190 28 0 0
それはともかくとして,このスクレイピングってどこまでやっていいものなのでしょう….Librahackの二の舞にはなりたくないよ.
(※追記)
id:kkobayashi_aさんが大幅に綺麗に書き直してくださいました.感謝多謝!
id:kkobayashi_a:20100829:p1