気象庁防災XMLのPull型提供（Atom Feed）について

**最初に要点:**

* 更新監視は HTTP If-Modified-Since を使って効率的に取得しましょう。
* 更新監視を毎分起動するならば、毎分20秒から始めるといいことあるかも。

2019-09-27 追加情報があります（品質について）： https://qiita.com/e_toyoda/items/2942903d406ed96c6bed
2021-12-16 HSTS化にご注意ください（速報。本稿はそのうち手を入れます）
https://qiita.com/e_toyoda/items/19b53286264cfe47ba9f
2022-02-01 試験用フィードについて記載

# はじめに

気象庁防災情報XML形式によるデータ公開は、2012年12月17日から始まった WebSub プロトコル（旧称PubSubHubub）による [PUSH 型提供](http://xml.kishou.go.jp/open_trial/index.html)に加えて、2017年3月からは Atom Feed により HTTPS GET だけで構築できる [PULL 型提供](http://xml.kishou.go.jp/xmlpull.html)が行われています。
2022年3月15日からは HSTS 化されます。

WebSub と異なり、利用者側で HTTP サーバを立ち上げて情報セキュリティリスクを背負い込む必要はありません。利用者機器は24時間稼働していなくても大丈夫です。通信遅延や情報抜けは問題ないように調整しました（近く報告します）。お試しください。

# フィード一覧

フィード内容に含まれる電文URLのリンクは、 ~~2022-03-15~~ 2022-03-10 からhttpsに変わります。

|名称|高頻度フィード|長期フィード|内容|
|:---|:---|:--|:--|
|定時|[regular.xml](https://www.data.jma.go.jp/developer/xml/feed/regular.xml)|[regular_l.xml](https://www.data.jma.go.jp/developer/xml/feed/regular_l.xml)|気象に関する情報のうち、天気概況など定時に発表されるもの|
|随時|[extra.xml](https://www.data.jma.go.jp/developer/xml/feed/extra.xml)|[extra_l.xml](https://www.data.jma.go.jp/developer/xml/feed/extra_l.xml)|気象に関する情報のうち、警報・注意報など随時発表されるもの|
|地震火山|[eqvol.xml](https://www.data.jma.go.jp/developer/xml/feed/eqvol.xml)|[eqvol_l.xml](https://www.data.jma.go.jp/developer/xml/feed/eqvol_l.xml)|地震、火山に関する情報|
|その他|[other.xml](https://www.data.jma.go.jp/developer/xml/feed/other.xml)|[other_l.xml](https://www.data.jma.go.jp/developer/xml/feed/other_l.xml)|上記３種類のいずれにも属さないもの|

## https試行用Atomフィード
リンクを https に替えたものをお試しいただけるよう、2022-02-01 から 2022-03-22 まで、下記のフィードが臨時に設けられます。

|名称|高頻度フィード|長期フィード|内容|
|:---|:---|:--|:--|
|定時|[regular.xml](https://www.data.jma.go.jp/developer/xml/https_feed/regular.xml)|[regular_l.xml](https://www.data.jma.go.jp/developer/xml/https_feed/regular_l.xml)|気象に関する情報のうち、天気概況など定時に発表されるもの|
|随時|[extra.xml](https://www.data.jma.go.jp/developer/xml/https_feed/extra.xml)|[extra_l.xml](https://www.data.jma.go.jp/developer/xml/https_feed/extra_l.xml)|気象に関する情報のうち、警報・注意報など随時発表されるもの|
|地震火山|[eqvol.xml](https://www.data.jma.go.jp/developer/xml/https_feed/eqvol.xml)|[eqvol_l.xml](https://www.data.jma.go.jp/developer/xml/https_feed/eqvol_l.xml)|地震、火山に関する情報|
|その他|[other.xml](https://www.data.jma.go.jp/developer/xml/https_feed/other.xml)|[other_l.xml](https://www.data.jma.go.jp/developer/xml/https_feed/other_l.xml)|上記３種類のいずれにも属さないもの|


# 高頻度・長期フィード2種類の使い分け

* 通常は高頻度フィードを使います。
    * 高頻度フィードは毎分更新されており、少なくとも直近10分間の更新情報が記載されています。
* 長期フィードは、１時間に１回更新されており、直近数日間の更新情報が記載されています。
    * これは（10分以上の）長時間にわたって止まっていた利用システムを最新状況に追随するために設けられています。たとえば利用者側システムが平日昼間保守になっていて、金曜夜に障害停止したシステムを月曜日に復旧するような場合を想定して、長時間の更新情報を提供することにしています。
    * ファイルが大きいので、常時ウォッチするとしんどいです。

# フィードの監視

フィードの URL に繰り返し HTTP GET 要求をすれば、Atom Feed 形式のファイルが取れるわけですが、ただ単に wget url で取得するのはちょっと待ってください。

* wget コマンドであれば、 -N オプションで、既存ファイルより新しい場合にだけダウンロードが行われます。
* curl コマンドであれば、 -z オプションで、既存ファイルより新しい場合にだけダウンロードが行われます。

これらは内部で If-Modified-Since ヘッダを付けて条件付き HTTP 要求を行い、ファイルが更新されていた場合にだけダウンロードするものです。みなさんのシステムの負荷軽減にもなりますし、正直言うと気象庁の経費的にも助かります。どうかご協力ください。

# 更新タイミング

**気象庁として保証するわけではありませんが**、経験上、フィードのファイルは毎分20秒頃に新しいものが見えるようになるようです。フィード取得プログラムを Linux の cron で毎分起動しているならば、**先頭に sleep 20; を入れてください**。それだけで１分早くデータが取れるようになります。

20より小さい数字を指定すると僕より秒単位で早く取れると思いましたか？　数秒早く要求しすぎると、古いレスポンスが返ってきてしまいます。その後60秒間はあなたのお使いのプロバイダの近くの CDN キャッシュサーバが古い応答を返し続けますから、たぶんお得にはなりません。

# Atom フィードの解析
Atom フィードは RFC 4287 https://tools.ietf.org/html/rfc4287 で規定されています。もちろん大真面目にやっていただいていいんですが、**気象庁として保証するわけではありませんが**、要は

* ファイルの中から「`<link type="application/xml" href="http://www.data.jma.go.jp/略/なんとか.xml"/>`」となっている所を全部抽出
* 初めて見る URL があったらダウンロードする

という雑なロジックでも動きます。なぜかというと次のように作られているからです。

* 個々の電文について ~~UUIDを割り当てて~~[2021-06-22修正: UUIDほどではないけれど予測不能な] URLを生成
* たとえ同一内容でも複数回受信したら別URLとなるので、 `<updated>` タグをチェックして更新されていたら再取得する必要はない

（なぜ電文のファイル名に~~UUIDみたいな意味不明~~[2021-06-22修正: 予測不能]なものを使っているかというと、ズバリ意味不明なのがミソで、通番や電文種別などで予測できるファイル名にすると、皆さん1秒でも早くほしいのでダメ元で取りに来られるので、404エラーログだけでディスクフルになってしまいかねないからです。申し訳ありませんが、迅速取得に王道はありません。AtomフィードからURLを取得して電文本体を取るようにしてください。）

# 最低限の取得スクリプト例

* わかりやすいようにシェルスクリプトです。長時間試験していません。
* 電文は /tmp (環境変数 $outdir で変更可能) に吐き出されます。
* 電文が取得済みかどうかは、ファイルがそこにあることでチェックしています。
    * 当然ながら**放置すると膨大なファイル数になります**。
    * この方法では、たとえ古いファイルを消してもディレクトリファイルが巨大化したり嫌なことになるので、真面目にはDBMSか何か使って、取得結果の電文数が増えていっても困らないようにしてください。**言いましたからね**。
* 毎分cronで起動するのが念頭にあり、先頭に20秒sleepが入れてあります。
* SSL証明書ディレクトリ /etc/ssl/certs ($ca で変更可能) があればHTTPSを使います。これにより偽サイトからデータを食わされる心配は減じるでしょう。

```shell:sample-wget.sh
#!/bin/sh
PATH=/bin:/usr/bin

: ${ca:='/etc/ssl/certs/'}
: ${outdir:=/tmp}
: ${magic:=20}
: ${feeds:='regular extra eqvol other'}

cd $outdir
if test -d $ca; then
  scheme=https
  caflag="--ca-directory=${ca}"
else
  scheme=http
  caflag=''
fi
server="${scheme}://www.data.jma.go.jp/developer/xml/feed"

sleep ${magic}

if test -f url.txt; then
  echo url.txt exists
  exit 0
fi
trap "rm -f url.txt" 0

for feed in ${feeds}
do
  feedurl="${server}/${feed}.xml"
  wget -qN ${caflag} ${feedurl}
  : > url.txt
  sed -n '/<link type="app/{s/.*href="//; s/".*//; p}' ${feed}.xml | while read url
  do
    base=`basename ${url}`
    if test ! -f $base; then
      echo $url >> url.txt
    fi
  done
  wget -qi url.txt
  : use data here
done
```

なお、このファイル sample-wget.sh を含め、実験に使っている取得ファイルを
https://github.com/etoyoda/feedfollow
に置いておきます。

# 追記： 2020-12-14 のファイル名パターンの変更について

2020年12月14日から、Atom Feed で指示される電文本体のファイル名が変更されています。

```
旧 urn:uuid:{uuid}
例 urn:uuid:74f4dc4d-5bc4-3f2d-9b54-69c689697b5a
新 {datetime}_{何だろう}_{ヘッダ}_{ランダム番号}.xml
例 20210701235020_0_VPRN50_010000.xml
```

正直僕もびっくりしたんですよ。

色々のインパクトがありますが、これは深く考えた気象庁の恒久的方針というわけではありません。サフィクスが .xml になったのは Windows では扱いやすくなったでしょうね。先頭文字が事実上 "2" で固定になったのは、たとえば S3 バケットに放り込んだ場合の検索効率が悪くなるという話を聞いたことがあります。ファイル名から内容が推測できるようになったことは、一通一通を見て重要性を見て管理したい人には快いことですが、そもそもDXなんだからそんなことに人手をかけるなよ。

それよりなにより、ファイル自動受信プログラムで、このファイル名パターンに依存しないように書くのは難しいことで、僕も気づかず依存していて、受信が止まった人もいるだろうし、暴走して大量アクセスを引き起こした人もけっこういる。こういうことを黙ってやってしまったのは、本当にいけないことだと思います。