Javascript が使えるヘッドレスなブラウザ(PhantomJS の代替)

 wget などは、Javascript が使えませんが、ヘッドレスなブラウザの PhantomJS は Javascript が使えます。と言ってもヘッドレスなので通常のブラウジングには使えません。

 例えば、ルータの Web インターフェースで再起動をさせようとした時、Javascript を使っていたりすると、wget を使っての自動化ができません。そこで登場するのが Javascript が使えるヘッドレスブラウザです。

 ヘッドレスブラウザは、Web システムのテストを自動化させる場合にも利用されます。というかテストの自動化で使われることが多いです。

 PhantomJS は Selenium でもよく使われていたものですが、開発は停止しています。

 PhantomJS の代わりになるものがないかを探したところ、Chrome(Crominium) をヘッドレスとして利用する puppeteer (パペッティア) というものを見つけました。修正が最近も行われているようです。開発が活発だということは、安定していない可能性もあります。今年に入った時点で、2/2 にバージョン 6.0.0 がリリースされています。約半年でバージョンが 4 上がっています。つまり、安定していない可能性が高いです。

 しかし、ブラウザの定番とも言える Chrome をヘッドレスで使えることは強みだと思います。

 その他、Chrome や FireFox などでテストを自動化するものには、puppeteer 以外にも、Selenium や PlayWright と言ったものがあります。それぞれ、以下の記事が参考になりました。

 以前は、PhantomJS を直接使っていましたが、PhantomJS の変わりに Headless Chrome を使うとなると、puppeteer か PlayWright を使ったほうがいいようです。Selemium でもいいのですが、Selemium は対応ブラウザが多いので、それだけ設定が複雑になります。

 試しに、puppeteer を使ってみました。

 npm のパッケージには、Chromium を含んだ puppeteer パッケージと、Chromium を含まない puppeteer-core パケージがあります。今回は、puppeteer-core をインストールします。(試してみたら、puppeteer の Chromium は x86 用らしく、Raspberry Pi では動かないようです。)

ローカルインストール

 インストールディレクトリに移動して以下のコマンドを実行します。

$ mkdir puppeteer
$ cd puppeteer
$ npm install puppeteer-core

スクリーンショットを撮ってみる

 puppeteer-core をインストールした場合は、

const puppeteer = require('puppeteer');

の代わりに

const puppeteer = require('puppeteer-core');

と書きます。また、puppeteer.connect([options]) か puppeteer.launch([options]) を使い、executablePath オプションで Chromium のパスを指定する必要があるようです。

このサイトのトップページを画像として保存してみます。ファイル名を test.js として以下の内容のファイルを作りました。

#!/usr/bin/node

const puppeteer = require("puppeteer-core");

const URL = "https://sirius10.net/";

(async () => {
  console.log("*** Start ***");

  console.log("Chromium 起動");
  const browser = await puppeteer.launch({
    headless: false,
    slowMo: 50,
    executablePath: "/usr/bin/chromium-browser"
  });

  console.log("新しいタブ");
  const page = await browser.newPage();

  console.log("ビューポート/デバイス設定");
  await page.setViewport({
    width: 1024,
    height: 1228
  });

  console.log("sirius10 へ移動");
  await page.goto(URL);

  console.log("スクリーンショットを sample.png に保存");
  await page.screenshot({
    path: "sample.png",
    fullPage: true
  });

  console.log("Chromium 終了");
  await browser.close();

  console.log("*** End ***");
})();

 ビューの設定で高さを 1228 にしているのは、高さを指定しないと、screenshot で fullPage を指定しても内容が描画されなかったからです。どうも、Raspberry Pi では、ビューポートに表示されている内容しかスクリーンショットできないようです。ちょっと困りますね。fullPage の意味がありません。

実行

 次のコマンドで実行します。

$ node test.js

 あるいは、実行権を付けて実行します。

$ chmod +x test.js
$ ./test.js

 Cromium が開き、ページを表示して閉じます。コマンドを実行したディレクトリに sample.png が作成されます。とりあえず、動いたようです。

puppeteer で撮ったサイトのスクリーンショット

 今回は試しなので、ヘッドレス動作はさせていません。test.js の “headless: false," の行を削除すれば、ヘッドレスとして動作します。

 まだ、ページ上の操作は試していませんが、使えるようです。

次の記事(2021.06.20 追記)

リンクを操作

pupeeteer,Raspberry Pi

Posted by sirius