Puppeteerでできることまとめ

GMOアドマーケティングのy.a.です。

PuppeteerはHeadless Chrome使うのを便利にするNode ライブラリです。
https://developers.google.com/web/tools/puppeteer/

(引用元:Puppeteer | Tools for Web Developer https://developers.google.com/web/tools/puppeteer/

ですのでスクレイピングなり、なにかWebページのテストを自動化したい場合に、比較的手軽に色々できます。
そこでPuppeteerに興味を持った方へ、なるべく簡潔にPuppeteerで出来ることをいくつか紹介したいと思います。
※なお実行環境にNode.jsがインストールされていることが前提です。

インストール

基本的な定義
main.js

実行するには下記コマンド

スクリーンショットはできる?

できます。page.screenshotを使用してできます。とても簡単です。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagescreenshotoptions

上記はページ全体ですが、特定の要素だけ取るということも可能です。elementHandle.screenshotです。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#elementhandlescreenshotoptions
例えばh1要素だけのスクリーンショットを撮りたい場合はこうです。

JS実行できる?

できます。page.evaluateを使用します。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args

こういう使い方をすることはないと思いますが、こんな感じでJS書けます。

クリックして遷移は?

できます。page.clickです。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageclickselector-options

あるいはelementHandle.clickもありますので、それに倣うならこうやってもいけますね。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#elementhandleclickoptions

待つことは?

できます。page.waitForNavigationです。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitfornavigationoptions

page.goto()のデフォルトはloadなので、使う場面としてはclickしてページ遷移した後だと思います。

下記はDOMContentLoadedまで、次の処理を行わないというものです。

他にも、特定の要素を待つことなどもできます。waitForSelectorです。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitforselectorselector-options
下記はlazyクラスが付与された要素が出るまで待つ場合。

ただやろうと思えば、page.waitForでほぼ全てこちらでまとめられそうです。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagewaitforselectororfunctionortimeout-options-args

他にもtimeoutなど。下記は5000ms待つ場合です。

DOMレンダーツリーを取得

GoogleChromeのDevToolで言うところの「Elements」パネルで表示されるものも、取得できます。

先に紹介したpage.evaluateで、JS実行できることがわかっているので、あとはそれを応用してみましょう。
下記はloadイベント後のDOMレンダーツリーです。

リダイレクト検知

できます。request.redirectChainを使用します。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#requestredirectchain

page.gotoがResponseクラスというPromiseオブジェクトを返しますので、それを利用します。

fileプロトコルも取得できる?

できます。page.gotoの引数に fileプロトコルでパスを指定すれば良いだけです。 file://path/to/html

ちなみにHTMLのstringだけ渡してもいけます。これはsetContentを使用します。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pagesetcontenthtml-options

おまけ

async/await

紹介したサンプルコードを見てもわかると思うのですが、async/await(ES2017)がとてもよく出てきます。これは非同期処理のために必要なものです。
使い方についてほんとにざっくり説明すると、
functionの前にasyncを定義することで非同期関数になりまして、その中で呼び出す別の非同期関数の前にawaitをつければ、その処理が返るまで待ちます。

再掲しますが、最初にサンプルとして出したものも、そういった形で作られていることが分かると思います。

ただこの辺はJavaScriptのPromise(ES2015)の理解が前提ですので、
PuppeteerやNode.js使う際は、ES2015以降の新シンタックスなどは押さえておくとよいと思います。

独特に感じるAPI

APIドキュメントを見ていると
「page.$()」や「page.$$()」など出てきます。
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageselector
https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageselector-1

それぞれdocument.querySelector、document.querySelectorAllと同等のものなんですが、ちょっと見ない感じだな、と思っていたらどうやらCommand Line APIのようでした。
https://developers.google.com/web/tools/chrome-devtools/console/command-line-reference?hl=ja

つまりブラウザのコンソールでも使えるんですね。
jQueryを読み込んでいる場合、$はjQueryオブジェクトになるわけですが、そうでない場合はこのCommand Line APIとして使えるわけです。

その他PuppeteerではcreateCDPSessionといった Chrome Devtools Protocolを使えるAPIも用意されています。
つまり普段開発でChromeを使用している人にとってもChromeの機能をほぼ不足なく使えそうです。
https://chromedevtools.github.io/devtools-protocol/

ということで私もまだまだ使い倒したいと思います。

それでは。