Closed hrsano645 closed 4 years ago
xmlフォーマットの情報 気象庁防災情報XMLフォーマット | 技術資料
DLできるxmlファイルの提供元 気象庁 | 気象庁防災情報XMLフォーマット形式電文(PULL型)
個々にあるatomフィードの長期フィード、定時のリンクで良いともう
気象台の天気予報はuuidが降られている。これが同じなら、このフィードを見に行く必要はなく、全国の気象台からの予報xmlファイルを取りに行けばよいと思う。
各気象台のxmlファイルで定義されている地域名を元に天気botが答えてくれるようにするのが理想。時間なければ気象台の都道府県で...
atomフィードの中身は、必要に応じて出てくる情報もあるっぽい。
uuidが固定っぽいのもなんとなくわかってきたが、観測や情報公開の時に割り当てされるらしくて、例えば静岡の天気予報は常時同じuuidでは取れないっぽい。
調べを進めていくと、気象庁XML電文をREST APIで取得できることも分かった。先端IT活用推進コンソーシアム(AITC)(旧XMLコンソーシアム)という組織が公開している
参考(とてもありがたい情報源): https://gist.github.com/uemuraj/06f2269f00d60688b77bfa3de6e1edd0
検索するAPI側を調べてみると
府県天気予報
や府県週間天気予報
と入れる
http://api.aitc.jp/jmardb-api/search?datetime=2020-07-28 00:00:00&datetime=2020-07-29 00:00:00&order=new&title=府県週間天気予報
http://api.aitc.jp/jmardb-api/search?datetime=2020-07-28 00:00:00&datetime=2020-07-29 00:00:00&order=new&title=府県天気予報
.json
に変えるとjsonとしてDL可能今日半日ぐらいアクセスしてみて感じたこと
areaname
, areacode
なる地域指定ができるようになっているが、天気予報ではできないっぽい。府県週間天気予報
では areaname_meta
, areacode_meta
はできた。http://api.aitc.jp/jmardb-api/search?datetime=2020-07-28 00:00:00&datetime=2020-07-29 00:00:00&order=new&areaname_mete=静岡県&title=府県週間天気予報
府県週間天気予報
の結果: 今日を基準に1週間分の予報を出す。府県天気予報
は地域を絞ることができないので、検索結果から地域を見ながら探索しないといけない最終的には、地域を絞った週間天気予報を使って最新の結果を取得することにした。 検索可能な地域名を作っておけば何とかなりそう。府県のみを対象にしておく。
APIの検索で、一部の地域(東京都とか)を取得することができない状態がわかったので、やはり気象庁xmlのatomフィードからとりに行った方が楽かもしれない。
試しに、atomフィードから週間天気予報のみの最新一覧を出すスクリプトを書いてみた(非常に雑)
# coding: utf-8
import itertools
from bs4 import BeautifulSoup
# あらかじめatomフィードのxmlはDLしてる
with open("regular_l.xml", encoding="utf-8") as jma_xmlfile:
soup_jma_xml = BeautifulSoup(jma_xmlfile, "xml")
# entityから、府県週間天気予報 > 各気象台の情報を一覧でだして、最新の予報の電文xmlを探しに行く
tenki_list = list()
# 週間予報のみのリストを作る
yohou_list = sorted(
[e for e in soup_jma_xml.find_all("entry") if e.find("title", text="府県週間天気予報")],
key=lambda e: e.author.text,
)
# groupbyで地域事の週間天気予報の電文をまとめる
station_by_yohou_list = itertools.groupby(yohou_list, lambda e: e.content.text)
for name, g in station_by_yohou_list:
content = name
list_g = list(g)
# ソートで最新の週間天気予報の電文を取りに行く
g_new = sorted(list_g, key=lambda e: e.updated.text, reverse=True)[0]
updated = g_new.updated.text
new_url = g_new.link["href"]
print(f"{content}: updated:{updated} new_url:{new_url}")
tenki_list.append(f"{content}: updated:{updated} new_url:{new_url}\n")
with open("export_tenki_list.txt", "w", encoding="utf-8") as export_file:
export_file.writelines(tenki_list)
気象庁のxmlのパースに苦労してしまって(xmlそんなに扱ってない故です...)進捗が悪すぎたので、AITCのAPIでも試してみる。
APIの検索で、一部の地域(東京都とか)を取得することができない状態がわかったので、やはり気象庁xmlのatomフィードからとりに行った方が楽かもしれない。
これは、検索で地域別で取れたほうが楽だったからだけど、そもそもbotが毎回リクエストを打つのはよくないので、地域ではなく全国レベルで全部取得したほうが早いと思う。
気象庁のXMLのみで週間予報の一覧を出せるようにするスクリプト:
AITCのAPIのみで週間予報の一覧を出せるようにするスクリプト:未完成。途中で各気象台のjsonファイルがDLできないときがあるのであきらめた
気象台名と地域名のマッピングを考えていたけど、当初はこうしようとした
KISYODAI_STATION_MAPS = {
"東京都府県週間天気予報": ["東京", "東京地方"],
"宮崎県府県週間天気予報": ["宮崎", "宮崎県"],
"岡山県府県週間天気予報": ["岡山", "岡山県"],
"千葉県府県週間天気予報": ["千葉", "千葉県"],
"栃木県府県週間天気予報": ["栃木", "栃木県"],
"三重県府県週間天気予報": ["三重", "三重県"],
"福島県府県週間天気予報": ["中通り・浜通り"],
"茨城県府県週間天気予報": ["茨城", "茨城県"],
"新潟県府県週間天気予報": ["新潟", "新潟県"],
"八重山地方府県週間天気予報": ["八重山地方"],
"熊本県府県週間天気予報": ["熊本", "熊本県"],
"岐阜県府県週間天気予報": ["岐阜", "岐阜県"],
"鳥取県府県週間天気予報": ["鳥取", "鳥取県"],
"群馬県府県週間天気予報": ["群馬", "群馬県"],
"長野県府県週間天気予報": ["長野", "長野県"],
"石川県府県週間天気予報": ["石川", "石川県"],
"奈良県府県週間天気予報": ["奈良", "奈良県"],
"山梨県府県週間天気予報": ["山梨", "山梨県"],
"兵庫県府県週間天気予報": ["兵庫", "兵庫県"],
"大東島地方府県週間天気予報": ["大東島地方"],
"青森県府県週間天気予報": ["津軽"],
"佐賀県府県週間天気予報": ["佐賀", "佐賀県"],
"京都府府県週間天気予報": ["京都", "京都府"],
"福岡県府県週間天気予報": ["福岡", "福岡県"],
"山口県府県週間天気予報": ["山口", "山口県"],
"宮古島地方府県週間天気予報": ["宮古島地方"],
"岩手県府県週間天気予報": ["岩手", "岩手県", "内陸"],
"長崎県府県週間天気予報": ["長崎", "長崎県"],
"大阪府府県週間天気予報": ["大阪", "大阪府"],
"大分県府県週間天気予報": ["大分", "大分県"],
"沖縄本島地方府県週間天気予報": ["沖縄", "沖縄本島地方"],
"埼玉県府県週間天気予報": ["埼玉", "埼玉県"],
"石狩・空知・後志地方府県週間天気予報": ["石狩・空知・後志地方"],
"高知県府県週間天気予報": ["高知", "高知県"],
"網走・北見・紋別地方府県週間天気予報": ["網走・北見・紋別地方"],
"山形県府県週間天気予報": ["山形", "山形県"],
"島根県府県週間天気予報": ["島根", "島根県"],
"愛知県府県週間天気予報": ["愛知", "愛知県"],
"釧路・根室・十勝地方府県週間天気予報": ["釧路・根室地方"],
"愛媛県府県週間天気予報": ["愛媛", "愛媛県"],
"福井県府県週間天気予報": ["福井", "福井県"],
"渡島・檜山地方府県週間天気予報": ["渡島・檜山地方"],
"宗谷地方府県週間天気予報": ["宗谷地方"],
"広島県府県週間天気予報": ["広島", "広島県"],
"徳島県府県週間天気予報": ["徳島", "徳島県"],
"上川・留萌地方府県週間天気予報": ["上川・留萌地方"],
"鹿児島県府県週間天気予報": ["鹿児島", "鹿児島県", "鹿児島県(奄美地方除く)"],
"滋賀県府県週間天気予報": ["滋賀", "滋賀県"],
"静岡県府県週間天気予報": ["静岡", "静岡県"],
"富山県府県週間天気予報": ["富山", "富山県"],
"宮城県府県週間天気予報": ["宮城", "宮城県", "東部"],
"胆振・日高地方府県週間天気予報": ["胆振・日高地方"],
"和歌山県府県週間天気予報": ["和歌山", "和歌山県"],
"神奈川県府県週間天気予報": ["神奈川", "神奈川県"],
"秋田県府県週間天気予報": ["秋田", "秋田県"],
"香川県府県週間天気予報": ["香川", "香川県"],
}
ただこれだと問題があって、キーとなる地域名と、気象台の一致はいいけど、キーとなる地域名と気象台が複数ある場合に困る。 わかりやすいのは北海道になる。 例: 北海道 -> 石狩とか釧路とか網走とかが対象になるけど、この方法だと北海道というあいまい検索はできない。
なので、以下のようにしたらいいかも。地域名(station_name)と気象台名(kisyodai_name)を辞書で両方とも複数対応しておく。天気情報を出すときに、気象台の複数の情報がリストアップされてしまうがしょうがない?
KISYODAI_STATION_MAPS = [
{"station_name":["地域名1", "地域名2"], "kisyodai_name":["気象台名1", "気象台名2"]}
]
今回は、マッピングを考えている時間もそれほどないので、正しさに目をつぶっておく...余裕があったら対応したい。 (この辺は多分VUI的な方面を見ておくと対応しやすかったかもしれない。)
天気botの実体部分の今日の進捗。大体できてきたので、詰めてからテストを書いてみる
このときに、テスト用のxmlファイルを用意したくて、固定にしたい。 なので、予めDLしてあるファイルパスあたりをpytestのmonkeypatch.setattrで置き換えられるといいかも。 https://thinkami.hatenablog.com/entry/2017/03/07/065903
pytestでテストを用意する
使うモジュールはこれ
テストする項目を仮ぎめ
とりあえずの動くテストが作れた。雑なassertなので、上で決めたことをちゃんとやること。
monkeypatchを全部で動かすのが面倒なので、fixtureも使ったw
今回の天気botは動作がかなり遅いので、slackbotのEvents APIのレスポンス再送条件に当たる可能性が高い(というかテスト中にしょっちゅうあたってる)
なので、xmlファイルをDLする前にレスポンスしてしまって、xmlファイルのDLが終わって天気が見れるようになったら結果を返すようにしたほうがいいかも。今のbotの共通のハンドル関数だとできないから何らかの変更が必要...
共通ハンドル関数をasyncにして、何度かメッセージを受け取れるようにするとか?APIの処理待ちをするときはそれがいいはず。
現在の方法でやることにした
https://github.com/py-suruga/pycon-jp-2020-tutorial/issues/9#issuecomment-664775513 より、Livedoor天気APIがサービス終了するとのことで、気象庁の天気予報情報を使うbotに変更する。
やらないといけないこと(2020-07-28時点