Python + AWS Lambda + Line Notify で自動で毎朝Lineに本日のお天気を通知してみた。

#完成物
![Screenshot_2018-09-27-01-50-36.png](https://qiita-image-store.s3.amazonaws.com/0/157806/c8011042-877d-507e-81de-2029c9059e4a.png)
###こんな感じのものを毎朝通知してほしい！


# きっかけ
昨日の天気予報では、雨ではなかったのに、当日、雨予報に変わっている時、傘を忘れてしまう。
残念ながら私のキャンパスは駅から離れたど田舎キャンパスであるため、雨の日傘が無いと必然的に死んでしまう。

→さてどうしよう
→翌日の天気を通知してくれるアプリも無いことはない。
→だが、Android側のタスクキラーで弾かれたり、細かい設定がいじれない。
**→なら自分でつくろう** 　~~AWSのLambda使ってみたいし~~

**みなさんでも無料で構築可能です。是非挑戦してみてください。**
###こんな感じで実装
![bandicam 2018-09-27 14-58-41-060.jpg](https://qiita-image-store.s3.amazonaws.com/0/157806/c87c72b3-05ae-04d3-e58d-43aebdb51d20.jpeg)



# お天気情報取得からLineに通知

なんと先人がここまで実装してくださってました。
きれいなコードで見やすい。とてもありがたい。
　[Pythonで天気予報をLINE通知する](https://qiita.com/kutsurogi194/items/6b9c8d37b2b83fc2ce87)



# LineNotifyに登録
LineNotifyのAPIキーを取得します。
普段のLineアカウントで即登録できるのでとても早く取得できて驚き。
どうやらこれ自分以外にも送れそうなので、もしかしてめちゃくちゃ何かに使えるAPIなのでは・・・？(語彙力)

　[[超簡単]LINE notify を使ってみる](https://qiita.com/iitenkida7/items/576a8226ba6584864d95)



# Lambdaを構築
AWSに登録していない人はまず登録しましょう。
 [Amazon Web Service](https://aws.amazon.com/jp/)

**[注]色々説明が入りますが、私自身、AWS初心者のため認識が間違っている場合があります。**

AWSは基本は従量課金制ですが、Lambdaは個人使用ではなかなか消費できない量(一分間に何回も出来るレベル)の無料枠があるので、おそらく無料で出来ます！


###■まずLambda関数を登録しましょう
**エラーが出てますが、撮り忘れの写真をもう一度再現しただけなので、特に関係ありません。**

**終わったあとに気が付きましたが、ウェザーの綴りは「Weather」らしいです。。。**
![bandicam 2018-09-27 02-04-06-548.jpg](https://qiita-image-store.s3.amazonaws.com/0/157806/3d491cf8-90c0-ceb9-7086-16041148d7bd.jpeg)


登録するとこういった画面が出てきます。

![bandicam 2018-09-27 00-58-56-054.jpg](https://qiita-image-store.s3.amazonaws.com/0/157806/90a69770-6fd5-bbf9-f7c6-164d68776fb5.jpeg)
この画面の意味は、Whether_To_LineNotifyというLambda関数が存在して、Amazon CloudWatch Logsという機能が、そいつのログを監視しているよ~みたいな感じ(だと思います。)

その下にはこのようなエディタがあります。

![bandicam 2018-09-27 00-31-07-098.jpg](https://qiita-image-store.s3.amazonaws.com/0/157806/fa9efeed-23af-a37e-292e-4e2967003c68.jpeg)

画像右上のハンドラと書かれているのが、Lambdaが実行する関数です。
つまり、Lambda_functionのLambda_handler()を実行する。ということです。

**AWSはなんとCLIからちょこまか操作せずに、ブラウザ上でサクサク開発出来るんですね。。。驚きです。**(もちろんCLIからもデプロイ出来ます)



###■スクリプトを作成
上記のお天気情報をLineに通知するソースを少し編集しました。　[(Pythonで天気予報をLINE通知する)](https://qiita.com/kutsurogi194/items/6b9c8d37b2b83fc2ce87)

GitHub https://github.com/Yougurut/WhetherToLineNotify

Line Notify API Keyは環境変数を使ってるので、柔軟に書き直してください。
CITY_CODEをいじれば全国各地の天気予報が取得可能です。

```python:Lambda_function.py
import otenki

def lambda_handler(event, context):
    # TODO implement
    otenki.OtenkiNotify()
```

```python:otenki.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import json
import sys
import urllib.parse
import urllib.request
import datetime
import os

# weather's API
WEATHER_URL="http://weather.livedoor.com/forecast/webservice/json/v1?city=%s"
CITY_CODE="130010" # TOKYO

# LINE notify's API
LINE_TOKEN= os.environ.get("LINE_NOTIFY_API_KEY")
LINE_NOTIFY_URL="https://notify-api.line.me/api/notify"

def get_weather_info():
    try:
        url = WEATHER_URL % CITY_CODE
        html = urllib.request.urlopen(url)
        html_json = json.loads(html.read().decode('utf-8'))
    except Exception as e:
        print ("Exception Error: ", e)
        sys.exit(1)
    return html_json

def set_weather_info(weather_json, day):
    min_temperature = None
    max_temperature = None
    try:
        weather = weather_json['forecasts'][day]['telop']
        max_temperature = weather_json['forecasts'][day]['temperature']['max']['celsius']
        min_temperature = weather_json['forecasts'][day]['temperature']['min']['celsius']
    except TypeError:
        # temperature data is None etc...
        pass
    msg = "\n天気: %s\n最低気温: %s\n最高気温: %s" % \
               (weather, min_temperature, max_temperature)
    return msg

def send_weather_info(msg):
    method = "POST"
    headers = {"Authorization": "Bearer %s" % LINE_TOKEN}
    payload = {"message": msg}
    try:
        payload = urllib.parse.urlencode(payload).encode("utf-8")
        req = urllib.request.Request(
            url=LINE_NOTIFY_URL, data=payload, method=method, headers=headers)
        urllib.request.urlopen(req)
    except Exception as e:
        print ("Exception Error: ", e)
        sys.exit(1)

def OtenkiNotify():
    weather_json = get_weather_info()
    
    now = datetime.datetime.now() + datetime.timedelta(hours=9) ## GMT+9:00
    weekday = now.weekday()
    yobi = ["月", "火", "水", "木", "金", "土", "日"]
    msg_header = "\n本日" + str(now.date()) +"(" + yobi[weekday] + ")"

    msg = set_weather_info(weather_json, 0)
    print (msg_header + msg)
    send_weather_info(msg_header + msg)
    if("雨" in weather_json['forecasts'][0]['telop']):
        send_weather_info(msg_header+"\n☔☔☔☔☔☔☔☔\n今日は雨が降ります。\n傘を忘れずに！\n☔☔☔☔☔☔☔☔")
```
[(Pythonで天気予報をLINE通知する)](https://qiita.com/kutsurogi194/items/6b9c8d37b2b83fc2ce87)
との変更点は
・時間をawsのシステムと合わせる
・曜日を追加
・日本語に
・雨の日は追加で傘を持っていくように通知
といった内容です。

この2つのコードをrootに追加したあとに、上部のバーの保存ボタンを押したあとにテストしてみてください。~~最初保存ボタンを押して無くて10分ぐらい格闘してました~~

![bandicam 2018-09-27 00-36-29-589.jpg](https://qiita-image-store.s3.amazonaws.com/0/157806/58dff55c-b309-7d4a-053d-c0c73dcc967e.jpeg)

これで自分のLineアカウントに今日のお天気の通知が行けばOKです。


###■トリガー(予定)を登録。
先程のせたDesignerにCloudWatch Eventsというトリガーを追加します。
![bandicam 2018-09-27 00-27-31-791.jpg](https://qiita-image-store.s3.amazonaws.com/0/157806/f98b07fd-b3b9-453f-65b7-59a7a8888c44.jpeg)
CloudWatch Eventsというトリガーはどの時間・間隔でLambda関数を走らせるのか？というものです。

そのトリガーの設定はこんな感じで設定してあげます。
![bandicam 2018-09-27 00-28-42-569.jpg](https://qiita-image-store.s3.amazonaws.com/0/157806/4ea9bdca-8974-9278-49cf-0595c46e6afb.jpeg)

スケジュール式はcron(0 21 * * ? *)となっていますが、これは毎日UTC21:00(日本時間の朝6:00)にLambda関数を走らせるという意味です。

#結果
![Screenshot_2018-09-27-13-53-31.png](https://qiita-image-store.s3.amazonaws.com/0/157806/581c6bd5-73dc-355a-04f6-d44652630b18.png)
ちゃんと朝6:00に天気予報のLine通知が来ました。
これで雨の日に傘を忘れることが無くなる。。。はず！！！

**AWS初心者でも2時間ほどで実装できたので、雨の日の傘で困っている方は是非挑戦してください！！**