そういう、モデルなんです。

ビジネスモデル、3Dモデル、設計図、模型などの現状と動向を考察、関連書籍の紹介

画面操作を自動化するツール Puppeteer (パペティア)職場環境では動かない…(解決)

ここまでのあらすじ

さまざまなトラブルを乗り越え、とにかく自宅のパソコンでは Puppeteer が動作する状態にした。

tombi-aburage.hatenablog.jp

Google での検索結果の参照先を次々と開いて、画像でひたすら保存するスクリプトなどを書いてみたら、うまいこと動作したので、これなら仕事の情報収集でも使えそうだと判断した。

職場のパソコンにインストール

自宅のパソコンで成功したときと同じ手順で、ローカルインストールしようとしたが、まるでうまくいかない。

npm install から、いきなりコケた。

npm install --save puppeteer

npm ERR! code ENOTFOUND
npm ERR! errno ENOTFOUND
npm ERR! network request to https://registry.npmjs.org/puppeteer failed, reason: getaddrinfo ENOTFOUND registry.npmjs.org registry.npmjs.org:443
npm ERR! network This is a problem related to network connectivity.
npm ERR! network In most cases you are behind a proxy or have bad network settings.
npm ERR! network
npm ERR! network If you are behind a proxy, please make sure that the
npm ERR! network 'proxy' config is set properly. See: 'npm help config'

npm ERR! A complete log of this run can be found in:
npm ERR! C:Users ombiAppDataRoaming pm-cache_logs9-05-08T03_28_28_136Z-debug.log

親切にもプロキシが怪しいと書いてある。言う通り職場のプロキシのせいに違いない。

qiita.com

を参考にして npm のプロキシ設定を行うことにする。

proxy と https-proxy に職場指定の auth.pac とかいうファイルを指定

call npm -g config set proxy "http://example.com/auth.pac"
call npm -g config set https-proxy "http://example.com/auth.pac"

この環境設定コマンドは成功した。しかし npm install はやはりうまくいかない。

npm install --save puppeteer

npm ERR! code E405
npm ERR! 405 Method Not Allowed: puppeteer@latest

npm ERR! A complete log of this run can be found in:
npm ERR! C:Users ombiAppDataRoaming pm-cache_logs9-05-08T03_31_43_005Z-debug.log

今度は E405 とかいうエラーに変わった。

registry も設定

call npm -g config set registry "http://registry.npmjs.org/"

この環境設定コマンドは成功した。しかし npm install はやはりうまくいかない。

npm install --save puppeteer

npm ERR! code E404
npm ERR! 404 Not Found: puppeteer@latest

npm ERR! A complete log of this run can be found in:
npm ERR! C:Users ombiAppDataRoaming pm-cache_logs9-05-08T03_36_03_259Z-debug.log

今度は E404 とかいうエラーに変わった。

どう見てもプロキシが怪しい

プロキシ認証を通るよう、パスワード等を指定する

普段からプロキシにアクセスするたびにユーザ名とパスワードを入力しているので、これらの指定をしないとダメなのかもしれない。

qiita.com

を参考にして、

  • まず .PACファイルの中を見て、プロキシの実URLアドレスを割り出す
  • ユーザ名とパスワードを指定したURL表記で設定する

ことにした。

.PACファイル http://example.com/auth.pac をブラウザで覗いてみると、JavaScript の関数みたいなものが書いてあった。

どうやら自分のIPアドレスとアクセス先のURLから、使うプロキシを判定する処理の関数らしかったので、スクリプトの処理内容を分析して、職場パソコンのIPアドレスに対応するプロキシの実URLアドレスを割り出した。

npm config set proxy http://userid:password@proxy.example.com:8080
npm config set https-proxy http://userid:password@proxy.example.com:8080

今度は code EPERM, errono -4048, syscall rename  エラー

先の環境設定コマンドは成功した。しかし npm install はやはりうまくいかない。

npm install --save puppeteer

npm ERR! path P:projectspuppeteer_sample ode_modulesminimistpackage.json.3444437947
npm ERR! code EPERM
npm ERR! errno -4048
npm ERR! syscall rename
npm ERR! Error: EPERM: operation not permitted, rename 'P:projectspuppeteer_sample ode_modulesminimistpackage.json.3444437947' -> 'P:projectspuppeteer_sample ode_modulesminimistpackage.json'
(中略)
npm ERR! The operation was rejected by your operating system.
npm ERR! It's possible that the file was already in use (by a text editor or antivirus),
npm ERR! or that you lack permissions to access it.
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator (though this is not recommended).

OSに拒否されて、ファイルをリネームできないとのこと。

インストール先の P ドライブがローカルではなく、ネットワーク上のドライブであることが関係しているのかもしれない。

職場のネットワークドライブのアクセス権限を変更することはできないので、お奨めしない not recommended と書かれてはいるが「管理者として実行」することにした。(command again as root/Administrator 相当)

なお、このときはすぐに「管理者として実行」をやってしまったが、VS Code を再起動(もしくはパソコンごと再起動)し、ただ同じコマンドを打ち直すだけで治ることも多い。

アクセス権と関係なく、何かのプロセスがファイルをつかんでいて、ファイル操作のタイミングが合わなかった場合にも errno -4048  が出るようだ。

node.js command prompt を管理者として実行してから install

npm install --save puppeteer

> puppeteer@1.15.0 install P:projectspuppeteer_sample ode_modulespuppeteer
> node install.js

Downloading Chromium r650583 - 144.8 Mb [=== ] 17% 204.2s

Chromiumダウンロードに進んだようだ。よしよし。

やはりプロキシだったか

正しくインストールされた模様

Downloading Chromium r650583 - 144.8 Mb [====================] 100% 0.0s
Chromium downloaded to P:projectspuppeteer_sample ode_modulespuppeteer.local-chromiumwin64-650583
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN puppeteer_sample@1.0.0 No description
npm WARN puppeteer_sample@1.0.0 No repository field.

+ puppeteer@1.15.0
added 6 packages from 6 contributors and audited 50 packages in 610.199s
found 0 vulnerabilities

ゲージが100%になった後、続きのメッセージが出るまでに30秒以上待たされ、また失敗したのかと思ったが、無事にインストールは完了した。

全く問題なし

自宅パソコンで動作した実績のあるサンプルスクリプトを職場で起動したが、newPage 呼び出しが永久に終わらない orz

職場のネットワークの遅さのせいなのか、プロキシ経由のせいなのか、パソコンの低性能のせいなのか原因は分からないが、自宅のパソコン(環境)と比べると明らかに動作が遅い。

高々 puppeteer の launch、Chromium の起動までに30秒くらいかかった。
しかし、その後 newPage メソッドを呼び出すところで完全に止まってしまい、それ以上はまったく進まず、常にタイムアウトになってしまう。

いろいろ調べたが同一事象の前例はなくて、行き詰ってしまった。

launch が遅いというケースは多いようだが、newPage で止まる事例は見当たらない。

残念ながら職場では使えないようだ…

なぜ newPage で止まる?

Error: Page crashed!、CDPSession.Page が出ている

ソースの随所にコンソール出力を入れて切り分けた結果、launch までは動作しており、page オブジェクトの生成のところで止まっていることが分かった。

ネットで色々調べたところ、特徴的なエラーメッセージは Error: Page crashed!、CDPSession.Page といえそうだった。

この CDPSession とやらは、puppeteer と Chromium 間のローカルなプロトコルのセッションらしく、それが通っていない(プロセス間通信途絶)ように見えたので、Chromium の起動モードが怪しい?

npm run main

> puppeteer_sample@1.0.0 main P:projectsPuppeteerSample
> index.js

start 16:15:41 GMT+0900 (GMT+09:00)
require 完了 16:16:19 GMT+0900 (GMT+09:00)
launch 完了16:16:25 GMT+0900 (GMT+09:00)
(node:10192) UnhandledPromiseRejectionWarning: Error: Page crashed!
at Page._onTargetCrashed (P:projectsPuppeteerSample ode_modulespuppeteerlibPage.js:170:24)
at CDPSession.Page.client.on.event
(以下略)

プロキシはエラーと関係なし、--no-sandbox 指定で解決

切り分けには延べ日数で4日ほどかかった。

結論としては launch のさいに指定ができる args に --no-sandbox を指定するだけで、先ほどのエラーは出なくなった。

const browser = await puppeteer.launch({
headless: true,
slowMo: 50,
args: [
'--no-sandbox',
]
});

start 16:54:12 GMT+0900 (GMT+09:00)
require 完了 16:54:36 GMT+0900 (GMT+09:00)
launch 完了16:54:39 GMT+0900 (GMT+09:00)
newPage 完了16:54:42 GMT+0900 (GMT+09:00)
setViewport 完了16:54:42 GMT+0900 (GMT+09:00)

--no-sandbox 必須だな…

プロキシのユーザID、パスワードは authenticate で指定

エラーとは関係なかったが、headless: false で動作確認したところプロキシがユーザID、パスワードを要求するダイログを出していたので、以下の要領で記述した。

await page.authenticate({
username: 'プロキシのユーザID',
password: 'プロキシのパスワード'
});

なお args に --proxy-server を指定する必要はなかった。

ようやく、職場でも問題なし