Pythonでスクレイピングの初歩の初歩

はじめに

普段はあまり触らない領域だが,スクレイピングに興味が沸く出来事があったのでチャレンジした記録.

 

(*)宣伝を兼ねて...今回の記事は 第7回 Python勉強会@仙台+PHP.Sendai第8回勉強会 – connpassで行ったLTを基にしています.

 

動機(飛ばして可)

先日,中学の友人らとUSJに行った.楽しいのだが,とにかく待ち時間が長い...

うんざりしていたところ,USJ リアルタイム待ち時間 | USJ待ち時間・混雑情報 というサイトを発見.

各アトラクションの待ち時間をリアルタイムで表示してくれる機能に加えて,過去の待ち時間の推移も表示してくれている.
(おそらく公式がアプリ向けに配信している情報をスクレイピングしている.来場前に公式アプリをダウンロード!|パークの楽しみ方|ユニバーサル・スタジオ・ジャパン™|USJ)

これを見れば,アトラクション巡りの戦略もたてやすくなる.

仕組みはよくわかならいけど,これは迷える子羊たちを幸せにするサイトだ!と思い感動.

 

僕もやってみたい!あとデータから待ち時間予測モデルも作りたい!と思ったのが本チャレンジの動機である.

ちなみにUSJ訪問を含めた中学の愉快な仲間たちとの旅行の詳細については,大阪旅行 -noah.plusに詳しい.

 

今回やったこと

基本的にスクレイピングは,「ある特定のweb pageの特定の情報を取得するアクション」が構造上の最小の要素となる.

これを一定時間ごとに呼び出す関数,取得したデータを保存・出力する関数,などど組み合わせてスクレイピングの一連のシステムが構成される.

大規模に行ったり,取得データを商用利用する場合などは,特に慎重に行う必要がある.Webスクレイピングする際のルールとPythonによる規約の読み込み – Stimulator が参考になった.

 

今回は,前述の最小構成要素「ある特定のweb pageの特定の情報を取得するアクション」を一回だけ行う.

さきほどのサイトから「ジュラシック・パーク・ザ・ライド」の待ち時間の情報を取得しようと思う.

 

参考サイト

ググればもう完璧.結局,写経しただけみたいになってしまった.

 

コード

In [1]:
# coding: UTF-8
import urllib3 
from bs4 import BeautifulSoup
In [2]:
#ターゲットページのurl
url = "http://usjinfo.com/attrWait.php?attr_id=2"
In [3]:
# サイトにアクセス
http = urllib3.PoolManager(
response = http.request("GET", url)

リクエストが成功したかどうか確認.

In [4]:
print(response.status)
200

200なので問題なし.404だったらURLを要確認.BeautifulSoupは以下のように使う.

In [5]:
data = BeautifulSoup(response.data, "lxml")

引数lxmlは解析器を指定している.

PythonでWebスクレイピングする時の知見をまとめておく – Stimulator

ガッツリスクリプトにして回す時は、解析器を選択しておくと吉。

  • html.parser
    • デフォルトで付いてくるやつ
    • 本当に些細なミスでも落ちるし中身がPythonなので遅い
    • Pythonのバージョンに依存して中身も違う
  • lxml
    • C言語の高速実装な解析器
    • 最近のWebの複雑な構造や動的な物に少し弱い
  • html5lib
    • html5の規則に対応
    • ブラウザで表示するのとほぼ同じメソッド
    • かなり重い

さて今回は,以下のページをスクレイピングする.

ジュラシック・パーク・ザ・ライド(R)の待ち時間 | USJ待ち時間・混雑情報

htmlコードはこんな感じ...


~省略~
<ul class="list">
  <li class="li-title">
    15時2分現在の待ち時間
      </li>
  <li class="li-item">
          35分
      </li>
  <li class="li-link"><a href="dateHourlySpecifiedDay.php">今日これまでの待ち時間</a></li>
      <amp-img src="hourly_pictures/day/2_20180825.gif" width="200" height="100" layout="responsive" alt="ジュラシック・パーク・ザ・ライド(R)の今日の待ち時間"></amp-img>

                <li class="li-link"><a href="dateHourlySpecifiedDay.php?date=20180824">1日前の待ち時間(2018年08月24日(金))</a></li>
  <amp-img src="hourly_pictures/day/2_20180824.gif" width="200" height="100" layout="responsive" alt="ジュラシック・パーク・ザ・ライド(R)の1日前の待ち時間"></amp-img>
~省略~

<ul>の中の<li class="li-item">に入っているぽい.以下のようにタグとクラスを指定して取得できる.スクレイピングのコツは結局のところ,タグの構造を理解してうまく処理ことなんだなって思った.(いまさら)

In [7]:
data.find_all("li", attrs={"class": "li-item"})
Out[7]:
[<li class="li-item">
           50分
       </li>]

どうやら取得できたっぽい..stringでタグの中身を取得できる.

In [8]:
w_time = data.find_all("li", attrs={"class": "li-item"})[0].string
In [9]:
w_time
Out[9]:
'\n          50分\n      '

少しゴミが入っている模様.力技で整形する.

 

In [10]:
#どうしよう
w_time_int = int(w_time.split("分")[0])
In [11]:
w_time_int
Out[11]:
50

 

とりあえずできた.

 

今後の課題

興味本位でいじってみたが,さすがPython.良くも悪くも簡単に実装できた.今後の課題は以下.

  • リアルタイムで情報を取得するシステムの実装
  • スクレイピングのお作法の勉強(重要)

  • 正規表現の勉強(重要)

  • 出力フォーマットの整理
  • 取得データの解析
2