HTMLの表のスクレーピング

ここでは例として環境放射線測定結果のような表をpandasで読み込む方法を説明する。

注意すべき点は,表の見出しにセル結合が使ってあって,列見出しに階層構造があることである。

表自体をスクレーピングするのは簡単である。あらかじめpandasとlxmlがインストールされているとする:

import pandas as pd

tables = pd.read_html('http://monitoring.tokyo-eiken.go.jp/report/shinjuku/mon_air_week_201112w.html')
len(tables)     # => 1
df = tables[0]  # 最初の表を取り出す

この df を表示すると,次のようになる(多少編集してある):

     測定日時(Measurement time) 線量率 (dose rate)μGy/h (microgray per hour)
     測定日時(Measurement time)              最大値(max) 最小値(min) 平均値(average)
0    2011/03/20 23:00~23:59                0.0515   0.0465       0.0494
1    2011/03/20 22:00~22:59                0.0524   0.0405       0.0478
2    2011/03/20 21:00~21:59                0.0464   0.0416       0.0443
3    2011/03/20 20:00~20:59                0.0470   0.0414       0.0443
4    2011/03/20 19:00~19:59                0.0468   0.0425       0.0445
..                      ...                   ...      ...          ...
[168 rows x 4 columns]

列見出しに階層構造があることがわかる。列名を表示してみる:

df.columns

MultiIndex([...],) のように出力される。

In [ ]: df.columns[0]
Out[ ]: ('測定日時(Measurement time)', '測定日時(Measurement time)')

In [ ]: df.columns[3]
Out[ ]: ('線量率 (dose rate)μGy/h (microgray per hour)', '平均値(average)')

このように,列名にあたる部分がtupleになっていることがわかる。したがって,一番右の列を取得するには

df['線量率 (dose rate)μGy/h (microgray per hour)', '平均値(average)']

とすればよいが,番号で df.iloc[:,3] でもよい。手っ取り早くプロットしてみよう:

import matplotlib.pyplot as plt

df.iloc[:,0] = [pd.Timestamp(x[:16]) for x in df.iloc[:,0]]
df.plot(0, 3)
plt.legend(['線量率(μGy/h)'])
plt.xlabel('')
plt.ylabel('')
plt.savefig('190929a.png', bbox_inches="tight")
新宿の線量率