C#でSeleniumをやめてPlaywrightを使ってみた1
Playwrightっていうのがあるらしい
ブラウザの自動処理ってSeleniumでいつもやっているんだけど、別に不満もないけど、比較的新しいツールとしてPlaywrightがいいらしいときいた。
どうせ自分はSeleniumを使うといってもChromeで自動処理したいだけなんだけど、Seleniumの場合、Chromeのバージョンアップにともなって適合するバージョンのドライバをダウンロードしなきゃいけなかったりでちょっと不便。(ま、起動時にチェックして自動でダウンロードする専用クラスは自作したんだけど)
で、Seleniumで自動処理しているときにときどきブラウザ自体が落ちるときがあって、これを何とかしたいと思って調べたらPlaywrightが引っかかってきた。とはいえ、ブラウザが落ちなくなるとかSeleniumより安定するという話があったわけではない。
ただただ、古くからあるSeleniumではなく2020年産の新しいツール(思想)であるPlaywrightに移行するのもよさそうだし、Microsoftが面倒みているので、将来性も悪くなさそう。
とはいえ、PlaywrightをC#で日本語で説明しているページとかも見つからない。あるのかもしれないけど。
Visual Studio 2017で手探りでやってみようとしたが、うまくいかん。なぜ失敗したかというと、.Netframework 4.8でやろうとしたから。どうも.NET Core 5.0でないと駄目なようだが、Visual Studio 2017では無理。(Core のもっと下のバージョンでもいいのかもしれないが少なくとも2017のコンソールアプリプロジェクトで.NET Core 2.1を指定してもだめだった)
Visual Studio 2022のインストール
と、いうことでVisual Studio 2022のインストールから。
https://visualstudio.microsoft.com/ja/vs/ ←からVisual Studio Community 2022を選択してダウンロードしてインストール
C#のデスクトップ開発なので、デフォルトのままインストール。
テスト用のプロジェクトを作成
プロジェクトを新規で起こす。.NET 5.0用なので、Windows フォームアプリを選ぶ(.Netframeworkがついていないほう)
プロジェクト名を適当につける。ちなみに自分はソースリストの変数やメソッド名を日本語で書く人なので、当然プロジェクト名も日本語。
追加情報のフレームワークで.NET 5.0を選ぶ。6.0でもいいとは思うが。
続いてNuGetパッケージのインストール。「プロジェクト」→「NuGetパッケージの管理」
「参照」のタブを押して検索窓に「Playwright」と入力して検索するといくつか出てくるが、「Microsoft.Playwright」を選んで「インストール」する。
これで準備完了。とりあえず、ブラウザを立ちあげるまで行こう。
ブラウザを立ち上げるコード
まずはusing句を追加
枠内をクリックするとソースがクリップボードにコピーされます |
using Microsoft.Playwright; |
つづいて、ブラウザが入っていないPCにブラウザを自動的にダウンロードして入れるための処理をコンストラクタに書く。ChromiumだけじゃなくてFirefoxとか入るみたい。
枠内をクリックするとソースがクリップボードにコピーされます |
var 戻り値 = Microsoft.Playwright.Program.Main(new[] { "install" });
if (戻り値 != 0)
{
Console.WriteLine("ブラウザのインストールに失敗");
Environment.Exit(戻り値);
}
Console.WriteLine("ブラウザがインストールされた");
|
ちなみに、VisualStudio2017の.Netframework 4.8でこれを実行するとブラウザのインストールに失敗した。最初はここでいきなり躓いて、.NET 5.0が必要なことに気づくまで小一時間。
枠内をクリックするとソースがクリップボードにコピーされます |
private async Task ブラウザ起動()
{
var playwright = await Playwright.CreateAsync();
var ブラウザ = await playwright.Chromium.LaunchAsync();
var ブラウザコンテキスト = await ブラウザ.NewContextAsync();
var ページ = await ブラウザコンテキスト.NewPageAsync();
await ページ.GotoAsync("https://www.google.com");
}
|
あとはTask.Run()で呼び出してあげればいいはず。
と、いうことで全体はこんな感じ。
枠内をクリックするとソースがクリップボードにコピーされます |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Microsoft.Playwright; namespace Playwrightテスト { public partial class Form1 : Form { public Form1() { InitializeComponent(); var 戻り値 = Microsoft.Playwright.Program.Main(new[] { "install" }); if (戻り値 != 0) { Console.WriteLine("ブラウザのインストールに失敗"); Environment.Exit(戻り値); } Console.WriteLine("ブラウザがインストールされた"); Task.Run(() => ブラウザ起動()); } private async Task ブラウザ起動() { var playwright = await Playwright.CreateAsync(); var ブラウザ = await playwright.Chromium.LaunchAsync(); var ブラウザコンテキスト = await ブラウザ.NewContextAsync(); var ページ = await ブラウザコンテキスト.NewPageAsync(); await ページ.GotoAsync("https://www.google.com"); } } } |
さて、デバッグ実行してみる。
じゃ~ん。なにも表示されません。
タスクマネージャを開くと、Chromiumが立ち上がっている。
これ、なぜかというと、Headlessモードで動いているから。オプションを設定する必要がある。
こんな感じになおす
枠内をクリックするとソースがクリップボードにコピーされます |
var ブラウザ = await playwright.Chromium.LaunchAsync(
new BrowserTypeLaunchOptions { Headless = false }
); |
さて、デバッグ実行。
じゃじゃ~ん。ちゃんと、ブラウザ表示されたよ。
ChromiumではなくChromeで起ち上げる
OKOK。ただ、毎回インストールのDOS窓出てくるのウザイな。それにChromiumわざわざインストールしなくてもChrome入っているし、Firefoxとか余計なものも入れたくない。
と、いうことで、インストール処理は削ってしまって、かつChromeで立ち上げるようにしよう。
ChromeにするのはBrowserTypeLaunchOptionsにChannelを加える。
枠内をクリックするとソースがクリップボードにコピーされます |
var ブラウザ = await playwright.Chromium.LaunchAsync(
new BrowserTypeLaunchOptions {
Headless = false,
Channel = "chrome"
}
);
|
さて、実行してみよう。
よし。うまくいったよ。っていっても見た目ほぼ一緒でわからないけど、タスクバーのアイコンはChromiumの青系ではなくChromeの黄色系のアイコンになってる。
なお、"chrome"のところは"Chrome"と書いたらダメ。起動しない。
ユーザープロファイルを指定する
Playwrightで起動したChromeでURLに「Chrome://version」と打ってみると、毎回プロファイルのフォルダが違う名前で一時的に作られているようだ。毎回クリーンな環境で起動するのは自動テストで使うには便利だが、クッキーの保存などが無効になってしまうため、自動処理で巡回などをするときに、認証しなおしだったりして面倒。Steamなんかに入ろうものなら、毎回ブラウザの新規認証になってしまう。
と、いうことで、プロファイルフォルダを指定するオプションを設定して起動してみよう。「--user-data-dir」を指定すればいいはず。
ん~、きっとまたオプションで指定すればいいと思う。
https://playwright.dev/dotnet/docs/api/class-browsertype
↑ここを参考にすると、Argsを指定すればよさそう。
複数のオプションを並べるだけでよさそう。
枠内をクリックするとソースがクリップボードにコピーされます |
var ブラウザ = await playwright.Chromium.LaunchAsync(
new BrowserTypeLaunchOptions {
Headless = false,
Channel = "chrome",
Args = new[] { @"--user-data-dir=C:\ChromeProfile" }
}
); |
「C:\ChromeProfile」というフォルダを作っておいて試してみる。
起動してみたけど、タスクバーにも何も出ない。ダメかぁ?何が悪いんだろ。
ここから、悩みに悩む。
「--」は不要で「user-data-dir=C:\ChromeProfile」でやってみてもダメ。
「--user-data-dir="C:\ChromeProfile"」や「user-data-dir="C:\ChromeProfile"」でやってみてもダメ。
じゃあ、ほかのオプションは動くのかと「--browser-test」でやってみたら、ちゃんと起動する。
「=」がついているオプションではうまく行かないのかと思い、試しに「--copy-to-download-dir=C:\temp」で起動してみても動く。
でたらめなオプション「--detarame=C:\detarame」とか指定しても起動する。
なんでぇ??
C#での記事とか見つからないけど、Node.jsとかでは普通に指定しているような記事もあったりするし、さっぱりわからん。
「ブラウザ起動()」メソッドの先頭にブレークポイントを設定して、ステップ実行してみる。
「playwright.Chromium.LaunchAsync()」の処理のあと、ステップ実行がすっ飛んでる。
アレ?例外が起きてる?実行してもなにも出ないけど。あ、そうか、非同期メソッドだから例外取れないんだ。
ということで「Task.Run()」しているところにWait()を追加してみる。
枠内をクリックするとソースがクリップボードにコピーされます |
Task.Run(() => ブラウザ起動()).Wait(); |
実行してみると…
ああぁぁ、例外発生した~。
枠内をクリックするとソースがクリップボードにコピーされます |
System.AggregateException: 'One or more errors occurred. (Pass userDataDir parameter to `browserType. launchPersistentContext(userDataDir, ...)` instead of specifying --user-data-dir argument)' |
なんか、「--user-data-dir」だけ特別っぽいこと書いてる。
「launchPersistentContext()」を使えばいいのか??
枠内をクリックするとソースがクリップボードにコピーされます |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using Microsoft.Playwright; namespace Playwrightテスト { public partial class Form1 : Form { public Form1() { InitializeComponent(); Task.Run(() => ブラウザ起動()).Wait(); } private async Task ブラウザ起動() { var playwright = await Playwright.CreateAsync(); var ブラウザコンテキスト = await playwright.Chromium.LaunchPersistentContextAsync( @"C:\ChromeProfile", new BrowserTypeLaunchPersistentContextOptions { Headless = false, Channel = "chrome" } ); var ページ = await ブラウザコンテキスト.NewPageAsync(); await ページ.GotoAsync("https://www.google.com"); } } } |
こんな感じ。それ、実行。
やっと立ち上がった。「Chrome://version」をたたいてみる。
プロファイルのパスもちゃんと「C:\ChromeProfile」配下になってる。よし。
まずは、こんなところか。ちょっと気になるのは、指定したURL以外にabout:blankのタブがあることか。これなんでだろ。ま、この辺は次回。
コメント
コメントを投稿