JavaScript
Node.js
Chrome

ChromeのヘッドレスモードをMacOSXで試してみた

More than 1 year has passed since last update.

マストドンで盛り上がる最中、
こっそり一部で盛り上がってたChromeのヘッドレスモード
MacOSXで少し試してみたいと思います。

開発中の機能ということで、仕様の変更もあると思いますが、2017/4/16段階ではちゃんと以下のやり方で動作してます:)

準備

Google Chrome Canaryをインストール
開発段階にある機能がのってるchromeです。ささっと入れちゃいます。

nodejsインストール(v6.3以上)
ちなみに今回試したのはv7.9.0

シェルにCanaryバイナリへのエイリアスを作成します(僕は.zshrcに追加しました/bashの人は.bash_profileかな)

alias chrome-c='/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary'

設定を読み込みます(source ~/.zshrc)

適当なディレクトリを作成して、その中にscript.jsを作成します。

$mkdir headless-test
$npm install chrome-remote-interface
$vim script.js
script.jsの中身
const CDP = require('chrome-remote-interface');

CDP((client) => {
  // Extract used DevTools domains.
  const {Page, Runtime} = client;

  // Enable events on domains we are interested in.
  Promise.all([
    Page.enable()
  ]).then(() => {
    return Page.navigate({url: 'https://example.com'});
  });

  // Evaluate outerHTML after page has loaded.
  Page.loadEventFired(() => {
    Runtime.evaluate({expression: 'document.body.outerHTML'}).then((result) => {
      console.log(result.result.value);
      client.close();
    });
  });
}).on('error', (err) => {
  console.error('Cannot connect to browser:', err);
});
// [引用](https://github.com/cyrus-and/chrome-remote-interface)

実行してみる

ターミナルを2画面開いて
一つで先に

$ chrome-c --headless --remote-debugging-port=9222 https://chromium.org
特に出力はなく、入力待ちみたいな状態になります
もしmesa library周りのエラーが出たら--disable-gpuオプションをつけると良いそうです。

もう一つで

$node script.js
スクリプト内のhttps://example.comをアクセスしたいurlに変更してください
以下はqiita.comへアクセスした際の出力
https://qiita.com/
https://cdn.qiita.com/assets/public-f33264c77b8d85793c9875b153a1a98b.min.css
https://cdn.qiita.com/assets/siteid-large-c5f1d2812cc28cb0621d57061b9eb0f5.png
https://www.google.com/recaptcha/api.js
https://b.hatena.ne.jp/images/entry-button/button-only.gif
https://b.hatena.ne.jp/js/bookmark_button.js
...

読み込みされてるようです!
以上!!

おまけ

Nginxで確認したアクセスログ

自サイトへリクエストを送ってログをチェックしてみました

[16/Apr/2017:14:30:04 +0900] "GET / HTTP/1.1" 200 2783 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/60.0.3072.0 Safari/537.36" "-"

HeadlessChromeってなってます!

ページロードの計測

script.jsを以下のように変更してみました。

const CDP = require('chrome-remote-interface');

CDP((client) => {
    // extract domains
    const {Network, Page} = client;
    // setup handlers
    Network.requestWillBeSent((params) => {
        console.log(params.request.url);
    });
    Page.loadEventFired(() => {
        client.close();
        console.timeEnd('loadtimer')
        console.log('timer-end')
    });
    // enable events then start!
    Promise.all([
        Network.enable(),
        Page.enable()
    ]).then(() => {
        console.log('timer-start')
        console.time('loadtimer')
        var res = Page.navigate({url: 'https://qiita.com'});
        return res;
    }).catch((err) => {
        console.error(err);
        client.close();
    });
}).on('error', (err) => {
    // cannot connect to the remote endpoint
    console.error(err);
});

実行した結果

// 実行結果
timer-start
https://qiita.com/
https://cdn.qiita.com/assets/public-f33264c77b8d85793c9875b153a1a98b.min.css
https://cdn.qiita.com/assets/siteid-large-c5f1d2812cc28cb0621d57061b9eb0f5.png
https://www.google.com/recaptcha/api.js
https://b.hatena.ne.jp/images/entry-button/button-only.gif
https://b.hatena.ne.jp/js/bookmark_button.js
https://platform.twitter.com/widgets.js
...

loadtimer: 1260.686ms
timer-end

qiitaトップは、1sくらいでページ読み込みができるみたいです(これでちゃんと計測できてるのかな?)

参考

https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
https://github.com/cyrus-and/chrome-remote-interface