ホーム > Data manipulation / データ操作

Seleniumを使って花粉の飛散状況を確認する

今年も花粉のスギ季節がやってきました。別に花粉が飛んでるか飛んでないかなんて知ったところで症状が変わるわけではないものの、データが公開されているならばこれを取得してみようかという気になるもの。…ならない?

環境省花粉観測システムはなこさん

「はなこさん」て。。。役所もずいぶん柔らかくなったものだ。と、サイトを訪れてみたらそうでもなかった。

環境省花粉観測システム(愛称:はなこさん)

このサイト、国内の各観測拠点で一時間おきに計測した花粉飛散量を、2月から5月(北海道と東北は3月から)の間、毎日提供し続けます。

残念ながらAPIでデータを取り出すことはできず、csvファイルをダウンロードする形です。

Seleniumを使う

このダウンロードデータ、あらかじめリンクが用意されていないので、単純なスクレイピングでは取得することができません。

指示に従ってJavascriptがデータ生成するので、いつものcurlでは結果が読み取れません。Javascript実行環境が必要なのです!

そこでSelenium。ChromeなどのブラウザをHeadlessモード(バックグラウンド動作)で動かして、Javascriptで生成されたhtmlコードを取得しましょう。

必要なものは以下のとおり。

  • ChromeやFirefoxなどのようなHeadlessモードで動くブラウザ
  • ブラウザを操作するためのドライバ。Chromeならchromedriver
  • pythonなどのスクリプトでブラウザ操作を記述するためのselenium

pythonのパッケージシステムpipでSeleniumを入れて、OSのパッケージシステムでchromedriverを入れると使えます。CentOSならyumね。

1
2
yum install google-chrome-stable
pip install selenium chromedriver-binary

Chromeとchromedriverのバージョンが違うとうまく動かなかったりするので、google-chrome --versionで表示されたバージョンのchromedriverを入れると幸せになれます。

~=はニアリーイコールね。

1
php install chromedriver-binary~='80.0.3987'

Pythonスクリプトを書く

Selenium自体はいろんなスクリプト言語から呼び出し可能なのですが、Pythonで呼ぶのが無難かも。ということで、新宿の飛散状況を取得するPythonスクリプト。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import io,sys
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
import time
from selenium import webdriver

options = webdriver.ChromeOptions()
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)

driver.get('http://kafun.taiki.go.jp/DownLoad1.aspx')
time.sleep(5)
driver.execute_script("document.getElementById('CheckBoxMstList_16').checked = true;")
time.sleep(5)
driver.execute_script("document.getElementById('hyoji').click();")
time.sleep(5)
print(driver.page_source)

driver.close()
driver.quit()

2行目のように文字コードを指定しておかないと、コードが違った場合にPythonが次のようなエラーを吐いて止まります。

1
2
3
4
Traceback (most recent call last):
File "/home/takeru/script/kafun.py", line 13, in <module>
print(driver.page_source)
UnicodeEncodeError: 'ascii' codec can't encode characters in position 22-28: ordinal not in range(128)

それから適宜time.sleep(5)などと待ち時間を入れておかないと、サイトが混み合っていてhtmlのレンダリングが遅れたときにエラーで止まります。ちなみにこの待ち時間を入れるためにはimport timeを指定する必要があります。

10行目でダウンロードページを開いて、12行目で新宿の観測地点を選択し、14行目でデータ表示ページを開いています。ダウンロードリンクをクリックできれば良かったのですが、うまく動かなかったのでこうなりました。

##Seleniumを自動実行
先程のPythonスクリプトを定期的にcronで実行して最新の花粉飛散状況を抽出しましょう。はなこさんは毎時35分頃データを更新するので、朝7時から夜7時台まで毎時45分にSeleniumを実行します。

1
45 7-19 * * *   python3 /home/takeru/script/kafun.py | grep -e '新宿区' | sed 's/<.[^>]*>/,/g' | cut -d ',' -f 12,14,16,18 > /tmp/kafun.csv

こうして得たデータはこんな感じ。

1
2
3
4
5
新宿区役所第二分庁舎,20200201,01,4
新宿区役所第二分庁舎,20200201,02,4
...
新宿区役所第二分庁舎,20200308,08,0
新宿区役所第二分庁舎,20200308,09,0

tail -n 1 などで最新情報を抽出できます。phpで取るならこんな感じ。

1
2
3
if(file_exists('/tmp/kafun.csv')){
$value = end(file('/tmp/kafun.csv'));
}

このあと適当にデータを加工すれば毎時の花粉飛散状況を表示できますよ。