Webブラウザの操作をJavaScriptで自動化出来る「Puppeteer」のバージョンが1.0になったというニュースが入ったので入門してみた
インターネットも最も重要なソフトウェアであるブラウザは、いたるところで使われています。しかしながら、人間と対話することを意識された設計であるため、コンピュータで複雑なこと自動操作する前提で作られてはいません。しかしながら、テストやスクレイピングのためにブラウザで動作させた結果を得たい場合があります。
操作を自動化した場合、GUIは不要となる場合が多いです。またGUIは動作が比較的重いため、エンジニアのではGUIの表示をオフにしたいことがしばしばあります。このような機能を実装したブラウザをヘッドレスブラウザ※1(headless browser)とよびます。代表例として、phantomJSがあります。
この記事で使ったスクリプト
Chromeのヘッドレスを体感しよう
- https://developers.google.com/web/updates/2017/04/headless-chrome?hl=ja
- https://chromium.googlesource.com/chromium/src/+/master/headless/README.md
- https://cs.chromium.org/chromium/src/headless/app/headless_shell_switches.cc
$ chrome \
--headless \ # Chrome をヘッドレスモードで実行する
--disable-gpu \ # 暫定的に必要なフラグ
--remote-debugging-port=9222 \
https://www.chromestatus.com # 開きたい URL(デフォルトは about:blank)
※ 現在は、--disable-gpu
を含めなければいけません。このフラグはそのうち不要にる予定です。
「Puppeteer」で出来ること
- サイトのスクリーンショットの生成
- サイトのPDFの作成
- chromeなのでjavascriptが動く
- JS動作後のWebサイトHTMLのスクレイピング
- SPA(single page application)にスクロールさせる
- SSR(server side rendering)を実装する
- フォームを使ったテストの自動化
- 最新Chromeを使っての最新のJavaScriptやブラウザ機能のテスト
- timeline traceをキャプチャーしてパフォーマンス診断を助ける
- などなど
使い方によってはもっとあると思いますが、思いつくだけでもコレだけあります。
ブラウザを使ってしなければならない処理なら、ほとんどに対応できると考えられます。
そもそも「Puppeteer」とはなんだろう?
Puppeteerをを事で言うならば、「chromeをnodejsを使って操作することの出来るライブラリ」です。
github公式には、下記のように詳しく描いていますが、「DevToolsプロトコル」とか知らなくても動かせます。
Puppeteer is a Node library which provides a high-level API to control headless Chrome or Chromium over the DevTools Protocol. It can also be configured to use full (non-headless) Chrome or Chromium.
※2 DevToolsプロトコル - https://chromedevtools.github.io/devtools-protocol/ - https://developers.google.com/web/updates/2017/04/headless-chrome?hl=ja#frontendPuppeteerはDevToolsプロトコル※2でヘッドレスChromeまたはChromiumを制御するための高水準APIを提供するNodeライブラリです。フル(ヘッドレスではない)のChromeまたはChromiumを使用するように設定することもできます。
puppeteerが使える環境を整える
今回使用した環境は下記です
- Nodejs version: v8.9.4
- Google Chrome version: 63.0.3239.132(Official Build)(64 ビット)
$ mkdir puppeteer-demo && cd puppeteer-demo
$ npm init
$ npm install --save puppeteer
index.js
の作成
$ touch index.js
package.json
にscript
の追加
package.jsonに追加したscriptは実行されると、node_moduleが読み込まれます。
$ tmpfile=$(mktemp)
$ cat package.json | jq '.scripts.app = "node index.js"' > $tmpfile
$ mv $tmpfile package.json
コレで環境は整いました。
例1: サイトのスクリーンショットを取得してみる
ここまでできたら、実際に動かしてみましょう。
まずは、サイトのスクリーンショットを取得してみます。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({path: 'example.png'});
await browser.close();
})();
$ npm run app
コレで、example.pngが作成されていて、ちゃんとスクリーンショットを取得出来ることがわかります。
[fcareerwave:20180207165841p:plain]
例2: サイトのスクリーンをPDFで取得する
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://news.ycombinator.com', {waitUntil: 'networkidle2'});
await page.pdf({path: 'hn.pdf', format: 'A4'});
await browser.close();
})();
$ npm run app
[fcareerwave:20180207194157p:plain]
例3: ブラウザ内でjavascriptを実行する
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
// Get the "viewport" of the page, as reported by the page.
const dimensions = await page.evaluate(() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio
};
});
console.log('Dimensions:', dimensions);
await browser.close();
})();