みなさん puppeteerつかってますか? 私は使ってません。なぜなら安定的に稼働させるための環境がないから...*1。
しかしそれも今日までです。
先日 beta になった GAE/SE Node について
GAE/SE Node は puppeteer も動くよ
— ぐら (@grapswiz) June 13, 2018
という話を聞きました。聞いたからにはやります。以下の通り。
const puppeteer = require('puppeteer') async function takeScreenShot(url, filePath) { const browser = await puppeteer.launch({args: ['--no-sandbox']}); const page = await browser.newPage(); await page.setViewport({ width: 1024, height: 768 }); await page.goto(url); await page.screenshot({ path: filePath }); await browser.close(); return }
こんな感じの関数を定義して動かした。ブログ用にちょっと整形したので、なんらかのミスで動かないかも。
以下感想と解説です。
起動時に --no-sandbox
オプションがいる
コンテナ環境下で Chromium を動作させる場合に --no-sandbox
オプションを要求されるの知らなくて最初うごかせなかった。ちゃんとエラーメッセージには書いてあるので、あとはどうやって puppeteer 経由で起動オプション渡すかって話だけど、上のコードみたいに .launch()
に渡すオプションに args キーの値として渡せばいいらしい。
--no-sandbox
オプションについてはちゃんと調べられてない。システムコール周りの話なのかなと思ってるけどなんなんだろうか……
インスタンスサイズ
デフォルトのインスタンスだとメモリ不足になったので、大きめのインスタンスを使っている。具体的には F4 インスタンス。
めちゃくちゃシンプルなページでも標準の F1 や F2 ぐらいだとこんな感じでメモリ不足に陥る。
上のスニペットで最後に毎回 browser.close()
してるのはメモリ問題への対策なのだけれど、これでも連続して重めのページをレンダリングすると死んでしまう。あんまり死ぬようなら F4_1G にあげるしかか無いけど、その辺は様子見ながらやっていこうと思う。
その他
実際には 1 週間のライフサイクルを設定した GCS バケットにスクリーンショットをアップロードし、 Slack に投稿している。 Slack に投稿するところ久々にやったので、画像の展開方法わかんなくてちょっと大変だった。( attachments.[].image_url
が必要なやつ)
要所を黒塗りにしたら訳がわからなくなりました
反省
開発環境あんまり整えずにガーッと書いたので、ローカルで何も考えずに動かすと GCS にアップロードできずに落ちたり、flowtype も無く typescript で書いているわけでも無いので後半めちゃくちゃ辛くなってしまった。
最近は会社も家も静的型付け言語 + IDEの静的解析とか、flowtype みたいなスタティックタイプチェッカの支援を受け続けてるし、テストもだいたい書いているのであまり苦がなかったのですが、久々にこう、大変な感じでしたね、、、。