はじめに
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/
追記(2019/12/23)
Python3系で実行し、容量を食うchroniumをLambda Layerに設定することでコンソールからも関数を確認できるようにして、
なおかつ、デプロイはServerless Frameworkでできるように改良しました。
AWS Lambdaで動的サイトのwebスクレイピングをしてtwitterに投稿するbotを作った(続)
環境
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を入れます。
$ 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の環境変数として設定します。
#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の作成
#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ロールを割り当ててます。
ない場合は作りましょう。
lambdaにzipをアップロードしてデプロイ
作成したzipファイルをアップロードします。10MB以上ですがアップロードはできます。
S3に一度アップロードしてからアップロードをすることもできます。AWSはこちらの方法を推奨のようです。この場合はアップロードさえ終わればS3から消しても大丈夫です。
ハンドラのところは
Lambdaで動かすPythonファイルへのパス.そのファイル内で実行する関数の名前
を入力します。(今回はlambda_function.lambda_handler)
さらに画面下で環境変数を設定する項目があるのでそこでアクセストークンなどを(CK,CS,AK,AS)を忘れず設定しましょう。(参考)
保存をしてテストを動かして無事グリーンになること確認したら、twitterにちゃんと投稿されているか確認します。
Cloudwatch Eventsのルール適用
左側のリストからCloudWatch Eventsを選択します。
すると下に設定画面が出てくるのでcron式またはrate式で投稿するスケジュールを設定します。
後は追加して、設定したスケジュールで投稿されたら終了です!お疲れ様でした。
作ったもの
ソースコードはこちら
https://github.com/kihoair/intro_bot/
まだ昨日(2018/10/28)からしか動いていないのですが、制作物です。
https://twitter.com/intro_tweetbot
個人的によく行くジャズバーのジャムセッションのスケジュールを1日1回自動でつぶやいています。メンバー見てからセッションに行きたくなったりすることってあるんですよね。それでは!