プログラマでありたい

おっさんになっても、プログラマでありつづけたい

AWS Lambda+PhantomJS/CasperJSでスクレイピング

 AWS Lambdaはサーバ不要のプログラムの実行エンジンです。インフラ側はAWSが管理するのですが、実行原理が解っていると思いの外に自由度が高いです。Shellやコマンドを同梱させれば動くし、依存するライブラリがなければAmazon Linux上でビルドして同梱させれば良いのです。その実例の1つに、Lambda+PhantomJSがあります。PhantomJSは、ブラウザ不要で画面描画ができるツールです。リンクのクリックやボタンの押下・フォームに入力も出来るので、ログインが必要なページの情報を取ってくるということやスクリーンショットを取るといったことも可能です。LambdaとPhantomJSを組み合わせてお手軽スクレイピングをしてみましょう。

プロジェクトの用意



 Github上にビルド済みのライブラリ込のプロジェクト(phantom-lambda-template)があるので、それを使います。生のライブラリ等が配置されているので、こういう感じでやるのだと参考にもなると思います。

github.com

ソースを落としてきたら、まずそのディレクトリに移動して依存関係のモジュールをインストールします。

$ npm install

次に環境設定ファイルを作ります。

$ npm run setup 
$ vi .env
AWS_ENVIRONMENT=development
AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXXXXXXXXXXX
AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXX
AWS_ROLE_ARN=arn:aws:iam::123456789012:role/lambda-phantomjs
AWS_REGION=us-east-1
AWS_FUNCTION_NAME=phantom-lambda-template
AWS_HANDLER=index.handler
AWS_MODE=event
AWS_MEMORY_SIZE=128
AWS_TIMEOUT=300
AWS_DESCRIPTION=
AWS_RUNTIME=nodejs

AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_ROLE_ARNの部分を編集しておいてください。AWS_TIMEOUTもデフォルト3秒なので長めに設定しておきます。(この例は、最大値である300秒にしています。)注意点としては、このACCESS_KEYが設定されているユーザは、Lambdaのアップロードする権限とローカルで実行する為の権限です。ROLE_ARNの方が、実際にLambdaで実行される場合の権限になります。それぞれ適切なものを設定しておく必要があります。

ここまで設定したらローカル実行してください。エラーがでなければ、O.K.です。

$ npm run start

次にLambdaにアップロードします。下記のコマンドでアップできるようになっています。素晴らしい

$ npm run deploy

AWSコンソールにログインしてみるとLambdaファンクションが出来ているはずです。
f:id:dkfj:20151201015934p:plain
実行してみてください。デフォルトのサンプルだと、コンソールログに'Hello from phantom'と出るだけです。

このテンプレートがやっていること



 ちなみにこのモジュールをどうやって作っているのかは、同梱のシェルを見ると解ります。Amazon Linuxのインスタンスでビルドしたモジュールを利用しています。PhantomJSに限らず、同じようなやり方で色々なモジュールをLambdaで使えます。

build-phantomjs.sh

# Launch an EC2 instance using the region-appropriate AMI from this document:
# http://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.

# Use a fairly beefy Spot Instance (c4.large is good) unless you want to wait
# for a long time. Don't bother with a t2.micro.

# Once it starts, SSH into the machine:

ssh ec2-user@your-ec2-box.amazonaws.com

# And then run (following the instructions from
# http://phantomjs.org/build.html):

sudo yum -y install gcc gcc-c++ make flex bison gperf ruby \
  openssl-devel freetype-devel fontconfig-devel libicu-devel sqlite-devel \
  libpng-devel libjpeg-devel

wget https://github.com/ariya/phantomjs/archive/1.9.7.zip
unzip 1.9.7.zip
cd phantomjs-1.9.7/
./build.sh --confirm

# Once it's finished, retrieve the build product (run from your local machine):
scp ec2-user@your-ec2-box.amazonaws.com:phantomjs-1.9.7/bin/phantomjs .

# Since this AMI includes a newer version of libicudata than Amazon Lambda,
# we need to include those libraries too.
# This won't be necessary once
# https://github.com/ariya/phantomjs/issues/12948 is fixed.
scp ec2-user@your-ec2-box.amazonaws.com:"/usr/lib64/libicu*50" .

# That's it! Don't forget to terminate the EC2 instance.

カスタマイズ



 スクリーンショットを取る例に変えてみます。

var page = require('webpage').create();

page.viewportSize = { width: 1920, height: 1080 };
page.settings.userAgent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36';

page.open('http://github.com/', function() {
  page.render('github.png');
  phantom.exit();
});

ローカルで実行すると、github.pngというファイルが出来ると思います。後は、これをS3等にアップロードするようなものを使うと、Lambdaクローラーとして機能し始めます。この辺りはハマりポイント多いので、また時間作って書き足します。

まとめ



 Lambdaは、今年のアップデートで実行時間がMax5分。更にスケジュール実行の機能が付きました。これでクローラー作る為にサーバを用意する必要がほぼなくなっています。あとは、Pythonで作るか、Node.JSで作るかです。今年はNode.JSの良いクローラー本が出たので、それを参考にどんどんアイデアを実現できればなと思います。Ruby本もよろしくね

See Also:
クローラー/スクレイピング本がざくざく
『Rubyによるクローラー開発技法』を書きました
Rubyによるクローラー開発技法の目次
Lambdaで作るクローラー/スクレイピング


参照:
クローラー/Webスクレイピング Advent Calendar 2015
プログラマになりたい Advent Calendar 2015