Pythonで駅コード調査用データベースから情報をスクレイピングした

blog.zuckey17.org

前回、 Suicaの利用履歴をパースするリポジトリ中の StationCode.csvについて、

StationCode.csvがコミュニティーの有志によって作成されたものらしく、最新のものではないのか、完全ではないようです。

と書きました。

よくよく調べると、路線・駅コード一覧・登録 というサイトがあり、

路線・駅コード一覧・登録のページに遷移すると、駅コードのデータベースのようなものにたどり着きます。 ここで随時更新されているようなので、今回はこれをスクレイピングして、真・StationCode.csvを作成してみました。

Pythonによるスクレイピング、ちゃんとするのが初めてでいろいろハマりましたが以下のようなコードになりました。

import csv
import re
import urllib2
from bs4 import BeautifulSoup

current_page = 1

html = urllib2.urlopen("http://www.denno.net/SFCardFan/index.php")
soup = BeautifulSoup(html, "html.parser")
last_page_num = int(re.findall('[\d]+', soup.find("a", title="last page").string)[0])

file = open('StationCode.csv', 'w')

for num in range(last_page_num):
    html = urllib2.urlopen("http://www.denno.net/SFCardFan/index.php?pageID=" + str(current_page))
    soup = BeautifulSoup(html, "html.parser")
    rows = soup.find_all("table")[1].find_all("tr")
    del rows[0:2]
    for row in rows:
        datas = map(lambda x: not(isinstance(x, type(None))) and not(isinstance(x.string, type(None))) and x.string.encode('utf-8'), row.find_all("td")) # エンコード変換
        writer = csv.writer(file, lineterminator='\n')
        writer.writerow(datas)
    current_page += 1

file.close()

ファイルに書き出す際に UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) と文字エンコードで怒られたので、空文字列でない場合にUTF-8エンコードを変換する処理を書きました。

それ以外は意外とスムーズに進んだので、pythonすげーとなりました。

まとめ