Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8691

AWS LambdaとServerless Frameworkで爆速で作るTwitterbot

$
0
0

0. はじめに

ここ1年はStackstormばかり扱っているのですが、年末だし他の技術も触るかー!と思いたち、色々自分の作業ディレクトリを漁っていたところ、Twitterbotなるものを発掘しました。

Stackstorm???という方はこちらをご参照ください。(自演)
Dockerで始めるStackstorm再入門1/3(環境構築からOrquestaで書いたWorkflowの結果をslackに通知するところまでのチュートリアル)

話を戻します。
そのTwitterbotですが、私はvpsを使って運用していました。
ただ、そんなに頻繁に動かさないので、また勉強も兼ねて、このたびAWS Lambda(以下、lambda)移行にチャレンジした次第です。

lambdaってなに?という方は、AWSがオフィシャルなハンズオンを公開しているので、そちらをご参照ください。

本記事では、サンプルコードも用意しているので、ぜひお試しください。

1. 目次

  • 2. 環境/バージョン情報
  • 3. Serverless Frameworkとは
  • 4. ローカル開発環境の準備
  • 5. serverless.ymlを編集
  • 6. lambdaの実行ファイルを編集
  • 7. lambdaをローカルから実行
  • 8. lambdaをデプロイ
  • 9. 参考

2.環境/バージョン情報

ローカル開発環境

  • Ubuntu: 19.04 (Disco Dingo)
  • npm: 6.13.4
  • Python: 3.7.3

    • tweepy: 3.8.0
    • oauthlib: 3.1.0
    • requests: 2.22.0
    • requests-oauthlib: 1.3.0他
  • serverless

    • Framework Core: 1.60.4
    • Plugin: 3.2.6
    • SDK: 2.2.1
    • Components Core: 1.1.2
    • Components CLI: 1.4.0

AWS Lambda

  • python3.7

3. Serverless Frameworkとは

そもそもServerless Frameworkとはなんなのか。
公式ドキュメントでは、このように紹介されています。

The Serverless Framework consists of an open source CLI that makes it easy to develop, deploy and test serverless apps across different cloud providers, as well as a hosted Dashboard that includes features designed to further simplify serverless development, deployment, and testing, and enable you to easily secure and monitor your serverless apps.

参考: Serverless Framework Documentation

個人的に感じた特徴は以下のとおりです。

  • node.js製フレームワーク
  • ローカルで開発したファンクションをserverlessコマンドを使って任意のプロバイダープラットフォーム(AWS, GCPなど)にデプロイ
  • デプロイの設定はserverless.ymlで定義

4. ローカル開発環境の準備

  • サンプルリポジトリをクローン
  • AWSクレデンシャルの設定
  • Serverless Frameworkのインストールとプロジェクトの作成
  • プラグインのインストール

サンプルリポジトリをクローン

gkz@localhost ~$ git clone https://github.com/gkzz/lambda_twbot.git \
&& cd lambda_twbot

AWSクレデンシャルの設定

gkz@localhost ~$ aws configure
~/.aws/config
[default]
region = ap-northeast-1
output = json
~/.aws/credentials
[default]
aws_access_key_id = xxxxxxxxxxx
aws_secret_access_key = yyyyyyyyyyyyy

Serverless Frameworkのインストールとプロジェクトの作成

gkz@localhost ~$ sudo npm install -g serverless
gkz@localhost ~$ serverless create \
> --template aws-python3 \
> --name src \
> --path src
Serverless: Generating boilerplate...

(略)

 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.60.4
 -------'

Serverless: Successfully generated boilerplate for template: "aws-python3"

プラグインのインストール

今回は以下の3つのプラグインをインストールしました。

プラグインの名称目的
serverless-python-requirementsライブラリをインストールするため
serverless-dotenv-plugin環境構築を読み込むため
serverless-offlineローカル開発環境でlambdaを実行するため

参考までにserverless-python-requirementsをインストールした際のコマンドを貼りますが、他の2つも同様にインストールしています。

gkz@localhost ~$ sudo npm install --save serverless-python-requirements

プロジェクト構成

serverless,ymlを編集する前にディレクトリ構成を確認しておきましょう。
特に確認したい点は以下の2点です。

  • serverless.ymlからみた.envの配置場所です。
    • Twitterのtokenは./config/.envから読み取ります。
  • requirements.txtはserverless.ymlと同じ階層に配置します。
gkz@localhost ~$ cat src/handler.py.tmpl > src/handler.py
gkz@localhost ~$ cat config/.env.tmpl > config/.env
gkz@localhost ~$ tree -L 2
.
└── src                    # プロジェクトフォルダ
    ├── 37                 # python -m venv $nameで作ったpython3.7の仮想環境の名称
    ├── config             # .envなど変数が記載されたファイルの親ディレクトリ
    ├── handler.py         # lambdaの実行関数
    ├── node_modules
    ├── package.json
    ├── package-lock.json
    ├── __pycache__
    ├── requirements.txt   # tweepyなど必要なライブラリが記載
    ├── serverless.yml     # lambdaをローカル開発環境からデプロイするのに使う
    └── serverless.yml.org # プロジェクトフォルダを作る際に生成されたserverless.ymlのサンプルファイル

5 directories, 6 files

5. serverless.ymlを編集

/lambda_twbot/serverless.yml
service:srccustom:dotenv:basePath:./config/# ./lambda_twbot/src/.config/stage:${env:STAGE}# basepath/.envから環境変数STAGEを読み込むregion:${env:REGION} # 同様に環境変数REGIONを読み込むpythonRequirements:dockerizePip:non-linuxprovider:name:awsruntime:python3.7stage:${self:custom.stage}region:${self:custom.region}plugins:-serverless-python-requirements-serverless-dotenv-plugin-serverless-offlinefunctions:rtweet:handler:handler.rtweet# $filename.$function(handler.pyのrtweet関数を実行)memorySize:256timeout:90sevents:-schedule:cron(0/20 * * * ? *)# 毎日20分おきfav:handler:handler.favmemorySize:256timeout:90sevents:-schedule:cron(0/600 * * * ? *) # 毎日600分おき

6. lambdaの実行ファイルを編集

/lambda_twbot/src/handler.py
# coding: UTF-8
try:importunzip_requirementsexceptImportError:passimporttweepyimporttimeimportosimportrandomimporttracebackdef_set_token():""" set twitter token """CK=os.environ['CONSUMER_KEY']CS=os.environ['CONSUMER_SECRET']AT=os.environ['ACCESS_TOKEN']AS=os.environ['ACCESS_TOKEN_SECRET']auth=tweepy.OAuthHandler(CK,CS)auth.set_access_token(AT,AS)returntweepy.API(auth)def_find_tweet(token):found=[]kws=['#python 本','#lambda 楽しい',]forkwinkws:fortweetintweepy.Cursor(token.search,kw).items(5):found.append(tweet)returnfounddefrtweet(event,context):""" entry point of rtweet """counter=0token=_set_token()tweets=_find_tweet(token)fortweetintweets:try:#print('\nRetweet Bot found tweet by @' + tweet.user.screen_name + '. ' + 'Attempting to retweet.')
tweet.retweet()logger.info(tweet.retweet())counter+=1#print('Retweet published successfully.')
# Where sleep(10), sleep is measured in seconds.
# Change 10 to amount of seconds you want to have in-between retweets.
# Read Twitter's rules on automation. Don't spam!
time.sleep(random.randint(2,5))# Some basic error handling. Will print out why retweet failed, into your terminal.
excepttweepy.TweepErroraserror:print('''Retweet not successful. 
            Reason: {r}
            '''.format(r=error.reason))exceptStopIteration:print(traceback.format_exc())breakreturn"RtweetConts: {num}".format(num=counter)deffav(event,context):""" entry point of fav """counter=0token=_set_token()tweets=_find_tweet(token)fortweetintweets:try:tweet.favorite()# Where sleep(10), sleep is measured in seconds.
# Change 10 to amount of seconds you want to have in-between retweets.
# Read Twitter's rules on automation. Don't spam!
time.sleep(random.randint(2,5))# Some basic error handling. Will print out why retweet failed, into your terminal.
excepttweepy.TweepErroraserror:print('''Fav not successful. 
            Reason: {r}
            '''.format(r=error.reason))exceptStopIteration:print(traceback.format_exc())breakreturn"FavConts: {num}".format(num=counter)#if __name__ == "__main__":
#    rtweet('', '')
/lambda_twbot/src/requirements.txt
certifi==2019.11.28
chardet==3.0.4
idna==2.8
oauthlib==3.1.0
PySocks==1.7.1
requests==2.22.0
requests-oauthlib==1.3.0
six==1.13.0
tweepy==3.8.0
urllib3==1.25.7

7. lambdaをローカルから実行

実行する前にrequirements.txtからライブラリをインストールすることと、-fあるいは-functionで実行関数を指定することを忘れないでください。

gkz@localhost ~$ python3.7 -m venv 37 && \
> source 37/bin/activate \
> pip install -r requirements.txt 
gkz@localhost ~$ serverless invoke local --function rtweet
gkz@localhost ~$ serverless invoke local --f fav

8. lambdaをデプロイ

デプロイは以下のコマンドで実行できます。

gkz@localhost ~$ serverless deploy -v
gkz@localhost ~$ sls deploy -v

ファイルを編集した際には一度削除してから改めてデプロイします。
やりかたはdeployをremoveに変えるだけです。

gkz@localhost ~$ serverless remove
gkz@localhost ~$ sls remove

9. 参考

P.S. Twitterもやってるのでフォローしていただけると泣いて喜びます:)

@gkzvoice


Viewing all articles
Browse latest Browse all 8691

Trending Articles