Twitter API v2をAWSで動かし自動投稿するようにした件
TwitterのAPIをAWS Lambdaで動かす方法を紹介します。
Twitter APIの仕様変更に伴う対応を行ったのでその時のメモです。
世間でも話題になりましたがTwitter APIが有料化になってしまい、 それにともない数多くの無料で使えていたTwitter関連サービスが廃止・有料化になりました…
私もIFTTTというサービスを使ってWebサイトの新規記事リンクをTwitter上に自動で投稿するように設定したのでしたが、 残念ながら有料化してしまいました。
ただしTwitter APIはすべて有料化してしまったわけではなく、 Freeプランだと投稿だけはできるようなのでAWSのLambdaでAPIを実行するように対応しました。
さくっとできるためご興味ある方はやってみてください。
対応概要
ゴール
- AWS Lambda(今回はPythonで実装)でTwitter APIを呼び出しWebサイトの新規記事を投稿する
- CloudWatchで定期的にLambdaを動かし、新規記事の更新状態をチェックする
- 新規記事はWebサイトのRSS情報(xmlファイル)を読み取りS3に保存しておく
作業概要
- Twitter開発者用サイトでAPI利用設定 →今回は割愛。以下の参考サイトを確認ください。
- AWS SAMでLambda等の必要なリソース作成
参考サイト
- Twitter APIのFreeプランを利用してツイートする →APIの利用手順がのってます。
- 【Python】Twitter API v2を使ってツイートする →Pythonの利用例はこちら。
- 開発者プラットフォーム Twitter API →公式サイト。
1.Twitter開発者用サイトでAPI利用設定
詳細は割愛。上記サイトが参考になります。
アクセスキー等はメモして保存しておきましょう。
2.AWS SAMリソース設定(Lambda、CloudFormation)
- AWS SAMでリソースは作成。
- LambdaはDocker利用、実行コードはpython。
Lambda
srcディレクトリ配下に以下のファイルを置く。
- app.py: メイン処理実行
- Dockerfile: Docker定義
- requirements.txt: 使用ライブラリ記述
app.py
import feedparser
import boto3
import os
import json
import tweepy
# AWS環境パラメータ
S3_BUCKET_NAME = os.environ.get('S3_BUCKET_NAME')
CLIENT_AWS = boto3.client('s3')
# TwitterAPIパラメータ
CONSUMER_KEY = '{環境に合わせて変更してください}'
CONSUMER_SECRET = '{環境に合わせて変更してください}'
ACCESS_TOKEN = '{環境に合わせて変更してください}'
ACCESS_TOKEN_SECRET = '{環境に合わせて変更してください}'
CLIENT_TWITTER = tweepy.Client(
consumer_key=CONSUMER_KEY,
consumer_secret=CONSUMER_SECRET,
access_token=ACCESS_TOKEN,
access_token_secret=ACCESS_TOKEN_SECRET
)
# 記事一覧情報の一時保存先(S3)
POST_FILE = 'manga/posts.json'
# ツイート対象のWebサイトRSS情報
URL = "{環境に合わせて変更してください}"
def lambda_handler(event, context):
# RSSの情報を取得
feed = feedparser.parse(URL)
# 過去の投稿情報を取得
before = check_file(POST_FILE)
# 現在の投稿保存先
posts = []
if before:
# 取得した現在情報から記事の日付、タイトル、URLを取得
for entry in feed.entries:
# IDをURLから抽出
post_id = int(entry.link.split("/")[-2])
post = {
'id': post_id,
'title': entry.title,
'url': entry.link,
'published': entry.published,
}
# 前回実行時の投稿と比較して新規登録されているデータはツイート
if not (post in before):
msg = entry.title + "\n#まとめ #2ch #5ch #漫画" + "\n" + entry.link
try:
CLIENT_TWITTER.create_tweet(text=msg)
except Exception as e:
print('[error] ', e)
posts.append(post)
# 今回参照した記事一覧情報を保存
CLIENT_AWS.put_object(Body=json.dumps(posts), Bucket=S3_BUCKET_NAME, Key=POST_FILE)
else:
print("Failed to get POST_FILE.")
def check_file(file_name):
"""登録先のファイルの有無をチェック
:rtype: object
"""
try:
response = CLIENT_AWS.get_object(Bucket=S3_BUCKET_NAME, Key=file_name)
check_result = json.loads(response['Body'].read())
except:
check_result = False
return check_result
requirements.txt
feedparser
boto3
tweepy
SAM template.yaml
以下のコードでリソースを作成。 PyCharmでデプロイ。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
python3.9
Lambda and EventBridge SAM for tweetForManga
Globals:
Function:
Timeout: 3
Environment:
Variables:
TZ: Asia/Tokyo
S3_BUCKET_NAME: {環境に合わせて変更してください}
Resources:
LambdaRole:
Type: AWS::IAM::Role
Properties:
RoleName: TweetForMangaLambdaRole
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/AmazonS3FullAccess
LambdaFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: TweetForMangaLambda
Role: !GetAtt LambdaRole.Arn
Timeout: 30
MemorySize: 128
PackageType: Image
Architectures:
- x86_64
Metadata:
Dockerfile: Dockerfile
DockerContext: ./src
DockerTag: python3.9-v1
Rule:
Type: AWS::Events::Rule
Properties:
Description: Scheduled Rule AM7 ~ AM0 every 15,45min
Name: TweetForMangaLambdaRule
# AM7 ~ AM0 15,45min
ScheduleExpression: 'cron(15,45 22-15 * * ? *)'
State: ENABLED
Targets:
- Arn: !GetAtt LambdaFunction.Arn
Id: lambda
FunctionPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !Ref LambdaFunction
Principal: events.amazonaws.com
SourceArn: !GetAtt Rule.Arn
Outputs:
LambdaFunction:
Description: "Lambda Function ARN"
Value: !GetAtt LambdaFunction.Arn
LambdaRole:
Description: "Implicit IAM Role created for function"
Value: !GetAtt LambdaRole.Arn
最後に
Twitter APIは無料枠だと1,500件/月ツイートできるみたいです。
Share this post
Twitter
Facebook
Email