気象庁HPで公開されているJSONを読んでTwitterに掲載してみた。
みなさん、こんにちは!
今日は、以前行われた日本の気象庁HP変更の際に、いつの間にか実装されてたAPIを時間起動で取得してAWS LambdaからTwitterに配信する。というところを作ってみたので、ご紹介します!
きっかけ
きっかけは気象庁のHPが更新された際に、気象庁の中の人が拾ったこのTweetからでした。
ということで、どんなものなのか。
簡単にみてみると、結構いろんなものがありました。
アメダスや天気予報はもちろん、、、防災情報だと
・台風
・注意報・警報・特別警報
・火山の警報・注意報・予報
火山があるということは、火山の緯度経度やCodeなどが入ったJSONももちろんありました!
アメダスがあるということは、アメダスの緯度経度や読み方、タイプ情報の入ったJSONもありました!
今回はその中でもアメダスと天気予報のJSONを取得し、Twitterで配信するというものを作りました。
ということで、今回書いたコードはこちら。
import json
from datetime import datetime, timedelta, timezone
import requests
import os
import tweepy
import glob
import re
#****には自身のコードを入力してください
api_key = os.environ['API_KEY']
api_secret_key = os.environ['API_SECRET']
access_token = os.environ['token']
access_secret_token = os.environ['secret_token']
dt = datetime.now()
# 認証を行う
auth = tweepy.OAuthHandler(api_key, api_secret_key)
auth.set_access_token(access_token, access_secret_token)
def lambda_handler(event,context):
JST = timezone(timedelta(hours=+9), 'JST')
dt_jst = datetime.now(JST)
url = "https://www.jma.go.jp/bosai/forecast/data/forecast/130000.json"
amedas = "https://www.jma.go.jp/bosai/amedas/data/map/"
time = dt_jst.strftime('%Y%m%d%H')
now_hour = dt_jst.strftime('%H')
output = '/tmp/' + "jma.json"
ame_out = '/tmp/'+"ame.json"
res = requests.get(url)
res2=requests.get(amedas+time+"0000.json")
api_response = res.json()
api = res2.json()
with open( output, mode='w') as file:
json.dump(api_response, file,ensure_ascii=False, indent=1)
with open( ame_out, mode='w') as f:
json.dump(api, f,ensure_ascii=False, indent=1)
file = open(output)
file2 = open(ame_out)
test = file.read()
test2 = file2.read()
value = json.loads(test)
value2 = json.loads(test2)
#地点名
name= value[0]['timeSeries'][0]['areas'][0]['area']['name']
#日付1行目
time = value[0]['timeSeries'][0]['timeDefines'][0]
tdatetime = dt.strptime(time, '%Y-%m-%dT%H:%M:%S+09:00')
date = str(tdatetime.year)+"年"+str(tdatetime.month)+"月"+str(tdatetime.day)+"日 "+str(tdatetime.hour)+"時発表 "
#気象1行目
wx = value[0]['timeSeries'][0]['areas'][0]['weathers'][0]
text_wx = re.sub(r"\s", "", wx)
#風
wind = value[0]['timeSeries'][0]['areas'][0]['winds'][0]
text_wind = re.sub(r"\s", "", wind)
#日付2行目
time2 = value[0]['timeSeries'][0]['timeDefines'][1]
tdatetime2 = dt.strptime(time2, '%Y-%m-%dT%H:%M:%S+09:00')
date2 = str(tdatetime2.month)+"月"+str(tdatetime2.day)+"日 "+str(tdatetime2.hour)+"時以降は"
#気象1行目
data2 = value[0]['timeSeries'][0]['areas'][0]['weathers'][1]
text2 = re.sub(r"\s", "", data2)
#amedas
tokyo = value2['44132']['temp'][0]
out = date+name + " 今の天気は " + text_wx +" 風は、"+text_wind+" "+date2+ text2 +"。 現在"+now_hour+"時の東京の気温は"+str(tokyo) +"度です。(気象庁HPより)"
print(out)
api = tweepy.API(auth)
test = api.update_status(out)
print(output)
#立つ鳥跡を濁さず
for p in glob.glob('/tmp/' + '*.json'):
if os.path.isfile(p):
os.remove(p)
print("===End===") # for debug
なんか説明するより、コード見せた方が早い。と思って、貼りました。
説明欲しいかたは、このまま見ていただけますと幸いです。
ここでは、概況っぽいデータとアメダスのデータの2つを取得して組み合わせています。
概況データって、どんなデータ?
コードだけ見せられても、という感じだと思いますので、まずここで取得しているデータを説明します。
まず、こちらが気象庁HPで誰もが見れるものです。
こちらには、天気マーク、天気を文字で表したもの、風、波、降水確率、気温の要素が、今日・明日・明後日の3日分あります。
そして、上記のプログラムで取得しているJSONがこちら。
東京のデータを取得したい時には、130000.json としてあげます。
インデント入っていないので分かりにくいですが、よくよく見ると、weathersのところに上記のHPに書かれているものと同じものが入っています。
あとは、更新時刻だけなのですが、気象庁の発表時刻は日本時間の5時、11時、17時の3回発表。
と言いたいところですが、データを見ていると、どうやら毎時発表されて若干、ビミョーーーに内容が変わっているっぽい。
(まじか、、、と思いました)
アメダスのJSONデータは?
アメダスも、気象庁HPだと日本地図の上に気温や湿度、降水量などが以下のように記されている感じです。
アメダスは気象庁から配信されているデータは10分おきに観測しているため、こちらのAPIも10分おきになっています。
(気象庁的には、1分値や10秒値も持ってるっぽいけどなぁ ぼそっ)
ただ、10分おきとはいえ、時間を与えてあげる必要があるため、Python上では、
amedas = "https://www.jma.go.jp/bosai/amedas/data/map/"
time = dt_jst.strftime('%Y%m%d%H')
res2=requests.get(amedas+time+"0000.json")
という形にして、時間変数を持たせています。
そして、この時に気をつけないといけないのは、、、
例えばですが、
12:00に観測したデータは12:00にプログラムを回しても取得できません!
もう一度言います。
12:00に観測したデータは12:00にプログラムを回しても入っていません!
自分もたまに陥るのですが、12:00に観測したデータを一度気象庁に集めて、
「データの確からしさ」を見て、問題ないということであれば配信する。という流れです。
なので、12:00に観測されたデータは大体12:10頃、すなわち10分遅れで配信されます。
そこを考慮したLambdaのEventBridgeを作る必要がありますね。
自分はそこまで頻繁にはしなくていいかな。。。
ということで、2時間に1回(rate 2 hours)、18分頃に取得して配信をしています。
ということで、ざっくりとですが、これをヒントにしてやれば、あなたもbotになれます(キリッ)