Python
スクレイピング
python3

降水ナウキャスト(気象庁)をスクレイピングして5分毎の降水データ取得する

気象庁の「高解像度降水ナウキャスト」の画像部分

スクリーンショット_2018-07-05_11_04_07.png

がなんか便利そうだったのでスクレイピングしてどうにか(今回はLINEに送ってみるゾ)してみます。

気象庁コンテンツの利用について
データの二次利用は自由ですが一応一読しました。

「5分毎に更新」とありますが実際は1分ずれているので、crontab等で自動実行する場合は1,6,11,16... * * * *のように1分から始まり5分刻みに登録したほうが良さそうです。

環境と使用するモジュール

・MacBook Air Early2015(MacOS High Sierra)

・Python 3.6.2(pip3)

・requests(pip3 install requests)

・datetime(標準モジュール)

画像をダウンロードする

ナウキャストのページで画像を右クリック、画像アドレスをコピーで画像のURLが取得できます。

http://www.jma.go.jp/jp/radnowc/imgs/radar/000/201807051055-00.png

URLの「201807051055」の部分を変更してリクエストを飛ばします。一見unixタイムかと思いましたが、単純に年月日時分の順に並んでいるだけなので変換作業はありません。

import requests
from datetime import datetime

def get_image():

    time = list(datetime.now().strftime("%Y%m%d%H%M"))
    m = int(time[-1])
    if m > 0 and 5 > m:
        time[-1] = '0'
    else:
        time[-1] = '5'
    time = ''.join(time)

    url = 'http://www.jma.go.jp/jp/radnowc/imgs/radar/000/' + time + '-00.png'
    req = requests.get(url)
    with open('rain.png', "wb") as w:
        w.write(req.content)
        w.close()

まず時間の処理ですが、気象庁は5分刻みに更新しているのでURLの「201807051055」部分を現在時刻に置き換えて、末尾の5の部分(分の一桁台)を0か5に加工する必要があります。(crontabで実行することを前提とし、1分ずらしてからプログラムを実行するために現在時刻ではつじつまが合わない)

get_image()の時間の処理を少し分解して考えてみます。まず変数timeをlistしないで出力させると以下のように現在時刻の数字のみが表示されます。

time = datetime.now().strftime("%Y%m%d%H%M")

#出力結果
201807051209

この末尾を0か5かに置き換えたいのですが、特定の位置にある文字列を入れ替えるメソッドが無かった(もしあったら教えてください。。)のでリストに変換してからインデックスを指定して文字列を入れ替えます。

リストの末尾をインデックスで指定し数値に変換してから変数mに格納します。

mが0以上で5以下だったらtimeの末尾に0を代入(crontabで1分、11分、21分に実行した場合0,10,20になるように)、それ以外は5を代入します。(6分、16分、26分に実行した場合5、15、25になるように)

最後に変数timeに加工したリストを文字列に戻して代入します。

m = int(time[-1])

if m > 0 and 5 > m:
    time[-1] = '0'
else:
    time[-1] = '5'

time = ''.join(time)

あとは画像をダウンロードする処理で、先程加工した変数timeをurlにはめ込んでリクエストをおくるだけです。

url = 'http://www.jma.go.jp/jp/radnowc/imgs/radar/000/' + time + '-00.png'
req = requests.get(url)
with open('rain.png', "wb") as w:
  w.write(req.content)    

実行すると以下のように画像が保存されます。

rain.png

あとは煮るなり焼くなり。。。

おまけ(Messaging APIを使ってLINEに送る)

LINEに通知を送るテンプレとして一応置いておきます。
Messaging APIの記事は探せばたくさんあるので割愛。基本的には変数line_notify_tokenに自分のアクセストークンを入れればおk。

def line(me):
    line_notify_token = 'hogehogecheese'
    line_notify_api = 'https://notify-api.line.me/api/notify'
    message = '\n' + me
    payload = {'message': message}
    files = {"imageFile": open("rain.png", "rb")}
    headers = {'Authorization': 'Bearer ' + line_notify_token}
    line_notify = requests.post(line_notify_api, data=payload, headers=headers, files=files)

全体像

import requests
from datetime import datetime


def get_image():
    time = list(datetime.now().strftime("%Y%m%d%H%M"))
    m = int(time[-1])
    if m > 0 and 5 > m:
        time[-1] = '0'
    else:
        time[-1] = '5'
    time = ''.join(time)
    url = 'http://www.jma.go.jp/jp/radnowc/imgs/radar/000/' + time + '-00.png'
    req = requests.get(url)
    with open('rain.png', "wb") as w:
        w.write(req.content)


def line(me):
    line_notify_token = 'hogehogecheese'
    line_notify_api = 'https://notify-api.line.me/api/notify'
    message = '\n' + me
    payload = {'message': message}
    files = {"imageFile": open("rain.png", "rb")}
    headers = {'Authorization': 'Bearer ' + line_notify_token}
    line_notify = requests.post(line_notify_api, data=payload, headers=headers, files=files)


if __name__ == '__main__':
    get_image()
    line('降水情報')

実行結果〜

写真 2018-07-05 12 58 48.jpg

crontabで時間指定して自動実行する際の設定(5分刻み)

1,6,11,16,21,26,31,36,41,46,51,56 * * * * pythonのpath 実行ファイルのpath

とりあえずやりたいことはできたので今回はここまでにします。気象庁のデータを触るのはなかなかおもしろかったので別の機会にまた挑戦してみます。