70
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-07-05

はじめに

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

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

サンプルとは少し異なりますが、実際にやってみたソースはこちらです。
https://github.com/chimame/search_ranking_checker_on_aws_lambda

前提条件

本記事は以下のライブラリ等を使用しております。
Nodejs: 8.10
puppeteer: 1.10.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 context = browser.defaultBrowserContext()
    const page = await context.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.push(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.5.0がリリースされているがそのバージョンでは動かないので、1.4.0で動作させる必要がある。
(逆に動いたよっていう方いらっしゃったら教えてください)

1.10.0で動くことを確認したので、修正しています。

puppeteerのchromiumは使用しない

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

.npmrc
puppeteer_skip_chromium_download=true

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

日本語表示

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

私自身で日本語フォントの適用をやってみたが、UserAgentが設定されていないとフォントが反映されなかったので、そこは注意してほしい。

await page.setUserAgent('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36')

// If User Agent is not set, the font will not be reflected, so User Agent must be set
await page.evaluate(() => {
    var style = document.createElement('style')
    style.textContent = `
        @import url('//fonts.googleapis.com/css?family=Source+Code+Pro');
        @import url('//fonts.googleapis.com/earlyaccess/notosansjp.css');
        div, input, a{ font-family: 'Noto Sans JP', sans-serif !important; };`
    document.head.appendChild(style)
})
await page.waitFor(1000) // Wait until the font is reflected

参考記事

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

70
47
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
70
47

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?