読者です 読者をやめる 読者になる 読者になる

歩いたら休め

If the implementation is easy to explain, it may be a good idea.

【Python3.6】AWS Lambdaでツイッターを検索して自動リツイートする

先程の記事に引き続き、AWS LambdaでPython3.6が使えるようになったので、過去にPython2.7で書いたバッチ処理のレガシーコードをLambdaに移行しています。

まずは、下の記事で書いた「ツイッターを検索した結果を自動リツイートする」コードを移行します。今見るとけっこうコード酷いですね。

kiito.hatenablog.com

Pythonのコードを書き直す

AWS Lambdaの流儀に従ってコードを書いていきます。

ここではlambda_function.pylambda_handlerという関数を用意して、実行するように設定することとします。

後述しますが、アクセストークン等は環境変数で渡しています。

import os
import time
from datetime import datetime
import twitter


TARGET_TERMS = ['ファンタジスタドール', '鵜野うずめ']
API_ENV_KEY = ['CONSUMER_KEY', 'CONSUMER_SECRET', 'ACCESS_TOKEN_KEY', 'ACCESS_TOKEN_SECRET']
COUNT = 100

def lambda_handler(event, context):
    client = TwitterClient()
    client.run(TARGET_TERMS)
    return True


class TwitterClient(object):
    def __init__(self):
        self.client = twitter.Api(*[os.environ[k] for k in API_ENV_KEY])
        self.nowtime = int(time.mktime(datetime.now().timetuple()))
        self.begin_time = self.nowtime - 60 * 60
    
    def run(self, terms):
        for term in terms:
            for tweet in self._search_tweet(term):
                if tweet.created_at_in_seconds in range(self.begin_time, self.nowtime):
                    self._post_retweet(tweet.id)

    def _search_tweet(self, term):
        return self.client.GetSearch(term=term, count=COUNT, result_type='recent')

    def _post_retweet(self, tweet_id):
        try:
            self.client.PostRetweet(tweet_id)
        except:
            print(f'{tweet_id}は既にリツイートされています')

ちなみにpython-twitterというライブラリを使っています。

github.com

zipで固めてアップロードする

先程の記事で用意したDockerイメージを使って、依存ライブラリも含めたzipファイルを用意しました。

kiito.hatenablog.com

requirements.txtには以下を記述しています。

python-twitter

環境変数でアクセストークン他を設定する

AWS Lambdaでは環境変数が設定できるので、アクセストークンなどはこちらから渡すことにします。

dev.classmethod.jp

こんな感じです。

f:id:takeshi0406:20170506170833p:plain

本来は「暗号化ヘルパーを有効にする」を選択すべきだと思うのですが、「どうせ自分以外見ないだろう」という甘い考えでやっていません。

本当はDockerで環境変数や依存ライブラリまで再現した開発環境を用意すればかっこよかったのですが、今回は小規模なコードなので特に用意しませんでした。

その他の設定

あとは以下の設定を行いました。特に難しいことはないと思います。

  • 「トリガー」で定期的に実行する
  • タイムアウト時間を3秒から3分まで長く設定しなおす(3秒ではさすがに打ち切られてしまう)