前回:Lambdaでお手軽サーバーレス入門(CloudWatch Events編)
前回は、天気予報を定期的に取得しましたが、ログに出力しただけでした。
今回は、Pythonのライブラリを使って、Twitterに投稿してみたいと思います。
前回のソース
import os
import json
from urllib.parse import urlencode
from urllib.request import urlopen
from datetime import datetime
API_ID = os.getenv('OWM_API_ID')
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
def lambda_handler(event: dict, context):
if not API_ID:
print('ERROR: No API ID')
return
# get whether information from OpenWeatherMap
url = 'https://api.openweathermap.org/data/2.5/weather?{}'.format(urlencode({
'q': 'Ho Chi Minh City,VN',
'units': 'metric',
'appid': API_ID
}))
with urlopen(url) as f:
raw_data = json.loads(f.read().decode('utf-8'))
print('Location: {}, {}'.format(raw_data['name'], raw_data['sys']['country']))
print('Time: {}'.format(datetime.fromtimestamp(raw_data['dt']).strftime(DATETIME_FORMAT)))
print('Weather: {}, {}'.format(raw_data['weather'][0]['main'], raw_data['weather'][0]['description']))
print('Temperature: {}℃'.format(raw_data['main']['temp']))
print('Pressure: {:,}hPa'.format(raw_data['main']['pressure']))
print('Humidity: {}%'.format(raw_data['main']['humidity']))
if __name__ == '__main__':
lambda_handler({}, None)
PythonでのTwitterライブラリ
Twitterの開発者サイト https://developer.twitter.com/en/docs/developer-utilities/twitter-libraries.html でたくさん紹介されています。
この中で、Tweepyを使ってみたいと思います。
(★がたくさんあるため、という理由)
プロジェクトにインストール
通常Pythonのライブラリは pip install tweepy
のようにインストールすると使えますが、今回は、プロジェクトのフォルダにインストールしたいので、少しコマンドラインを変えてみます。
cd /path/to/qiita-lambda-cloudwatch-events
pip install tweepy -t .
めっちゃエラー出ました…。
調べると、StackOverflowで答えを見つけました。
[install]
prefix=
このファイルをプロジェクト(lambda_function.pyと同じ場所)に置いて、再度試してみます。
無事、成功しました。
Tweepyを使う
ソースを以下のように変更します。
import os
import json
from urllib.parse import urlencode
from urllib.request import urlopen
from datetime import datetime
import tweepy
OWM_API_ID = os.getenv('OWM_API_ID')
TWITTER_CONSUMER_KEY = os.getenv('TWITTER_CONSUMER_KEY')
TWITTER_CONSUMER_SECRET = os.getenv('TWITTER_CONSUMER_SECRET')
TWITTER_ACCESS_TOKEN = os.getenv('TWITTER_ACCESS_TOKEN')
TWITTER_ACCESS_TOKEN_SECRET = os.getenv('TWITTER_ACCESS_TOKEN_SECRET')
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
def lambda_handler(event: dict, context):
if not OWM_API_ID:
print('ERROR: No OpenWeatherMap API ID')
return
# get whether information from OpenWeatherMap
url = 'https://api.openweathermap.org/data/2.5/weather?{}'.format(urlencode({
'q': 'Ho Chi Minh City,VN',
'units': 'metric',
'appid': OWM_API_ID
}))
with urlopen(url) as f:
raw_data = json.loads(f.read().decode('utf-8'))
print('Location: {}, {}'.format(raw_data['name'], raw_data['sys']['country']))
print('Time: {}'.format(datetime.fromtimestamp(raw_data['dt']).strftime(DATETIME_FORMAT)))
print('Weather: {}, {}'.format(raw_data['weather'][0]['main'], raw_data['weather'][0]['description']))
print('Temperature: {}℃'.format(raw_data['main']['temp']))
print('Pressure: {:,}hPa'.format(raw_data['main']['pressure']))
print('Humidity: {}%'.format(raw_data['main']['humidity']))
if TWITTER_CONSUMER_KEY and TWITTER_CONSUMER_SECRET and TWITTER_ACCESS_TOKEN and TWITTER_ACCESS_TOKEN_SECRET:
# Post to Twitter
twitter_auth = tweepy.OAuthHandler(TWITTER_CONSUMER_KEY, TWITTER_CONSUMER_SECRET)
twitter_auth.set_access_token(TWITTER_ACCESS_TOKEN, TWITTER_ACCESS_TOKEN_SECRET)
twitter_api = tweepy.API(twitter_auth)
print('Your Twitter name is {}'.format(twitter_api.me().name))
twitter_api.update_status(status='''{city} ({country}) の天気 ({time}時点)
{weather} - {description}
気温🌡 {temperature}℃
気圧👂 {pressure:,}hPa
湿度💦 {humidity}%
'''.format(
city=raw_data['name'],
country=raw_data['sys']['country'],
time=datetime.fromtimestamp(raw_data['dt']).strftime(DATETIME_FORMAT),
weather=raw_data['weather'][0]['main'],
description=raw_data['weather'][0]['description'],
temperature=raw_data['main']['temp'],
pressure=raw_data['main']['pressure'],
humidity=raw_data['main']['humidity']
))
if __name__ == '__main__':
lambda_handler({}, None)
TwitterのAPIを使えるようにする
2018年の7月より、従来のように簡単にAPIキーを作れなくなったようです。
(恥ずかしながら今知りました)
なので、 https://developer.twitter.com/en/apply/user より申請しなければいけないようです。
申請が通ったら、こちらから作成できます。
作成されると、概要が見れる画面に遷移するので、そのまま「Keys and tokens」タブをクリックします。
下の「Access token & access token secret」にある「Create」をクリック。
ここで登場した4つの値、
- API key
- API secret key
- Access token
- Access token secret
は、メモしておいてください。
環境変数を設定する
ここでLambda関数画面を開き、先程メモした4つの環境変数をそれぞれ設定します。
- TWITTER_CONSUMER_KEY <- API key
- TWITTER_CONSUMER_SECRET <- API secret key
- TWITTER_ACCESS_TOKEN <- Access token
- TWITTER_ACCESS_TOKEN_SECRET <- Access token secret
Zipファイルを作る
さて、肝心のソースなんですが…
上記の画面で上半分に見切れているインラインエディタだと、ファイルのアップロードができません。
なので、Zipファイルを作り、アップロードします。
ここにあるファイルを すべて 一つのZipファイルにします。
必ず、ソースファイルがZipファイルの直下になるように作ってください。(ひとつ上のフォルダで作ろうとすると、そのフォルダがルートになる圧縮ソフトもあるため注意)
Macの場合は、⌘+A
で全て選択して、「Compress 27 items」です。
出来上がったZipファイルを、Lambdaコンソール(先程環境変数を設定した画面)でアップロードします。
Function code内のCode entry typeを「Upload a .zip file」にし、ファイルとして先程圧縮したZipを選択します。
Saveをクリックすると、Zipがアップロードされ、再びインラインエディタが使えるようになります。
圧縮したファイルがすべて出ていますね!
これで成功です。
※トータルサイズが3MBを超える場合、インラインエディタは表示されません。
テスト
まずは動くか直接実行してみます。
右上の「Test」をクリックすると…
赤枠の部分、増えてます!
そして肝心の自分のTwitterを見ると…
増えてますね!
やばい…湿度が高くなってる=スコールの予感?
(現在ベトナム南部は雨季です。あと1ヶ月ほどで終わると思いますが)
何かおかしい?
はい、 時刻がUTC です。
(その前の同じようなツイートは、ローカルマシンから実行したものです)
LambdaはすべてUTCで動くので、datetime.strftime
の結果も、タイムゾーンを指定しなければUTCになります。
なので、あとでこっそり変えておきました。