Closed5
Playwrightでブラウザ自動操作終了後に継続して手動操作する方法

実現したいこと
- Playwrightでブラウザ操作を途中まで自動化したい。
- 続きは手動で操作を継続したい。
- 手動操作終了後、手動でブラウザを閉じることで起動元のPlaywrightも正常終了させたい。
→起動元のPlaywrightが終了するとブラウザも当然終了してしまうので、2の時点で何らかの対応が必要。

前提条件
- Playwright for .NET 1.50.0
- インストール済みのGoogle Chrome(Playwrightではブラウザをインストールしない)
- 通常表示とヘッドレスのどちらも利用するが、今回は手動操作するため通常表示のみ
- puppeteer/pyppeteerやPower Automateの代替としてブラウザ操作の自動化のみが目的(テスト自動化等の本来の用途は全くわかっていない)

結論
Task.Delay(-1)で止めてCloseイベントのコールバックでキャンセル処理を行う
- 自動操作したいところを通常通り記述する。
- 手動操作したいところで
Task.Delay(-1, CancellationToken)
で止め、手動操作する。 - ブラウザを手動で閉じることで、Closeイベントを発生させコールバック内で2をキャンセル処理、ブラウザとPlaywrightを正常終了させる。
その前に試した方法は2つ。
他の方法1 PauseAsync()で止める(用途によっては有効)
- 自動操作したいところを通常通り記述する。
- 手動操作したいところで
Page.PauseAsync()
で止め、手動操作する。(Inspectorウィンドウが開く) - InspectorウィンドウのResumeボタン(F8)を押下することで、2以降に処理が戻り、ブラウザとPlaywrightを正常終了させる。
→Inspectorウィンドウが別途開いてしまって鬱陶しい。
他の方法2 Page.IsClosedが変わるのを待つ(安易だけど動く)
- 自動操作したいところを通常通り記述する。
- 手動操作したいところで
while (! Page.IsClosed) await Task.Delay(10000);
などの適当な無限ループで止め、手動操作する。 - ブラウザを手動で閉じることで、
Page.IsClosed
がtrueに変わって2の無限ループを抜け、ブラウザとPlaywrightを正常終了させる。
→無限ループとTask.Delay()を使うならもっと良い方法がありそう。

Task.Delay(-1)で止めてCloseイベントのコールバックでキャンセル処理を行う
using Microsoft.Playwright;
// キャンセルトークン
CancellationTokenSource _cancellationTokenSource = new();
var _cancellationToken = _cancellationTokenSource.Token;
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.LaunchAsync(new()
{
Channel = "chrome", // インストール済みのChromeを起動
Headless = false // trueならヘッドレス
});
var context = await browser.NewContextAsync();
var page = await context.NewPageAsync();
// ブラウザのCloseイベント発生時の処理
page.Close += (_, _) => // 非同期処理がある場合は async (_, _) =>
{
// ブラウザがCloseされたタイミングでキャンセル実行
_cancellationTokenSource.Cancel();
_cancellationTokenSource.Dispose();
};
// 自動操作を書く
await page.GotoAsync("https://example.jp");
// ClickAsync()や
// FillAsync()など
// ここまでで自動操作終了
// ここから手動操作に移る
try
{
// キャンセルされるまで待つ
await Task.Delay(-1, _cancellationToken);
}
catch (Exception) {}
await context.CloseAsync();
await browser.CloseAsync();

他の方法1 PauseAsync()で止める(用途によっては有効)
// キャンセルトークンとブラウザのCloseイベント発生時の処理は不要
// ここから手動操作に移る、の try~catch を以下に書き換え
await page.PauseAsync();
他の方法2 Page.IsClosedが変わるのを待つ(安易だけど動く)
// キャンセルトークンとブラウザのCloseイベント発生時の処理は不要
// ここから手動操作に移る、の try~catch を以下に書き換え
while (! page.IsClosed) await Task.Delay(10000);
このスクラップは2025/02/12にクローズされました