Puppeteerを使用したHeadless Chromeの操作

f:id:vasilyjp:20180927090637j:plain

こんにちは、フロントエンド開発部の荒井です。 先日VASILYでは開発合宿が行われました。本記事では私が合宿で使用したHeadless Chrome + Puppeteerを紹介したいと思います。

chrome_logo

開発合宿のテーマ決め

合宿での開発内容は個人に委ねられており、普段出来ない開発を自由に行うことが出来ました。各々興味深いテーマを持ち寄っており、非常に面白い開発合宿でした。私も何をテーマにするか非常に悩みましたが、今後の業務のことも考え、久しく触れていなかったヘッドレスブラウザを使用した開発を行うことにしました。

ヘッドレスブラウザ

GUIを持たないブラウザで、フロントエンドの自動テストやSPA(Single Page Application)のスクレイピングにも用いられます。ヘッドレスブラウザとしてはPhantomJSが有名だと思いますが、メインメンテナーが終了を宣言したため、今回はHeadless Chromeを採用しました。ヘッドレス環境でChromeを動作させるHeadless ChromeはChrome 59から導入されています。

Headless Chromeを使用する

Headless Chromeを使用するのは非常に簡単です。 Chromeがインストールされていれば、以下の手順で使用することが出来ます。

1. Chromeがインストールされているパスを指定
alias chrome="/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
2. --headlessオプションを付けてChromeを実行
chrome --headless --disable-gpu --screenshot https://www.google.com

上記サンプルでは--screenshotオプションを使用してwww.google.comのスクリーンショットを撮っています。実行すると実行時のディレクトリにscreenshot.pngというスクリーンショットがあるはずです。このように簡単な機能であればコマンドラインフラグを使用することで達成出来ます。

Puppeteer

コマンドライン機能により、簡単にHeadless Chromeを使用することが出来ました。しかし、実際に自動テストやスクレイピングを行うにはプログラムの記述が必要になってきます。そこで今回使用したのがNode.jsからHeadless Chromeを簡単に扱えるPuppeteerです。

PuppeteerにはDev Tools ProtocolでChromiumを制御するAPIが提供されています。Node.jsからHeadless Chromeを扱うためのライブラリはいくつか存在しますが、PuppeteerはそのFAQにもある通り、Chrome DevToolsチームがメンテナンスを行なっています。今回採用した一番の決め手となりました。

動作例

それではPuppeteerをインストールしてsample.jsを作成してみます。 最初のサンプルはGoogleにてVASILY, Incと検索するコードです。

インストール

yarn add puppeteer

sample.js

const puppeteer = require('puppeteer');

puppeteer.launch({
  headless: false, // フルバージョンのChromeを使用
  slowMo: 300      // 何が起こっているかを分かりやすくするため遅延
}).then(async browser => {
  const page = await browser.newPage();

  await page.setViewport({ width: 1200, height: 800 }); // view portの指定
  await page.goto('https://www.google.co.jp/');
  await page.type('#lst-ib', 'VASILY, Inc');
  await page.click('.lsb');

  await page.waitFor(3000); // デモのための遅延
  browser.close();
});

実行

node sample.js

f:id:vasilyjp:20171116164615g:plain

デモのためヘッドレスモードをオフにしています。サンプルコードを見て頂いても分かる通り、基本的なAPIが用意されており、Headless Chromeを簡単に扱えます。Puppeteer APIはこちらをご参照ください。

SPAサイトの操作

次にVASILYのコーポレートサイトにアクセスしてみます。 VASILYのコーポレートサイトはVue.jsによるSPAであり、ソースコードを確認するとbody内はdivが1行とscrpitタグが存在するだけとなっています1

<body>
  <div id="app">
  </div>
  <script src="/dist/build.js"></script>
</body>

このようなSPAのサイトを扱ってみます。ServerSideRenderingをしていないサイトもよく見かけるので スクレイピングなどの参考にしてください。 下記サンプルではメニューのRECRUITをクリックしています。

const puppeteer = require('puppeteer');

puppeteer.launch({
  headless: false,
  slowMo: 300
}).then(async browser => {
  const page = await browser.newPage();

  await page.setViewport({ width: 1200, height: 800 });
  await page.goto('https://vasily.jp/');

  const recruit = await page.$('.contents > ul > li:nth-child(4) > a');
  await recruit.click();

  await page.waitFor(3000);
  browser.close();
});

f:id:vasilyjp:20171116164459g:plain

まとめ

Puppeteerを使用したHeadless Chromeの操作は非常に分かりやすく、動作させるまでスムーズに行えました。クライアントでDOMを生成しているサイトのスクレイピングをしたい方、自動テストに興味がある方は是非一度お試しになってください。

また、VASILY開発合宿の様子は後日記事が上がりますので、そちらもご覧ください。 私はHeadless Chrome + Puppeteerを使用して勤怠サイトを操作をしていました(悪巧みはしていません)

最後に

VASILYではエンジニアを募集しています。興味ある方はWantedlyからご応募ください!


  1. 2017年11月16日現在の情報です。開発合宿でコーポレートサイトへのNuxt.jsの採用が発表されたため、SSRされる可能性があります。

カテゴリー