技術的な話題   


いい感じに Javascript がゴリゴリ書かれていて、認証が必要なサイトを定期的にキャプチャを取る、という謎タスクが生まれ、ちょうど最近話題の Headless Chrome でも試してみるかな~~と思ったら puppeteer なるものがあるそうなので、これを使ってみる。

GoogleChrome/puppeteer: Headless Chrome Node API

GoogleChrome 配下にいるので Chrome 公式のパッケージだ。

// puppeteer 導入
$ npm init
$ npm install puppeteer

ドキュメントにもあるサンプルソースを入れてみる。

// index.js
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();
})();

https://example.com へとアクセスし、そのページをキャプチャして ./example.png に保存するソースだ。 await で簡単わかりやすい書き方になるのが素晴らしい。これを動かしてみる。

$ node index.js
(node:30285) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
/var/www/html/crawl/bitbucket_billing/node_modules/puppeteer/.local-chromium/linux-497674/chrome-linux/chrome: error while loading shared libraries: libXss.so.1: cannot open shared object file: No such file or directory


TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

(node:30285) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

かなしみ…。どうにも libXss.so.1 が開けずにエラーっぽい。パッケージを探してインストールし、再度動かしてみる。

$ yum provides */libXss.so.1
...

libXScrnSaver-1.2.2-6.1.el7.i686 : X.Org X11 libXss runtime library
Repo        : base
Matched from:
Filename    : /usr/lib/libXss.so.1

libXScrnSaver-1.2.2-6.1.el7.x86_64 : X.Org X11 libXss runtime library
Repo        : base
Matched from:
Filename    : /usr/lib64/libXss.so.1


$ sudo yum install libXScrnSaver
...

$ node index.js
(node:1345) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
/var/www/html/crawl/bitbucket_billing/node_modules/puppeteer/.local-chromium/linux-497674/chrome-linux/chrome: error while loading shared libraries: libgtk-3.so.0: cannot open shared object file: No such file or directory


TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

(node:1345) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

GTK+3 が要求される。都合によって CentOS6 なのだが GTK+3 は入れるのがめっちゃ困難だった記憶。とりあえず GTK+3 というか Chrome を入れる方法を調べたら必要なライブラリも揃うだろう、と判断して調べる。

Google Chrome 60 Released - Install on RHEL/CentOS 7/6 and Fedora 26-20

Yes, they’ve discontinued support for RHEL 6.X version as of Google Chrome and on other side, latest Firefox and Opera browsers run successfully on the same platforms.

CentOS6 では Chrome は動かない、ダメ。Richard Lloyd 氏がスクリプトを作っているそうだが、そのサイトでも、いつまでも古いものを使うな、って書いてあった。

Site has been shut down

You have two choices really (ignoring Chromium, which no-one seems to be keeping up-to-date for RHEL/CentOS 6):

1. Use Mozilla Firefox ESR via "yum install firefox" that is shipped with RHEL/CentOS 6. Unfortunately, this can be up to a year out of date w.r.t. features compared to the more "normal" Mozilla Firefox that you can download from Mozilla (but that "normal" Mozilla Firefox is now also using GTK+3 and doesn't work on RHEL/CentOS 6 either).

2. Move to RHEL/CentOS 7, perhaps first in a VM before upgrading on bare metal once the VM is to your satisfaction. The latest Google Chrome installs and runs out-of-the-box on RHEL/CentOS 7 (see below).

まあ、一旦使ってみるなら docker でもいいか。

$ docker run -it -d -v $(pwd):/var/www/puppeteer_test centos:latest
Unable to find image 'centos:latest' locally
latest: Pulling from centos
6c5159923047: Pull complete
acec82331181: Pull complete
1c1b67b33c28: Pull complete
Digest: sha256:57c91a43765de2147fa666a128477bc6101d6fda660feaaa5fbb1a8b110c934f
Status: Downloaded newer image for centos:latest
2be8ec65e6e4db3d852d563b82cc4c90ca90f62b4aaa6304d6e00f06d6a4a9e7

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
2be8ec65e6e4        centos:latest       "/bin/bash"         16 seconds ago      Up 16 seconds                           romantic_sinoussi

$ docker exec -it 2be /bin/bash

# cd /var/www/puppeteer_test/
# ls
index.js  node_modules  package-lock.json  package.json

# node -v
bash: node: command not found

// nodeがいないので入れる
# curl -sL https://rpm.nodesource.com/setup_8.x | bash -
# yum install nodejs

# node index.js
(node:114) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
/var/www/puppeteer_test/node_modules/puppeteer/.local-chromium/linux-497674/chrome-linux/chrome: error while loading shared libraries: libpangocairo-1.0.so.0: cannot open shared object file: No such file or directory


TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

(node:114) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

// とりあえず yum provides で探しながら一個ずつ入れていく
// をまとめたものがこちら
# yum groupinstall "Development Tools"
# yum install pango libXScrnSaver libXcomposite libXcursor libXi libXtst cups-libs libXrandr GConf GConf2 alsa-lib atk gtk3

// 起動してみる
# node index.js
(node:11985) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Failed to launch chrome!
[0920/101508.987383:ERROR:zygote_host_impl_linux.cc(88)] Running as root without --no-sandbox is not supported. See https://crbug.com/638180.


TROUBLESHOOTING: https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md

(node:11985) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

root で --no-sandbox なしは認められないらしいのでソースを変える。

// index.js
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({args: ['--no-sandbox']});
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'example.png'});

  await browser.close();
})();

再び実行。

# node index.js

# ls
example.png  index.js  node_modules  package-lock.json  package.json

キャプチャ取れたので、画像を確認。

勝ち。

というわけで puppeteer 動いた。CentOS6 で CentOS7 が動いてて~ってちょっとアレなので、バージョン上げてまた試……、じゃない、本来の目的だった認証通してキャプチャできるかをやらなくちゃ。続く。

前の記事: