Node.jsとPlaywrightでFirefoxを自動操縦する

これまで社内向けにPuppeteerにてChromeを自動操縦するアプリケーションを複数作成してきました。その自動化の結果として利用者の作業負担が減るとともに、ミスが減り余計なサイトの操作をする学習コストも減らすことが出来ました。

しかし、一部のPCで原因不明のPage CrashエラーSTATUS_STACK_BUFFER_OVERRUNのエラーが出るケースがあり、それをきっかけとして、Puppeteerと同じ源流を持つMicrosoftのPlaywrightを使ってみる事にしました。今回はファイルのダウンロードをするコードを記述してます。

今回使用するライブラリ等

Playwrightは本来Typescriptで記述するのが定石のようですが、通常のJavaScriptであっても利用は可能です。よって、今回は上記のライブラリだけをインストールして利用します。プロジェクトに対して以下のコマンドでインストールしておきます。

また、Puppeteerと一定の互換性があるため、流儀やコードはそのまま利用可能な部分も非常に多いです。Puppeteerについては以下のエントリーを参考にしてみてください。

playwright-firefoxを入れておかないと初回起動時にエラーが出ます。Firefox Nightlyを使いたい場合は、playwright-firefoxもnpmで入れておきましょう(@playwright/testではなくplaywrightの場合、npmでインストール時に3つのコアをダウンロードしてくれますので不要です)

npmでインストールした場合、「C:\Users\ユーザ名\AppData\Local\ms-playwright」にfirefoxはダウンロードされます。

Node.jsとPuppeteerでChromeを自動操縦する

Playwrightについて

概要

PuppetterとPlaywrightはどうやら同じ作者さんが、それぞれGoogleに居たとき、Microsoftに転籍してから作ったプロダクトのようで、非常に親しい存在でありながら、かなり毛色の違う点もあります。

  • Puppeteerと異なり、FirefoxやSafari(Webkit)の操縦もすることが可能
  • 通常のNode.jsだけじゃなく、TypeScriptやPython, Java, .NET等でも利用する事も可能

しかし、親しいだけで完全互換ではありません。特に今回のファイルのダウンロード等に関しては、仕様が大分異なる点もあります。また、ドキュメント量に関しては正直、Playwrightは後発ということもあって、Puppeteerと比較すると少ないのが難点です。

※現在、PuppeteerでもFirefox Nightlyを操作出来ますが、Playwrightの場合Firefox Nightlyの改造版(自動ダウンロードされる)を操作することになります。

図:FireFoxの改造版を動作してる様子

図:Firefoxの別途インストールを要求

Electron等で配布するような場合

現在、exectablePathで指定出来るのは、EdgeとChromiumのみで、FirefoxやSafariはexeを指定しても動作しません。指定しても通常のFireFoxでは以下のようなエラーが出て起動できません。Nightlyをインストールしても同様のエラーで、jugglerという特殊なバージョンでなければ動作しないようです。

よって、Electron等にPlaywrightを組み込んで配布するようなプログラムの場合は、クライアントPCにてnpmでインストール等当然できないので、以下のような措置が必要となります。

  1. C:\Users\ユーザ名\AppData\Local\ms-playwright\firefox-1323\firefox」の場所にFirefox Jugglerがインストールされてる必要性がある
  2. 1.のファイル群は開発マシンの中にだけ存在するので、上記のファイル群をパッケージにして別途配布する。
  3. 1.のケースの場合、exectablePathにてfirefox.exeを指定しても動作します

コードと解説

ソースコード

Puppeteerと大きくことなる点がいくつかあるので、そこを注意しながら記述する必要があります。

解説

どのブラウザを利用するか?を決めるのが1行目。変数名でfirefoxを指定するとFirefoxを利用する事が可能になります。Firefox自体は初回に自動ダウンロードされるため、ユーザが別途インストールする必要はありません(またこのときダウンロードされるのは、Firefox Nightlyになります)

webkitを指定すればSafariを、Chromiumを指定すればChromiumを操作するようになります。

次に、browserの定義でfirefox.launchにオプション指定することが可能です。ダウンロードをさせる場合には以下の2つの指定が必要です。Puppeteerの場合は、cdpsessionにてdownload先の変更をしていましたが、Playwrightの場合はオプション指定で変更が必要になっています。

ダウンロードについても単純にボタンをクリックして終わり・・・ではなく、イベントの定義が必要となっていて、定義をしておき、その結果としてダウンロードされるファイルは通常のファイルではなくテンポラリファイルになっています。よって、fs.renameSyncにてそれを本来のファイル名にリネームする処理を追加しています。パスは変数downloadの中に格納されるので、download.path()でフルパスを取得することが可能となっています。

page.waitForEvent(‘download’)が、ダウンロード待機できるのは、デフォルトでは30秒までなので、操作が多いコードの上部でセットしてしまうと操作中にTimeoutしてしまうので、ダウンロード直前にセットすると良いでしょう。またTimeoutの指定秒数を指定する事も可能です。

ややこしい反面、きちんとダウンロード待機してくれるので、コード自体はPuppeteerよりもスッキリしてると思います。また、公式サイトにはPromiseでダウンロードボタンをクリックして完了するまでを括って、ダウンロード完了待ちの事例が掲載されています。

Puppeteerを使ってボタンクリックとダウンロード

viewportの指定

上記のコードではブラウザの画面サイズ等していせずに起動していますが、予め開くサイズを指定した状態で起動させる事も可能。以下のようにviewportを指定する事が可能です。Puppeteerとは指定方法が異なる点の1つです。

pkgでEXE化できるのか?

Puppeteerの場合、puppeteer-coreを利用していたので、pkgにて単体のEXE化するにあたって以下のコマンドで簡単にパッケージにできました。ブラウザコンポーネントを含んでいないので、node_modulesなどがパッケージにされずといったこともありませんでした。

しかし、今回のplaywrightの場合、バイナリのEXEが含まれている為、@playwright/testの場合はCannot include directory %1のエラーが出て失敗。playwrightの場合はUnexpected characterのエラーが出て失敗。

playwright-coreの場合、インストール済みのブラウザは利用できるものの、firefoxはexectablePathで指定ができない為使えません。

よって現時点ではEXEでパッケージにしてどうこうはできそうにないです。

関連リンク

共有してみる:

コメントを残す

メールアドレスが公開されることはありません。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください