Node.js
AWS
lambda
puppeteer

AWS Lambda上でpuppeteerを動かして、スクレイピングする

はじめに

AWS Lambda上のヘッドレスブラウザで動かしたいものがあったので、それの備忘録も兼ねて書いておきます。ちなみに所属会社で似たようなことをしているのですが、PhatomJS(オワコンなのは知ってる)をAWS Lambda上で動かすために、わざわざカスタマイズしてからそれ専用にビルドするという変態技が使われている部分を書き換えたいという想いからの実験でもあります。

そこで本記事ではpuppeteer(パペティア?読み方あってる?)を使って、AWS Lambda上でヘッドレスブラウザを動かすということをしてみます。

前提条件

本記事は以下のライブラリ等を使用しております。
Nodejs: 8.10
puppeteer: 1.4.0 ←これ重要

AWS Lambda上でのヘッドレスブラウザ

みんな大好きサーバーレスのAWS Lambdaでヘッドレスブラウザを動かしてごにょごにょします。

プログラム

とりあえず四の五の言わずプログラムを貼る

index.js
const launchChrome = require('@serverless-chrome/lambda')
const CDP = require('chrome-remote-interface')
const puppeteer = require('puppeteer')

exports.handler = async (event, context, callback) => {
  try {
    // chromeを起動して、puppeteerから操作できるようにする
    const slsChrome = await launchChrome()
    const browser = await puppeteer.connect({ 
      browserWSEndpoint: (await CDP.Version()).webSocketDebuggerUrl 
    })
    const page = await browser.newPage()

    // ブラウザ操作(Googleでの検索結果)
    await page.goto(`https://www.google.co.jp/search?q=${event.searchWord}`, { waitUntil: 'domcontentloaded' })

    const searchResults = await page.evaluate(() => {
      const ret = []
      const nodeList = document.querySelectorAll("div#search h3")

      nodeList.forEach(node => {
        ret(node.innerText)
      })

      return ret
    })

    return callback(null, JSON.stringify({ searchResults: searchResults }))
  } catch (err) {
    return callback(err)
  }
}

解説

特に難しいことはしてないが、大事なのは次の3つ。
この3つを守れば上記のプログラムでスクレイピングしているとこをお好きなように弄っても動くはずです。

必要なのはパッケージは3つでpuppeteerのバージョンには注意

まずプログラムを見てわかるとおり、@serverless-chrome/lambdachrome-remote-interfacepuppeteerの3つを使用している。その中でもpuppeteerは現在1.15.0がリリースされているがそのバージョンでは動かないので、1.14.0で動作させる必要がある。
(逆に動いたよっていう方いらっしゃったら教えてください)

puppeteerのchromiumは使用しない

普通なら使用してもいいのだが、今回はAWS Lambdaで動かすという条件がある。AWS Lambdaで登録できるプログラムサイズは50Mバイト以内という条件があるため、それをクリアするためにpuppeteerのchromiumを使用(ダウンロード)してはならない。
そこでpuppeteerのchromiumを使用しないようにするために.npmrcを作成し、以下の記述をしておく。

.npmrc
puppeteer_skip_chromium_download=true

これで使用されなくのでOKです。(もちろん環境変数にセットするという手もあるが、誰でも同じ環境になるようにするにはファイルで書いておいた方が吉)

https://github.com/GoogleChrome/puppeteer/issues/2270

日本語表示

今回はやってないが、参考記事通りにWebフォントいれたら表示されると思う。
この辺も含めて冒頭で触れたPhatomJSをカスタムビルドしている理由の1つ。

参考記事

本記事はこちらを参考にさせて頂き書いております。

https://www.pressmantech.com/tech/serverless/4417