Dev Browser スキル は何をしますか?
スクリプト実行間でページ状態を維持するブラウザ自動化。小さく焦点を絞ったスクリプトを書き、タスクを段階的に達成します。ワークフローの一部が確立し、繰り返し作業がある場合は、1回の実行でその繰り返し作業を行うスクリプトを作成できます。
アプローチの選択
- ローカル/ソースが入手可能なサイト: まずソースコードを読んで、セレクタを直接記述します。
- 未知のページレイアウト:
getAISnapshot()を使用して要素を発見し、selectSnapshotRef()で操作します。 - 視覚的フィードバック: スクリーンショットを撮って、ユーザーが見ているものを確認します。
セットアップ
2つのモードが利用可能です。どちらを使用すべきか不明な場合はユーザーに確認してください。
スタンドアロンモード(デフォルト)
新しいChromiumブラウザを起動して、新しい自動化セッションを開始します。
./skills/dev-browser/server.sh &
ユーザーが要求した場合は --headless フラグを追加してください。スクリプトを実行する前に、Ready メッセージが表示されるのを待ってください。
拡張機能モード
ユーザーの既存のChromeブラウザに接続します。以下の場合に使用します:
- ユーザーが既にサイトにログインしており、ローカル開発ではない認証済みの操作をあなたに行わせたい場合。
- ユーザーが拡張機能の使用を依頼した場合。
重要: コアフローは同じです。ユーザーのブラウザ内に名前付きページを作成します。
リレーサーバーを起動:
cd skills/dev-browser && npm i && npm run start-extension &
コンソールで Waiting for extension to connect... の後に Extension connected が表示されるのを待ちます。これにより、クライアントが接続し、ブラウザが制御可能になったことがわかります。
ワークフロー:
- 通常モードと同様に、スクリプトは
client.page("name")を呼び出して新しいページを作成したり、既存のページに接続したりします。 - 自動化はユーザーの実際のブラウザセッション上で実行されます。
拡張機能がまだ接続されていない場合は、ユーザーに拡張機能を起動して有効にするよう伝えてください。ダウンロードリンク: https://github.com/SawyerHood/dev-browser/releases
スクリプトの作成
すべてのスクリプトは
skills/dev-browser/ディレクトリから実行してください。@/インポートエイリアスを使用するには、このディレクトリの設定が必要です。
ヒアドキュメントを使用して、スクリプトをインラインで実行します:
cd skills/dev-browser && npx tsx <<'EOF'
import { connect, waitForPageLoad } from "@/client.js";
const client = await connect();
// カスタムビューポートサイズでページを作成(オプション)
const page = await client.page("example", { viewport: { width: 1920, height: 1080 } });
await page.goto("https://example.com");
await waitForPageLoad(page);
console.log({ title: await page.title(), url: page.url() });
await client.disconnect();
EOF
スクリプトが再利用を必要とする場合、複雑な場合、またはユーザーが明示的に要求した場合にのみ tmp/ ファイルに書き込んでください。
主要な原則
- 小さなスクリプト: 各スクリプトは1つのこと(ナビゲート、クリック、入力、確認)を行います。
- 状態の評価: 最後に状態をログ/返却して、次のステップを決定します。
- 説明的なページ名:
"checkout"、"login"のように、"main"のような名前は避けます。 - 切断して終了:
await client.disconnect()- ページはサーバー上に保持されます。 - evaluate内ではプレーンなJS:
page.evaluate()はブラウザ内で実行されます - TypeScript構文は使用できません。
ワークフローループ
複雑なタスクには次のパターンに従ってください:
- スクリプトを作成して1つのアクションを実行します。
- 実行して出力を確認します。
- 評価 - 動作しましたか?現在の状態は?
- 決定 - タスクは完了しましたか?それとも別のスクリプトが必要ですか?
- 繰り返し - タスクが完了するまで。
ブラウザコンテキスト内ではTypeScript不可
page.evaluate() に渡されたコードはブラウザ内で実行されますが、ブラウザはTypeScriptを理解しません:
// ✅ 正しい: プレーンなJavaScript
const text = await page.evaluate(() => {
return document.body.innerText;
});
// ❌ 間違い: TypeScript構文は実行時に失敗します
const text = await page.evaluate(() => {
const el: HTMLElement = document.body; // 型アノテーションはブラウザで失敗!
return el.innerText;
});
データのスクレイピング
大規模なデータセットをスクレイピングするには、DOMをスクロールする代わりにネットワークリクエストをインターセプトして再生します。リクエストキャプチャ、スキーマ発見、ページネーションされたAPIの再生に関する完全なガイドは references/scraping.md を参照してください。
クライアントAPI
const client = await connect();
// 名前付きページを取得または作成(viewportは新しいページにのみ適用)
const page = await client.page("name");
const pageWithSize = await client.page("name", { viewport: { width: 1920, height: 1080 } });
const pages = await client.list(); // すべてのページ名を一覧表示
await client.close("name"); // ページを閉じる
await client.disconnect(); // 切断(ページは保持される)
// ARIAスナップショットメソッド
const snapshot = await client.getAISnapshot("name"); // アクセシビリティツリーを取得
const element = await client.selectSnapshotRef("name", "e5"); // 参照で要素を取得
page オブジェクトは標準のPlaywright Pageです。
待機
import { waitForPageLoad } from "@/client.js";
await waitForPageLoad(page); // ナビゲーション後
await page.waitForSelector(".results"); // 特定の要素を待機
await page.waitForURL("**/success"); // 特定のURLを待機
ページ状態の検査
スクリーンショット
await page.screenshot({ path: "tmp/screenshot.png" });
await page.screenshot({ path: "tmp/full.png", fullPage: true });
ARIAスナップショット(要素の発見)
getAISnapshot() を使用してページ要素を発見します。YAML形式のアクセシビリティツリーを返します:
- banner:
- link "Hacker News" [ref=e1]
- navigation:
- link "new" [ref=e2]
- main:
- list:
- listitem:
- link "Article Title" [ref=e8]
- link "328 comments" [ref=e9]
- contentinfo:
- textbox [ref=e10]
- /placeholder: "Search"
refの解釈:
[ref=eN]- 操作用の要素参照(可視でクリック可能な要素のみ)[checked]、[disabled]、[expanded]- 要素の状態[level=N]- 見出しレベル/url:、/placeholder:- 要素のプロパティ
refとの相互作用:
const snapshot = await client.getAISnapshot("hackernews");
console.log(snapshot); // 必要なrefを見つける
const element = await client.selectSnapshotRef("hackernews", "e2");
await element.click();
エラー回復
ページ状態はエラー後も保持されます。以下の方法でデバッグしてください:
cd skills/dev-browser && npx tsx <<'EOF'
import { connect } from "@/client.js";
const client = await connect();
const page = await client.page("hackernews");
await page.screenshot({ path: "tmp/debug.png" });
console.log({
url: page.url(),
title: await page.title(),
bodyText: await page.textContent("body").then((t) => t?.slice(0, 200)),
});
await client.disconnect();
EOF