LoginSignup
1
4

More than 5 years have passed since last update.

Lambdaでお手軽サーバーレス入門(外部ライブラリ使用編)

Last updated at Posted at 2018-10-05

前回:Lambdaでお手軽サーバーレス入門(CloudWatch Events編)

前回は、天気予報を定期的に取得しましたが、ログに出力しただけでした。
今回は、Pythonのライブラリを使って、Twitterに投稿してみたいと思います。

前回のソース

GitHubにアップしました

lambda_function.py
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 .

image.png

めっちゃエラー出ました…。

調べると、StackOverflowで答えを見つけました。

setup.cfg
[install]
prefix=

このファイルをプロジェクト(lambda_function.pyと同じ場所)に置いて、再度試してみます。

image.png

無事、成功しました。

Tweepyを使う

ソースを以下のように変更します。

lambda_function.py
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 より申請しなければいけないようです。
申請が通ったら、こちらから作成できます。

私はこのように作ってみました。
twitter01.png

作成されると、概要が見れる画面に遷移するので、そのまま「Keys and tokens」タブをクリックします。
twitter03.png

下の「Access token & access token secret」にある「Create」をクリック。
twitter04.png

ここで登場した4つの値、

  • API key
  • API secret key
  • Access token
  • Access token secret

は、メモしておいてください。

環境変数を設定する

ここでLambda関数画面を開き、先程メモした4つの環境変数をそれぞれ設定します。
twitter05.png

  • 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ファイルを作り、アップロードします。

プロジェクトのフォルダはこの様になっています。
image.png

ここにあるファイルを すべて 一つのZipファイルにします。
必ず、ソースファイルがZipファイルの直下になるように作ってください。(ひとつ上のフォルダで作ろうとすると、そのフォルダがルートになる圧縮ソフトもあるため注意)
Macの場合は、⌘+Aで全て選択して、「Compress 27 items」です。

出来上がったZipファイルを、Lambdaコンソール(先程環境変数を設定した画面)でアップロードします。
Function code内のCode entry typeを「Upload a .zip file」にし、ファイルとして先程圧縮したZipを選択します。
twitter06.png

Saveをクリックすると、Zipがアップロードされ、再びインラインエディタが使えるようになります。
twitter07.png
圧縮したファイルがすべて出ていますね!
これで成功です。

※トータルサイズが3MBを超える場合、インラインエディタは表示されません。

テスト

まずは動くか直接実行してみます。
右上の「Test」をクリックすると…
image.png
赤枠の部分、増えてます!

そして肝心の自分のTwitterを見ると…
twitter08.png
増えてますね!

やばい…湿度が高くなってる=スコールの予感?
(現在ベトナム南部は雨季です。あと1ヶ月ほどで終わると思いますが)

何かおかしい?

はい、 時刻がUTC です。
(その前の同じようなツイートは、ローカルマシンから実行したものです)

LambdaはすべてUTCで動くので、datetime.strftime の結果も、タイムゾーンを指定しなければUTCになります。
なので、あとでこっそり変えておきました。

1
4
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
4