1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Python/AWS】第1回 LambdaとOpenWeatherMapで天気予報を自動ツイートする【データ分析】

Last updated at Posted at 2022-10-12

1. はじめに

本記事は【Python/AWS】の第1回として、
AWSのサービスを利用した一連のデータ分析の初回となります。

私自身、AWSのサービスを触るのは初めてなので、
細かい説明など不足する点はあるかと思いますが、
大まかな流れをこちらで解説していきたいと思います。

5回ほどに分けて投稿していく予定ですが、
分析の全体像は以下のようになります。
AWSアーキテクチャ.PNG
全体の分析目的は前回の分析から継続/発展して、
「Splatoon3」におけるコンテンツのユーザー満足度調査 です。

収集したデータから項目ごとに感情分析を行い、
ポジティブ/ネガティブの値を可視化することが最終目的です。

▼前回の記事はこちら▼

1-1. 本記事の概要と目標

初回のテーマは「AWS Lambdaの活用」ということで、
前回トピック分析でも利用したTwitterAPIと組み合わせ、
天気予報を自動ツイートしてくれる仕組みを作ります。

今回作成するパートのイメージはこのような形です。
天気予報アーキテクチャ.png

使用するサービスとそれぞれの役割は以下の通りです。
Aystem Maneger: TwitterAPIのkeyなどを安全に保管するために使用
Watch Cloud: Lambdaを実行するタイミングをコントロールするために使用
AWS Lambda: Pythonスクリプトを実行するためのサービス
OpenWeatherMap: 天気に関わる情報を取得できるAPI(AWSサービスではない)

なお本記事ではAWSの登録方法や、
サービス利用に必要な初期設定は取り上げていません。
必要に応じて以下の記事を参考にして下さい。

▼AWSへの登録/IAMロールの作成▼

1-2. 自動実行の流れ

自動実行の順番、流れとしては以下の通りです。
1.Watch Cloudにて毎朝8:00にトリガー
2.Lambdaのスクリプト内で以下を実行
3.System Managerで保管していたTwitterAPIを取得
4.OpenWeatherMapから天気情報を取得
5.取得した天気情報を文章に含めて自動ツイート

2. 実装

大まかなと説明の流れとして、
1.TwitterAPIのkeyをssmに保管
2.Lambda_functionの作成
3.Lambdaへのデプロイ
4.テスト
5.cloud watchの設定
の5段階に分けて確認をしていきます。

2-1.ssmにパラメータを保管

ssm.png
TwitterAPIのkeyやtokenは情報漏れが怖いため、
"Systems Manager""parameter store"を使用します。

なお自分がparameter storeを使用した際、
bearer_tokenの文字列が長すぎたためか、
全てを一つにまとめるとうまくいきませんでした。

そのためbearer_tokenのみ、単体で保管しているという状況です。

▼ssm利用時に参考にしたリンク▼

2-2.Lambda_functionの作成

まずは以下がコードの全体像となっています。

Lambda_function.py
import sys
# tweepyをインストールしたディレクトリ相対パスを指定する
sys.path.append('./python_package')
# coding: UTF-8
import json
import tweepy
import boto3
import datetime
from pyowm.owm import OWM
from pyowm.utils.config import get_default_config
from statistics import mode

ssm = boto3.client('ssm', "ap-northeast-1")
weekday_dict = {0:"月曜日", 1:"火曜日", 2:"水曜日", 3:"木曜日", 4:"金曜日", 5:"土曜日", 6:"日曜日"}

def lambda_handler(event, context):
    response = ssm.get_parameters(Names=["/credentials/twitter"], WithDecryption=True)
    params = json.loads(response['Parameters'][0]['Value'])
    bearer_res = ssm.get_parameters(Names=["bearer_token"], WithDecryption=True)
                                        
    client = tweepy.Client(consumer_key = params["consumer_key"],
                           consumer_secret = params["consumer_secret"],
                           access_token = params["access_token"],
                           access_token_secret = params["access_token_secret"],
                           bearer_token = bearer_res["Parameters"][0]["Value"]) #文字列が長いとjsonファイルの読み込みでエラーになるため
                           
    t_delta = datetime.timedelta(hours=9)
    JTS = datetime.timezone(t_delta, "JTS")
    now = datetime.datetime.now(JTS)
    weekd = weekday_dict[datetime.datetime.weekday(now)]
    today = now.strftime("%m/%d") + "(" + weekd[0] + ")"
    
    config_dict = get_default_config()
    config_dict["language"] = "ja"

    owm = OWM("自分のAPIkey", config_dict)
    mgr = owm.weather_manager()

    w = mgr.weather_at_place("Tokyo,JP").weather
    temp = w.temperature("celsius")["temp_max"]
    
    forecast = mgr.forecast_at_place("Tokyo,JP", "3h").forecast
    status_list = []
    for weather in forecast.weathers[2:7]:
        status_list.append(weather.detailed_status)
    today_w = mode(status_list)

    tweet_text = "{}\n天気は{}予報で、最高気温予想は{}だそうです。\n今日も一日頑張りましょう。(from lambda)".format(today,today_w, temp)
    client.create_tweet(text=tweet_text)

天気予報をツイートするだけなので
とても短い簡単なコードになっています。

コードの流れとしては
1.ssmからtwtterAPIのキーを取得
2.OpenWeatherMapから天気予報情報を取得
3.定型文に取得した情報を含めてツイート

といった具合になっています。

またLambdaを使用する際のルールとして、
lambda_hundlerを必ず定義する必要があります。

これはLambdaが実行される際に最初に実行される関数です。
コードはこの中に含めて書いていきます。

2-2-1.ssmからキーを取得

get_from_ssm.py
ssm = boto3.client('ssm', "ap-northeast-1")

response = ssm.get_parameters(Names=["/credentials/twitter"], WithDecryption=True)
params = json.loads(response['Parameters'][0]['Value'])
bearer_res = ssm.get_parameters(Names=["bearer_token"], WithDecryption=True)
                                        
client = tweepy.Client(consumer_key = params["consumer_key"],
                       consumer_secret = params["consumer_secret"],
                       access_token = params["access_token"],
                       access_token_secret = params["access_token_secret"],
                       bearer_token = bearer_res["Parameters"][0]["Value"])

ssmに保管したkey/tokenを取得します。

boto3.client("ssm", "region")にてクライアントを準備、
get_parameters(Nmes=["*パラメータ名*"])にて取得できます。

中身はJSONファイル形式なのでjsonで読み込み、
そのままtweepy.Clientの引数に指定しています。

▼SSM(boto3)のドキュメントはこちら▼

2-2-2.OpenWeatherMapから天気情報を取得

OpenWeatherMap.py
config_dict = get_default_config()
config_dict["language"] = "ja"

owm = OWM("*自分のAPIkey*", config_dict)
mgr = owm.weather_manager()

w = mgr.weather_at_place("Tokyo,JP").weather
temp = w.temperature("celsius")["temp_max"]
    
forecast = mgr.forecast_at_place("Tokyo,JP", "3h").forecast
status_list = []
for weather in forecast.weathers[2:7]:
    status_list.append(weather.detailed_status)
today_w = mode(status_list)

今回OpenWeatherMapの詳細については省き、
大まかな説明とさせて頂きます。

ここで行っていることは以下の2点です。
・最高気温予測の取得
・日中の天気予報情報の取得

無料のAPIでは3時間ごとの予報が取得可能のため、
日中の天気予報で最も多かった予報を採用しています。

▼参考ページ▼

2-2-3.取得した情報をツイート

tweet.py
weekday_dict = {0:"月曜日", 1:"火曜日", 2:"水曜日",
                3:"木曜日", 4:"金曜日", 5:"土曜日", 6:"日曜日"}

t_delta = datetime.timedelta(hours=9)
JTS = datetime.timezone(t_delta, "JTS")
now = datetime.datetime.now(JTS)
weekd = weekday_dict[datetime.datetime.weekday(now)]
today = now.strftime("%m/%d") + "(" + weekd[0] + ")"

tweet_text = "{}\n天気は{}予報で、最高気温予想は{}だそうです。\n今日も一日頑張りましょう。(from lambda)".format(today,today_w, temp)
client.create_tweet(text=tweet_text)

先に定義した辞書から取得した日時の曜日を取り出し、
"mm/dd(weekday)"のような形に変換する。

【Lambda内の実行時間】
datetime.now()などを使う場合は注意が必要です。
Lambda実行時の日時は日本時間ではなくUTCであるため、
日本時間にするにはtimedeltaを使って(+9h)の調整が必要になります。

あとはこれまでに取得した日付や天気情報を、
定型文にformat関数を用いて挿入してツイートする。

▼create_tweetのリファレンス▼

3. Lambdaへコードをデプロイ

Lambdaの編集画面で直接コードを書くことも可能ですが、
今回は事前に書いたpyファイルをアップロードしていきます。

またLambda内で使用できるモジュールには限りがあるため、
使用するモジュールによっては別で準備する必要があります。

今回はスクリプトのpyファイルと一緒に、
zipファイルに圧縮した状態でLambdaにアップロードします。

なおLambdaへアップロードする際は必ず スクリプトファイルの名前は、
「lambda_function.py」にする
必要があります。

【パッケージをzipする際の注意点】
パッケージとpyファイルをzipファイルに圧縮する際は、
画像のように個別に選択した状態で行います。
(2点を1つのファイルに入れてから圧縮するとエラーになる)

zipへ圧縮.png
pythonのコードを書いたpyファイルとパッケージを全てまとめて
zipファイルに圧縮し、アップロードします。
lambdaにzipをアップロード.png
今回はとても多くのパッケージを含んでいるため、
非常に大きなzipファイルとなってしまいました。

どうやらレイヤー機能を使うとパッケージを準備せず、
直接Lambda内でimportできるようなのですが、
今回は分かりやすい方法を採用しました。

そしてここで必要になるのが ssm連携の権限設定 です。
きちんと権限を設定しないとこの後のテスト段階で
延々とエラーバトルになるので必ず設定します。

▼Lambdaの権限設定▼

4. Lambdaのテスト

最後にデプロイしたコードをテストしていきます。
lambda_test.png

今回は初期設定のテストを行っただけですが、
エラーではなく 「Response」 が表示されていれば成功です。

実際に連携させたtwitterを見てみると、
設定したテキストがツイートされていることが確認できます。
(天気はわりと当たるが、気温は低く出がち?)
tweet.PNG

5. cloud watchの設定

最後にLambdaのトリガーを設定します。
このLambdaは毎朝8:00きっかりに働いて貰おうと思います。

作成したLambdaの設定から「トリガーを選択」を選びます。
トリガーを追加.png
EventBridgeを選択し、
イベントブリッジを選択.png
時間をUTCの23:00(日本時間だと+9hで8:00)に設定します。
時間を設定する.png
これで毎朝8:00にLambdaが自動で実行されます。

実際に上に添付したツイートの画像を見てみると、
投稿時間が8:00ジャストであることが分かると思います。

▼EventBridgeの参考リンク▼

6. 所感と今後の展望

6-1. 躓いた点

・サービスの全体像と繋がり
・IAMロールの仕様
・JSONファイルの扱い

今回AWSのサービスに触れるのは初めてで、
自分のやりたいことに対してどのサービスを使うべきか
その全体像を把握するのがまず躓いた点でした。

サービスの全体像はAWSが以前に公開している
サミットのスライド資料を参考に少しずつ理解しました。

▼2019年サミット資料/動画▼

そして各サービスを連携させるにあたって
必ず必要になるIAMロールや権限の設定の問題。

本記事で権限については触れていませんが、
基本一人での開発ではFullAccessで対処していました。

チームでの開発の場合は各ロールに権限の範囲を
適切に設定することで安全に開発ができると思います。

最後はJSONファイルの扱いについてですが、
これはスクレイピング未経験だったためです。

次回はデータを取得してJSONファイルとして扱い、
S3バケットへの保存をするのでここで一気に学びました。

6-2. 今後の展望

今回は初回ということで基本的なLambdaの使い方について、
前回学んだTwiiterAPIと併せて練習してみました。

次回からはこのLambdaの機能を利用して、
自動でTwitter上からデータを取得する機能 を作ります。

ちなみに今回のコードの応用だけで簡単な
Twitterbotも作れるのでそれだけでも楽しいと思います。

今回詳細は省きながら書かせて頂きましたがいずれは、
・AWSの登録方法
・IAMロールの仕様
・SSMでのパラメータ作成方法
・cloudwatchの仕様
・lambdaのレイヤー

あたりの詳細についても記事を書きたいと考えています。

6-3. さいごに

本記事を読んで頂いてありがとうございました。
コメントや質問、お気軽に宜しくお願い致します。

次回の記事

その他の参考リンク

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?