Python
スクレイピング
python3
pillow

気象庁の一日の降水データを使ってgifを作成する

前回の記事に引き続き、降水ナウキャストの一日分の画像を一気に集めて、ひとつのgifを作成しようと思います。

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

本記事ではrequestsを使い画像をダウンロード、Pythonの画像処理ライブラリPillowを使いgifの作成までの一連のプログラムを紹介します。

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

・MacBook Air Early2015(MacOS High Sierra)
・Python 3.6.2(pip3)
・requests (pip3 install requests)
・Pillow (pip3 install PIL)
・datetime,glab,os (標準モジュール)

コード

画像データを採る

前回同様、気象庁の降水ナウキャストからデータを取得していきます。サイト訪問後、気象レーダーの画像を(MacのChromeでは)右クリックで「画像のURLをコピー」で画像のURLが取得できます。

取得したURLの以下の部分を組み替えることで、別の時刻のデータを取得できます。
201811091035

左から年、月、日、時、分となっており、5分間隔で更新、ゼロ埋めの処理を施す必要があります。まずは前日の年、月、日データまでをdatetimeを使って取得していきます。

import datetime 
time1 = (datetime.datetime.now() - datetime.timedelta(days=1))

#出力結果
2018-11-08 11:42:37.877244

datetime.datetime.now()で現在時刻の取得、-datetime.timedelta(days=1)で現在時刻の1日分の減算ができます。

time2 = datetime.datetime(year=time1.year, month=time1.month, day=time1.day)

#出力結果
2018-11-08 00:00:00

前日の00:00にセットします

time3 = [(time2 + datetime.timedelta(minutes=(5*i))).strftime('%Y%m%d%H%M') for i in range(288)]

#出力結果
['201811080000', '201811080005', '201811080010', '201811080015',..... '201811082355']

リスト内包表記を使って288回(5分毎に画像がアップロードされるので、12x24=288)rangeで回しつつ5分ずつ加算していきます。strftime('%Y%m%d%H%M')で取得した時間を任意のフォーマット(201811~)に変換します。time2でセットした00:00から5分間隔で一日分加算すると201811080000から201811082355までのデータがtime3に格納されていることがわかります。

以上で必要な時間データは取得できたので実際にURLとつなげて画像ファイルをダウンロードしていきます。

for i in time3:
    url = 'http://www.jma.go.jp/jp/radnowc/imgs/radar/000/{}-00.png'.format(i)
    req = requests.get(url)
    if req.status_code == 200:
        with open(i + '.png', "wb") as w:
            w.write(req.content)
            print('Downloaded --> {}'.format(url))
    else:
        print('Error --> {}'.format(url))

urlには画像URLに取得した時間データをはめたもの。reqでurlにリクエスト。statusが200だったものをpngでダウンロードしてローカルに保存。statusが200以外のものをエラーとして処理します。

gifを作成する

取得した一日分の画像データを使ってgifを作成していきます。まず画像ファイルを操作するためのglabとそれを処理するための画像ライブラリPillowをインポートします。

import grob
from PIL import Image

Pillowを使ったgif作成のコードですが、以下の記事を参考にしました。
Python PillowでPNGからGIFを作る

files = sorted(glob.glob('*.png'))
images = [Image.open(i) for i in files]
images[0].save(file_name, save_all=True, append_images=images[1:], duration=50, loop=0)

Image.save()の引数durationはフレームの表示時間をミリ秒で指定、loopはgifのループ回数で0の場合は無限ループとなります。

完成形

import requests,datetime,glob,os
from PIL import Image

def get_image():
    time1 = (datetime.datetime.now() - datetime.timedelta(days=(1)))
    time2 = datetime.datetime(year=time1.year, month=time1.month, day=time1.day)
    time3 = [(time2 + datetime.timedelta(minutes=(5*i))).strftime('%Y%m%d%H%M') for i in range(288)]
    for i in time3:
        url = 'http://www.jma.go.jp/jp/radnowc/imgs/radar/000/{}-00.png'.format(i)
        req = requests.get(url)
        if req.status_code == 200:
            with open(i + '.png', "wb") as w:
                w.write(req.content)
                print('Downloaded --> {}'.format(url))
        else:
            print('Error --> {}'.format(url))

def make_gif():
    file_name = (datetime.datetime.now() - datetime.timedelta(days=1)).strftime('%Y-%m-%d') + '.gif'
    files = sorted(glob.glob('*.png'))
    images = [Image.open(i) for i in files]
    images[0].save(file_name, save_all=True, append_images=images[1:], duration=50, loop=0)
    [os.remove(f) for f in files]

if __name__ == '__main__':
    get_image()
    make_gif()

実行すると以下のようなgifが保存されていると思います。


最後に

一回のプログラムで288枚の画像をダウンロードするので、新しくディレクトリーを作ってその中で実行したほうが良さそうです。筆者の調べですが気象庁の降水ナウキャストの画像データは最大で5日前まで遡ることができました。あとプログラミングを初めて1年近く経ちますが重い腰を起こしてようやくgithubを動かしてみたので一応リンク貼っておきます。

https://github.com/0x0u/rainfall