Python
tweepy
lambda

Amazon LambdaでTwitterの自動リプライ

やりたいこと

Lambdaで定期的に特定のハッシュタグが含まれるTweetを取得して、それに対して自動で画像付きリプライを送る。

実装方法

  • CloudWatchのイベント機能で、n時間に一回Lambdaの関数を実行させる
  • Lambdaで、
    • S3からツイートに添付する画像ファイルを取得
    • n時間分の特定のつぶやき(例: #W杯 を含むツイート)を取得
    • 取得した特定のつぶやきに対して画像付きでリプライを送る

Lambdaで実装する理由としては、

  • 1日に数回しか実行しないスクリプトの為に常に稼働しているサーバを構築、管理するのはコストと時間がかかるのでやりたくない
    • コスト面では、Lambdaは月々100万リクエストまで無料
  • 添付画像に使うファイルをS3にアップロードするだけでよく、管理が楽
    • AWSのアカウントがあれば誰でも扱える

といったことが挙げられます。

TwitterAPIを扱う為のPythonライブラリ Tweepy

今回はPythonのライブラリTweepyを使って実装します。
http://www.tweepy.org/

API Referenceはこちらです。
TwitterのAPIが簡単に扱えるようになっています。
例えば検索APIは、

api.search(q='"#W杯"', lang='ja', result_type='recent',count=10)

このようにすることで、#W杯を含む日本語のツイートを最新のものから10件取得してくれます。

環境

  • Python 3.6.3
  • tweepy 3.6.0

必要なライブラリ等の導入

# Tweepyのインストール
pip install tweepy

今回はApexを使ってLambda関数をデプロイします。
導入については以下の記事を参照してください。(自演)
https://qiita.com/shioiyan/items/9ef9d309b8c16fe6b427

ファイル構成

今回のファイル構成は以下のようになります。

.
├── functions
│   └── twitter_reply
│       ├── function.json
│       ├── index.py
│       ├── requirements.txt
│       └── site-packages
└── project.json

実装

function.json
{
  "description": "twitter reply method",
  "runtime": "python3.6",
  "handler": "index.lambda_handler",
  "environment":{
    "PYTHONPATH": "/var/runtime:/var/task/site-packages",
    "CK": "xxxxx(Consumer Key)",
    "CS": "xxxxx(Consumer Secret)",
    "AT": "xxxxx(Access Token)",
    "AS": "xxxxx(Access Token Secret)",
    "KEYWORD": "#W杯",
    "IMAGE_NAME": "football.png",
    "BUCKET_NAME": "xxxxx(S3のbucket名)",
    "TEXT": "ニッポンチャチャチャ"
  }
}

TwitterアプリケーションのConsumer Key等はこちらでアプリケーション登録を行うことで取得することができます。
KEYWORDにはリプライを送りたいハッシュタグを入れておきます。
IMAGE_NAMEリプライで添付する画像(S3のBUCKET_NAME配下に置いておく)の名前です。
TEXTはリプライで画像と共に送る文章です。

index.py
# coding: UTF-8
import tweepy
from tweepy import TweepError
import os
import boto3

# Twitterの認証周りのkey
CK = os.environ['CK']
CS = os.environ['CS']
AT = os.environ['AT']
AS = os.environ['AS']

# Lambdaで実行される関数
def lambda_handler(event, context):
    # Twitterの認証
    auth = tweepy.OAuthHandler(CK, CS)
    auth.set_access_token(AT, AS)
    api = tweepy.API(auth)

    # s3から画像ファイルを取ってきてローカルに保存
    s3          = boto3.resource('s3')
    bucket_name = os.environ['BUCKET_NAME']
    filename    = os.environ['IMAGE_NAME']
    file_path   = '/tmp/' + 'image.png'
    bucket      = s3.Bucket(bucket_name)
    bucket.download_file(filename, file_path)

    # キーワードに当てはまるつぶやきをしている人に画像付きでリプライ
    keyword = os.environ['KEYWORD']
    text    = os.environ['TEXT']
    for status in api.search(q=keyword, result_type='recent',count=1):
        print(status._json)
        statusId  = status.id
        name      = status.author.name
        replyText = name + ", " + text
        try:
            # reply
            api.update_with_media(file_path, status=replyText.encode("UTF-8"), in_reply_to_status_id=statusId)
        except TweepError:
            print("Debug::TweepError reply failed...")
requirements.txt
tweepy==3.6.0

今回使うインストールしておく必要のあるライブラリはtweepyだけです。

これをApexでデプロイしましょう。

$ apex deploy twitter_reply --profile lambda-user --region ap-northeast-1

実行例

$ apex invoke twitter_reply --profile lambda-user --region ap-northeast-1

実行することでKEYWORDで設定したハッシュタグの含むツイート一件に対してリプライを画像付きで送ることができます。

また、定期的に実行するには、CloudWatchのイベントを使うことで実現できます。

注意点

  • 無差別にリプライを送ることはやめましょう。
  • 鍵垢(Tweet非公開)のTweetはapi.search()で取得できません。
    • Tweetを公開に設定を変えても、鍵垢の時にTweetしたものは取得できないです。(自分が試した限りではそうでした)
  • Twitter APIは時間あたりのリクエスト制限があるのであらかじめ確認しておいた方が良いです。

まとめ

Amazon Lambdaを使ってTwitterの特定のハッシュタグを含むツイートに画像付きでリプライを送ることができました。
鍵垢に対してリプライを送れないのが不便で、デバッグが大変だと感じました。
たくさんのツイートにリプライを送るときにどれくらいの実行時間が必要なのかはLambdaを使う上で確認しておく必要がありそうです。