PowerScan
JA

ローカルAPIでブラウザプロファイルを自動化する

自動化 · 読了目安 8 分 · PowerOps 著

写真: Unsplash

スクリプトからプロファイルを起動してデバッグ用エンドポイントを受け取り、アイデンティティとプロキシがすでに設定済みのブラウザにPlaywrightやPuppeteerで接続する方法を解説します。

アンチディテクトブラウザの自動化は、難しい問題として語られることがよくあります。実際はそうではありません。ツールが、自動化ライブラリがすでに使い方を知っているもの、つまりデバッグ用エンドポイントを渡してくれさえすればよいのです。

全体像

PowerOpsは、ループバックアドレスにバインドされたHTTP APIを実行します。スクリプトがプロファイルの起動を依頼すると、そのプロファイルのアイデンティティ、ストレージ、プロキシがすでに設定された状態でブラウザが起動し、実行中のブラウザのWebSocketエンドポイントが返されます。スクリプトは、Playwright、Puppeteer、またはDevToolsプロトコルを話せる他のツールで、そのエンドポイントに接続します。

自動化ライブラリは、フィンガープリントが何であるかを知る必要がありません。接続する時点で、環境はすでに整っています。

プロファイルを起動する

curl -s -H "Authorization: Bearer $POWEROPS_API_KEY" \
  http://127.0.0.1:50326/status

ステータス確認を除くすべてのルートで、ベアラーキーが必要です。ブラウザを起動すると、接続先のエンドポイントが返されます。

curl -s -X POST \
  -H "Authorization: Bearer $POWEROPS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"profileId": "..."}' \
  http://127.0.0.1:50326/browser/start

ライブラリを接続する

import { chromium } from "playwright";

const res = await fetch("http://127.0.0.1:50326/browser/start", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.POWEROPS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ profileId }),
});

const { ws } = await res.json();

// The profile's identity, storage and proxy are already in place.
const browser = await chromium.connectOverCDP(ws);
const [context] = browser.contexts();
const page = context.pages()[0] ?? await context.newPage();

await page.goto("https://example.com");

重要なのはコメントの行です。スクリプトの中にフィンガープリントの設定はありません。環境を設定するのはスクリプトの仕事ではないからです。それはプロファイルに属し、人が行をクリックして開いても、午前3時にスケジュールされたジョブが開いても、同じままです。

APIがカバーする範囲

ローカルに保つ仕組み

サインイン済みのアカウントを保持するブラウザを操作するAPIには、その境界について一言触れておく価値があります。

真似する価値のあるパターン

グループ内のプロファイルを照会し、一つずつ起動して作業を行い、停止します。すべてを一度に実行するのではなく、数個ずつ実行してください。制約になるのは自分のマシンのメモリで、各プロファイルは本物のブラウザプロセスだからです。

const { profiles } = await api("/profiles?groupId=" + groupId);

for (const batch of chunk(profiles, 5)) {
  await Promise.all(batch.map(async (profile) => {
    const { ws } = await api("/browser/start", { profileId: profile.id });
    try {
      await doTheWork(ws);
    } finally {
      await api("/browser/stop", { profileId: profile.id });
    }
  }));
}

`finally`でプロファイルを停止することは、見た目以上に重要です。正常に閉じることでブラウザの状態が書き出され、セッションの途中で強制終了されたプロファイルは、確立したばかりのセッションを失うことがあります。

すべての記事 · スキャンを実行