requests と beautifulsoup でバス時刻表を取得する
Python ライブラリの requests と beautifulsoup を使って自宅の最寄りにあるバス停の時刻表を取得してみました。これまでバスはめったに乗らなかったのですが、場所によってはバスの方が便利なことが多いなと気付き始めました。そんなこともあって、バス会社の HP からバス時刻表をクローリングしてみました。特に時刻表を取得して何かするわけではありません。ただの興味本位です。何かアイデアが降ってきたら色々やってみます。
使ったライブラリ
- requests … HTTP 操作のためのライブラリ
- beautifulsoup … HTML を解析し WEB クローリングを簡単に行えるライブラリ
クローリングする
クローリングをするにあたって始めにバス会社の HP の HTML がどのような構造になっているか確認する必要があります。だいたいどの HP も時刻表は table タグで構成されていることが多いです。早速見てみます。
予想通り table で構成されていました。table タグの class 属性値である "timeTableWkd" で時刻表を構成する要素を取得できそうです。beautifulsoup では find や findAll を用いて取得できます。
find の第一引数はタグ名、第二引数に属性値を指定します。取得ができたら table の子要素である tr や th、td タグの情報を取得していきます。全体としてこんな感じになりました。
# -*- coding: utf-8 -*-
"""
scrape bus stop diagram
"""
import requests
from BeautifulSoup import BeautifulSoup
"""---------------------------------------------
main.
"""
def main():
headers = {
"User-Agent": "<ユーザエージェント>"
}
busstop_request = requests.get("<バス会社の URL>", headers = headers)
busstop_soup = BeautifulSoup(busstop_request.text.encode(busstop_request.encoding))
time_table = busstop_soup.find("table", attrs = {"class": "timeTableWkd"})
for tr in time_table.findAll("tr"):
hour = tr.find("th", attrs = {"class": "left"})
minutes = tr.findAll("td", attrs = {"class": "pl-6"})
print hour.text,
for minute in minutes:
if minute.text != " ":
print minute.text,
print ""
if __name__ == "__main__":
main()
for 文の中では 時(hour)と 分(minutes)を取得しそれを単純にコンソールに吐き出しています。見づらくて申し訳ないですが、コンソール上には以下のように時刻表が吐かれます。
注意すること
- 過度なアクセスは控えましょう。攻撃されていると勘違いされないためです。
- user-Agent でクローラーであることを知らせましょう。
- robots.txt を確認しておきましょう。
まとめ
動的ページだと厄介ですが、基本的にはさくっと短時間で必要な情報がいつでも取得できるので便利です。時刻表以外にも、例えば物件情報なり店舗情報なりクローリングしてデータの収集にも利用できそうですね。
今回は beautifulsoup を使ってクローリングしましたが、個人的には casperjs が使いやすいです。テストフレームワークのため人間的操作をそのままコードに書けば良いので分かりやすく、動的ページにも対応しやすいのでおすすめです。