快速開始:接管候鳥環境
本章節提供三種語言的完整、可運行腳本。請選擇您最熟悉的語言進行操作。核心邏輯完全一致:向 ApiServer 請求 ws 地址,然後使用 connectOverCDP 接管候鳥。
方式一:JavaScript / Node.js 版
創建文件 start.js:
javascript
const { chromium } = require('playwright');
const axios = require('axios');
// ============================
// 配置項 (請填寫您的實際信息)
// ============================
const API_URL = 'http://127.0.0.1:8186';
const SESSION_ID = 'replace_with_your_session_id'; // 候鳥環境右鍵 -> 複製環境 ID
async function main() {
// ── 步驟 1: 告訴 ApiServer 開啟指定環境 ────────
console.log('⏳ 正在開啟候鳥環境...');
let wsEndpoint;
try {
const response = await axios.post(`${API_URL}/api/v1/browser/start`, {
Session_ID: SESSION_ID
});
if (response.data.code !== 0) {
console.error('❌ 環境啟動失敗:', response.data.message);
return;
}
// ── 步驟 2: 提取 WebSocket 地址 (Playwright 專用字段) ──
wsEndpoint = response.data.data.ws;
console.log('✅ 環境已開啟。ws 地址:', wsEndpoint);
} catch (err) {
console.error('❌ 無法連接 ApiServer,請確保它已運行!', err.message);
return;
}
// ── 步驟 3: 使用 connectOverCDP 接管 ─────────────────
const browser = await chromium.connectOverCDP(wsEndpoint);
console.log('🎉 Playwright 接管成功!');
try {
// ── 步驟 4: 獲取當前上下文與頁面 ────────────────────
// 候鳥環境有默認上下文,直接取第一個
const context = browser.contexts()[0];
const page = context.pages()[0] || await context.newPage();
// ── 步驟 5: 執行業務操作 ─────────────────────
await page.goto('https://www.mbbrowser.com', { waitUntil: 'domcontentloaded' });
console.log('📄 當前頁面標題:', await page.title());
// 等待 3 秒方便觀察
await page.waitForTimeout(3000);
console.log('✅ 腳本執行結束!');
} finally {
// 斷開 Playwright 連接 (候鳥窗口會繼續運行)
await browser.close();
}
}
main().catch(console.error);運行:
bash
node start.js方式二:Python 版
創建文件 start_playwright.py:
python
import requests
from playwright.sync_api import sync_playwright
# ============================
# 配置項
# ============================
API_URL = "http://127.0.0.1:8186"
SESSION_ID = "replace_with_your_session_id"
def get_ws_endpoint(session_id: str) -> str or None:
"""調用候鳥 ApiServer 啟動環境並返回 ws 地址"""
print("⏳ 正在開啟候鳥環境...")
try:
resp = requests.post(
f"{API_URL}/api/v1/browser/start",
json={"Session_ID": session_id},
timeout=30
)
data = resp.json()
except requests.exceptions.ConnectionError:
print("❌ 無法連接 ApiServer!請確保 apiserver.exe 已運行。")
return None
if data.get("code") != 0:
print(f"❌ 環境啟動失敗: {data.get('message')}")
return None
ws = data["data"]["ws"]
print(f"✅ 環境已開啟。ws 地址: {ws}")
return ws
def main():
ws_endpoint = get_ws_endpoint(SESSION_ID)
if not ws_endpoint:
return
with sync_playwright() as p:
# ── 使用 connect_over_cdp 接管 ─────────────────
browser = p.chromium.connect_over_cdp(ws_endpoint)
print("🎉 Playwright 接管成功!")
# 取出已有的默認 BrowserContext (保留所有 Cookie, Storage 等)
context = browser.contexts[0]
# 取首個頁面,若無則建新頁
page = context.pages[0] if context.pages else context.new_page()
# ── 執行業務操作 ──────────────────────────────
page.goto("https://www.mbbrowser.com", wait_until="domcontentloaded")
print(f"📄 當前頁面標題: {page.title()}")
page.wait_for_timeout(3000)
print("✅ 腳本執行結束!")
browser.close()
if __name__ == "__main__":
main()運行:
bash
python start_playwright.py方式三:Java 版
NOTE
對於 Java 版本,我們推薦使用候鳥客戶端的自動化腳本管理器,它會自動處理 Playwright JAR 包和驅動提取。以下代碼可直接在腳本編輯器中使用。
java
import com.microsoft.playwright.*;
import java.net.URI;
import java.net.http.*;
import org.json.*;
public class MBPlaywright {
static final String API_URL = "http://127.0.0.1:8186";
static final String SESSION_ID = "replace_with_your_session_id";
public static void main(String[] args) throws Exception {
// ── 步驟 1: 調用 ApiServer 啟動環境 ──────────────
System.out.println("⏳ 正在開啟候鳥環境...");
HttpClient httpClient = HttpClient.newHttpClient();
String body = "{\"Session_ID\":\"" + SESSION_ID + "\"}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "/api/v1/browser/start"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> response = httpClient.send(
request, HttpResponse.BodyHandlers.ofString()
);
JSONObject data = new JSONObject(response.body());
String wsEndpoint = data.getJSONObject("data").getString("ws");
System.out.println("✅ 環境已開啟。ws: " + wsEndpoint);
// ── 步驟 2: Playwright connectOverCDP 接管 ───────────────
// 設置跳過內置瀏覽器下載
System.setProperty("playwright.skip.browser.download", "1");
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().connectOverCDP(wsEndpoint);
System.out.println("🎉 Playwright 接管成功!");
BrowserContext context = browser.contexts().get(0);
Page page = context.pages().isEmpty()
? context.newPage()
: context.pages().get(0);
page.navigate("https://www.mbbrowser.com");
System.out.println("📄 當前頁面標題: " + page.title());
Thread.sleep(3000);
System.out.println("✅ 腳本執行結束!");
browser.close();
}
}
}逐行解析
connectOverCDP vs launch: 決定性區別
javascript
// ❌ 普通 Playwright 做法:新建一個空白的 Chrome 窗口
const browser = await chromium.launch();
// ✅ 候鳥 Playwright 做法:接管已有的指紋環境
const browser = await chromium.connectOverCDP(wsEndpoint);| 對比項 | 普通 launch() | 候鳥 connectOverCDP() |
|---|---|---|
| 瀏覽器狀態 | 全新、空白 | 帶指紋、代理、已有 Cookie |
| 後果 | 目標站點識別為 bare Chrome bot | 目標站點識別為「真人用戶」 |
| 多帳號 | 無法區分身份 | 通過 Session_ID 精確對應 |
為什麼用 data.ws 而不是 data.http?
| 字段 | 示例格式 | 適用框架 |
|---|---|---|
data.http | 127.0.0.1:9222 | Selenium (debuggerAddress) |
data.ws | ws://127.0.0.1:9222/devtools/browser/xxx | Playwright / Puppeteer ✅ |
Playwright 的 connectOverCDP 必須使用完整的 ws://... 地址。
browser.contexts()[0]: 不要創建新上下文
javascript
// ❌ 錯誤:新建上下文,候鳥中的 Cookie、存儲將丟失。
const context = await browser.newContext();
// ✅ 正確:使用候鳥已有的上下文 (保留帳號狀態)。
const context = browser.contexts()[0];常見問題故障排除
❓ 報錯: connect ECONNREFUSED 127.0.0.1:8186
ApiServer 未啟動或端口填寫錯誤。請確保 apiserver.exe 在終端窗口中運行。
❓ 報錯: Browser closed 或 Target page, context or browser has been closed
候鳥環境已被關閉 (超時或人工關閉)。請重新調用 /api/v1/browser/start。
❓ browser.contexts() 返回空數組
環境剛開啟時,默認上下文初始化可能需要幾百毫秒。建議加入短暫重試機制:
javascript
// 等待上下文出現 (最多等 5 秒)
let context;
for (let i = 0; i < 50 && !browser.contexts().length; i++) {
await new Promise(r => setTimeout(r, 100));
}
context = browser.contexts()[0];❓ browser.close() 會關閉候鳥窗口嗎?
在 connectOverCDP 模式下,browser.close() 僅會斷開 Playwright 的鏈接,不會關閉候鳥窗口。如需關閉窗口,請調用 stop 接口:
javascript
await axios.post(`${API_URL}/api/v1/browser/stop`, { Session_ID: SESSION_ID });TIP
準備好碼代碼了嗎?下一章 核心 API 參考 將教您如何使用 Playwright 強大な Locator 和 Page API。
