気象庁から情報を取得して東京23区の気象警報をSlackに通知する

どーも、おはこんばんちわ！

これは[Zapier Advent Calendar 2019](https://qiita.com/advent-calendar/2019/zapier) 5日目の記事です。


今回は、

- 23区の気象警報をいち早く察知したい！
- サードパーティのAPIではなく、より確からしい情報を参照したい！

という要望のもと、ちょっとしたZapをつくったので紹介させてもらいます。

こんなのをSlackに流してます :point_down: 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611/aa4689a8-01ec-3528-53c2-2ec155aae8b9.png)

## Zapの全体像
気象情報の取得には気象庁提供のデータを使い、フィルタリングしたりPythonでうまいことパースしたりしてSlackに通知します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611/a9b9877a-222b-30b6-a394-a20311c504ca.png)


## Zapの詳細
### フィードを取得してフィルタリングする
今回は、随時更新されるフィード
http://www.data.jma.go.jp/developer/xml/feed/extra.xml
を使います。

参照：[気象庁 \| 気象庁防災情報XMLフォーマット形式電文（PULL型）](http://xml.kishou.go.jp/xmlpull.html)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611/e5f04411-c07d-bbbe-d112-fe64b7c3d258.png)

ただ、このままだと災害情報以外にもいろんなものが含まれているのでフィルタリングします。
ここではタイトルが「気象特別警報・警報・注意報」の場合のみ次ステップに移行させています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611/20cad2b4-0769-a78e-4ba6-2bcaf098c2de.png)

### Pythonでデータを加工する
ZapierではJavaScriptかPythonのコードを実行できるんですが、xmlのパースにはPythonを使ったほうが良さそうだった（というかJavaScriptでは厳しそう）ので初めて書いてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611/40ce4a7d-b355-ca14-28b6-9c8381fa02f5.png)

```py
from xml.etree import ElementTree
response = requests.get(input_data['url'])
response.encoding = 'utf-8'
root = ElementTree.fromstring(response.text)

output = {'text': ''}
for item in root.findall('./{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Body/{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Warning/{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Item'):
  code = item.find('./{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Area/{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Code')
  if code.text == '130011' or code.text == '130012':
    area_name = item.find('./{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Area/{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Name')
    list = []
    for kind in item.findall('./{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Kind'):
      kind_text = ''
      kind_name = kind.find('./{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Name')
      if kind_name is None:
        continue
      if not '警報' in kind_name.text:
        continue
      kind_text += kind_name.text + '：'
      kind_status = kind.find('./{http://xml.kishou.go.jp/jmaxml1/body/meteorology1/}Status')
      kind_text += kind_status.text
      list.append(kind_text)
    if not list:
      continue
    text = '【' + area_name.text + '】' + '、'.join(list)
    print(text)
    output['text'] = output['text'] + text + "\n"
```

やってることは、

- 23区の情報だけ処理する
  - 地域コードが`130011`か`130012`
- 警報情報だけ処理する
- slack投稿用に整形したものを`text`にぶちこむ

です。Pythonというよりはxmlのnamespaceに結構苦戦しました。。


### さらにフィルタリング
「`text`が存在するか」でフィルタリングします。
（該当する情報がない場合は`text`が空になるため）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611/3ea9a289-6a6f-f3b2-5942-a3b697038de1.png)


### Slackに投稿する
あとはその`text`を所定のチャネルに投稿すればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/611/5f30d84d-48a3-22cb-4831-7ca3b104bcd7.png)


以上です :hugging: 

## 参考
- [気象庁 \| 気象庁防災情報XMLフォーマット](http://xml.kishou.go.jp/)
- [気象庁防災情報XMLフォーマット ｜ 技術資料](http://xml.kishou.go.jp/tec_material.html)