Edited at

AWS Lambdaで動的サイトのwebスクレイピングをしてtwitterに投稿するbotを作った


はじめに

webページからスクレイピングをしたデータを簡単に加工して自動投稿するtwitterのbotを作りました。

完全に初見のLambdaとPythonでできました。

以下のサイトを組み合わせただけのほぼパクリ記事です。作業ログです。

【Python】Chrome headlessで動的サイトのスクレイピング on AWS Lambda

AWS Lambda から Twitter に投稿する

無駄に面倒なAPI Keyとアクセストークンの入手の方法についてですが、以下の記事を参考にしてください。

登録ページ:https://apps.twitter.com/

https://qiita.com/tdkn/items/521686c240b0c5bc6207

https://syncer.jp/Web/API/Twitter/REST_API/


環境

Cloud9

Python 2.7.10(3系でもいけるはずです)

Twitter developに登録してAPI Keyとアクセストークンを入手済み

AWSのアカウント


ディレクトリ作成

requests_oauthlibをpip installしたときの挙動がMacとAmazon Linuxでは違ったので以下パッケージのインストールはCloud9上で全て行います。

ということでまずはCloud9で適当に環境を作成します。

そして作業ディレクトリを作成します。

$ mkdir webscraping_tweetbot

$ cd webscraping_tweetbot


seleniumインストール

作成したディレクトリにseleniumをインストールします。

pipでインストールするのですが、コマンドを実行したOS用のseleniumが自動でインストールされます。

今回は最終的にLambdaでプログラムを実行してもらうのでAmazon Linux用のseleniumが必要です。

参考記事に従ってバージョンも同じものをダウンロードします。

$ pip install selenium==3.13.0 -t .

後は作成されたディレクトリごとダウンロードして先ほどの作業ディレクトリの中に置きます。


requests_oauthlibのインストール

作業ディレクトリwebscraping_tweetbot直下に認証ライブラリであるrequests_oauthlibをインストールします。twitterに接続する際に必要になります。

$ pip install requests_oauthlib -t ./


beautifulsoup4のインストール

htmlを入手した後、データを整形するのにbeautifulsoupを使うので、webscraping_tweetbot直下にインストールします。

$ pip install beautifulsoup4 -t ./


serverless-chromiumのダウンロード

binディレクトリを作成してそこにダウンロードします。


最新版はPythonで動かない(2018年4月27日現在 [参照])ため、v.0.0-37を入れます。

引用: https://qiita.com/nabehide/items/754eb7b7e9fff9a1047d


$ mkdir bin

$ curl -SL https://github.com/adieuadieu/serverless-chrome/releases/download/v1.0.0-37/stable-headless-chromium-amazonlinux-2017-03.zip > headless-chromium.zip
$ unzip headless-chromium.zip -d bin/
$ rm headless-chromium.zip


Chrome driver のダウンロード

serverless-chromiumと同様です。

$ curl -SL https://chromedriver.storage.googleapis.com/2.37/chromedriver_linux64.zip > chromedriver.zip

$ unzip chromedriver.zip -d bin/
$ rm chromedriver.zip

これでライブラリのインストールは終わりです。


lambda_function.pyの作成

lambdaにtweetを投稿するlambda_function.pyを作成します。

webスクレイピングそのものはwebscrape.pyのwebscrapeという関数にさせます。

beautifulsoupを使ったwebスクレイピングについてはこちらを参考

アクセストークンなどはLambdaの環境変数として設定します。


lambda_function.py

#coding:utf-8


from requests_oauthlib import OAuth1Session
from webscrape import webscrape
import urllib3
import os

CK = os.environ['CK']
CS = os.environ['CS']
AT = os.environ['AT']
AS = os.environ['AS']

URL = 'https://api.twitter.com/1.1/statuses/update.json'

def lambda_handler(event, context):
# webscrape.pyのwebscrapeの返り値(shapingdata(html))を受け取る。
tweet=webscrape()

session = OAuth1Session(CK, CS, AT, AS)

params = {"status": tweet }
twitter = OAuth1Session(CK, CS, AT, AS)
req = twitter.post(URL, params = params)

if req.status_code == 200:
return tweet
else:
return req.status_code



webscrape.pyの作成


webscrape.py


#coding:utf-8

from selenium import webdriver
from bs4 import BeautifulSoup
import time

def webscrape():
# webdriver settings
options = webdriver.ChromeOptions()
options.binary_location = "./bin/headless-chromium"
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--single-process")

driver = webdriver.Chrome(
executable_path="./bin/chromedriver",
chrome_options=options
)

# web scraping
driver.get("URL")
#ここの時間が長いとlambdaの料金が無駄にかかります。driverがページの表示にかかる時間分だけを設定するのが良いです。
time.sleep(0.3)
html = driver.page_source.encode('utf-8')

return shaping_data(html)

def shaping_data(html):

soup = BeautifulSoup(html, "html.parser")
# 中略(beautifusoupの使い方に関しては他の記事を参照してください。)
return tweet_data



Zip化

webscraping_tweetbot上でLambdaにアップロードするファイルをzip化します。

あとはこれをダウンロードします。

zip -r webscraping_tweetbot.zip ./


Lambdaで関数作成

Lambdaの関数を作成します。

twitterのbotを作るのでcloudwatch eventへのアクセス許可のIAMロールを割り当ててます。

ない場合は作りましょう。

スクリーンショット 2018-10-29 12.08.19.png


lambdaにzipをアップロードしてデプロイ

作成したzipファイルをアップロードします。10MB以上ですがアップロードはできます。

S3に一度アップロードしてからアップロードをすることもできます。AWSはこちらの方法を推奨のようです。この場合はアップロードさえ終わればS3から消しても大丈夫です。

ハンドラのところは

Lambdaで動かすPythonファイルへのパス.そのファイル内で実行する関数の名前

を入力します。(今回はlambda_function.lambda_handler)

スクリーンショット 2018-10-29 12.11.37.png

さらに画面下で環境変数を設定する項目があるのでそこでアクセストークンなどを(CK,CS,AK,AS)を忘れず設定しましょう。(参考)

保存をしてテストを動かして無事グリーンになること確認したら、twitterにちゃんと投稿されているか確認します。


Cloudwatch Eventsのルール適用

左側のリストからCloudWatch Eventsを選択します。

スクリーンショット 2018-10-29 12.17.40.png

すると下に設定画面が出てくるのでcron式またはrate式で投稿するスケジュールを設定します。

スクリーンショット 2018-10-29 12.24.26.png

後は追加して、設定したスケジュールで投稿されたら終了です!お疲れ様でした。


作ったもの

ソースコードはこちら

https://github.com/kihoair/intro_bot/

まだ昨日(2018/10/28)からしか動いていないのですが、制作物です。

https://twitter.com/intro_tweetbot

個人的によく行くジャズバーのジャムセッションのスケジュールを1日1回自動でつぶやいています。メンバー見てからセッションに行きたくなったりすることってあるんですよね。それでは!