本家で issue には挙がってますが、まだ対応しているようではなさそうです。(2017/09/10 現在)
準備
serverless-chrome を手元に持ってきます。
$ cd /path/to/workdir $ git clone https://github.com/adieuadieu/serverless-chrome.git
そして、含まれている chrome/chrome-headless-lambda-linux-x64.tar.gz を展開します。今回は必要なものをすべてここに追加して、再アーカイブする方針です。(今回は作業ディレクトリとして /tmp を使用するものとします。)
$ cd /tmp $ tar xf /path/to/workdir/chrome/chrome-headless-lambda-linux-x64.tar.gz $ ls headless-chrome headless_shell libosmesa.so
fontconfig
以前 lambda で phantomjs を使う場合に同じように日本語が表示できないという問題があったようで、その時の対策が fontconfig を同梱して、それで日本語を表示させるというものでした。
どうやら今回もこの手法が使えそうなので真似てみます。
fontconfig を lambda で動かすためには amazon linux 向けにビルドする必要があります。そこで今回は docker-lambda を使ってみることにしました。
http://the.nyarla.net/entry/2017/02/06/142900the.nyarla.net
$ docker run -i -t -v /tmp:/var/task lambci/lambda:build /bin/bash
ビルドに必要なツールをインストールします。(以降 bash-4.2# というプロンプトは docker 内で実行するコマンドです。)
bash-4.2# yum install gperf freetype-devel libxml2-devel bash-4.2# easy_install pip bash-4.2# pip install lxml bash-4.2# cd /tmp
fontconfig を取得して、ビルドし、headless-chrome 配下にインストールします。
bash-4.2# git clone http://anongit.freedesktop.org/git/fontconfig bash-4.2# cd fontconfig bash-4.2# git checkout -b 2.12.4 refs/tags/2.12.4 bash-4.2# ./autogen.sh --sysconfdir=/var/task/headless-chrome/fontconfig/etc --prefix=/var/task/headless-chrome/fontconfig/usr --mandir=/var/task/headless-chrome/fontconfig/usr/share/man --enable-libxml2 bash-4.2# make bash-4.2# make install
インストール状況を確認します。(docker からは一旦 exit)
$ cd /tmp/headless-chrome/fontconfig $ ls etc usr
docker で install したため usr/share/fontconfig/conf.avail 配下の symlink が外からは切れて見えます。
リンク切れは serverless で deploy する時に error になってしまうため、それを回避するために、ここではとりあえずコピーして実体を持ってきておきます。(もっとスマートな方法もありそうですが未検討。)
$ cd /tmp/headless-chrome/fontconfig/usr/share/fontconfig/conf.avail $ rm ./* $ cp /tmp/headless-chrome/fontconfig/etc/fonts/conf.d/* .
日本語フォントを置くためのディレクトリの設定もしておきます。
$ cd /tmp/headless-chrome/fontconfig/usr/share/fontconfig $ vi local.conf
以下のファイルを local.conf として置いておきます。
<?xml version="1.0"?> <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> <fontconfig> <dir>/var/task/headless-chrome/fontconfig/usr/share/fonts</dir> </fontconfig>
日本語フォント
Google Noto Fonts を使用しようと考えていたのですが、サイズが大きそうなので、IPA フォントを使用することにしました。
$ cd /tmp $ wget http://dl.ipafont.ipa.go.jp/IPAexfont/ipaexg00301.zip $ unzip ipaexg00301.zip $ cp ipaexg00301/* /tmp/headless-chrome/fontconfig/usr/share/fonts/
フォントをインストールしたら fontconfig が参照できるようにキャッシュを生成しておきます。fc-cache を docker から叩いておきます。
bash-4.2# /var/task/headless-chrome/fontconfig/usr/bin/fc-cache -sv
strip
これで必要なものは準備できたのですが、このまま再パッケージすると 50MB 制限を超えてしまいます。そこで chrome のバイナリを strip すると、今回の追加分を込みで 50MB に収まるようになります。
bash-4.2# strip /var/task/headless-chrome/headless_shell
再アーカイブ
これで必要なものは準備できたため、再アーカイブします。
$ cd /tmp $ tar cfvz chrome-headless-lambda-linux-x64.tar.gz headless-chrome
デプロイ
いよいよデプロイです。先程つくった chrome のアーカイブを chrome 配下に置きます。
$ cd /path/to/workdir/serverless-chrome $ cp /tmp/chrome-headless-lambda-linux-x64.tar.gz chrome
上書きが嫌な場合は別の名前にして、webpack.config.js で指定しているアーカイブ名を別のものにしておきましょう。
const chromeTarball = path.join(__dirname, 'chrome/chrome-headless-lambda-linux-x64.tar.gz')
同梱した fontconfig をロードさせるために環境変数 LD_LIBRARY_PATH も設定しておく必要があります。
environment: CHROME_PATH: ./headless-chrome/headless_shell LD_LIBRARY_PATH: /var/task/headless-chrome/fontconfig/usr/lib
あとは serverless-chrome の readme どおりにすれば ok です。
$ yarn deploy
デプロイしたらブラウザでアクセスします。クエリパラメータ url でスクリーンショットを撮りたいサイトを指定します。
- ttps://XXXXXXXXXXXXXXXX.execute-api.ap-northeast-1.amazonaws.com/dev/chrome?url=http://www.hatena.ne.jp/
撮られたイメージが以下になります。
使用感
とりあえずメジャーなサイトのスクリーンショットを適当に撮ってみたのですが、
- やっぱりデータ量の多いサイトは (デフォルトのタイムアウト時間である) 15sec 制限にかかってしまう。(これは延長して回避できる。)
- IPA フォントなので日本語しかいけないのかと思ってたが、韓国語や中国語も読めそう。(ただし一部豆腐あり)
みたいな感じでした。
ローカルで動かす
docker-lambda を使うことで (スマートではないですが) ローカルでも動かすことは可能です。
$ cd /path/to/workdir/serverless-chrome/.serverless $ unzip serverless-chrome.zip $ cp handler.js /tmp $ docker run -i -t -e "CHROME_PATH=./headless-chrome/headless_shell" -e "LD_LIBRARY_PATH=/var/task/headless-chrome/fontconfig/usr/lib" -v /tmp:/var/task lambci/lambda:nodejs6.10 handler.run '{"queryStringParameters": {"url":"http://www.hatena.ne.jp/"}}'
標準出力に html がドバっと出るので、適当に切り出せば読めるはずです。