# BroSDK Playwright Python 深度教程
`brosdk-playwright` 是 BroSDK 指纹浏览器与 Playwright 自动化的**一键式集成方案**。它的核心理念是:**BroSDK 负责“造环境”(指纹/代理/会话持久化),Playwright 负责“干活”(页面自动化)**,两者通过 CDP(Chrome DevTools Protocol)桥接。
只需将 import 路径从 `playwright.sync_api` 换成 `brosdk_playwright`,即可在**不改变任何 Playwright 使用习惯**的前提下,获得多版本指纹内核、独立代理 IP、Cookie/Storage 会话持久化能力。
## 一、核心能力速览
| 能力 | 说明 |
|------|------|
| **零切换成本** | `sync_playwright()` 与 Playwright 官方签名完全一致,所有 API 原样可用 |
| **指纹环境管理** | 自动创建/复用 BroSDK 浏览器环境(独立指纹、独立代理) |
| **会话持久化** | 通过 `env_id` 复用环境,自动恢复 Cookie/Storage/登录态 |
| **CDP 自动桥接** | 将 BroSDK 异步启动事件桥接成同步的 `launch()` |
| **多环境并发** | 每个环境自动分配独立 CDP 端口,规避端口冲突 |
| **混合用法** | 不传 `env` 时走原生 Playwright;`firefox`/`webkit` 透传给原生 Playwright |
## 二、安装
### 基础安装
```bash
pip install brosdk-playwright
```
### 源码安装
```bash
git clone https://github.com/browsersdk/brosdk-playwright-python.git
cd brosdk-playwright-python
pip install .
```
### 反检测模式(Stealth)安装
如需使用反检测模式,需安装可选依赖:
```bash
pip install brosdk-playwright[stealth]
```
### 环境要求
| 项目 | 要求 |
|------|------|
| Python | 3.8+ |
| 原生库 | BroSDK 动态库(`brosdk.dll` / `brosdk.dylib` / `libbrosdk.so`) |
| 认证 | BroSDK API Key 或 userSig |
**特别说明**:`brosdk` PyPI 包是纯 Python 包,**不包含**原生动态库。`brosdk-playwright` 会在首次使用时**自动从 GitHub Releases 下载**对应平台的动态库到工作目录的 `libs/` 下。离线环境可通过 `auto_download=False` 关闭自动下载,并手动指定 `lib_path`。
Playwright 浏览器二进制**仅在走原生 Playwright**(`launch()` 不传 `env`,或用 `firefox`/`webkit`)时才需要 `playwright install`;走 BroSDK 时浏览器内核由 BroSDK 管理。
## 三、工作原理
```
用户代码 (Playwright API, 不变)
│
▼
brosdk-playwright 包装层
┌─────────────────────────────────────────┐
│ _BroBrowserType.launch(env=...) │
│ 1. resolve_env → 创建/复用环境 │
│ 2. launch_browser → sdk.browser_open │
│ (异步事件 20111 → 同步等待 CDP 端口) │
│ 3. connect_over_cdp → Playwright 连接 │
└─────────────────────────────────────────┘
│
▼
BroSDK 原生 SDK (brosdk.dll/.dylib/.so)
指纹内核 · 代理 · Cookie/Storage 持久化
```
**关键技术点**:`sdk_browser_open` 是异步的——CDP 端口不在返回值里,而是在事件回调 `eventId=20111`(`browser-open-success`)的 `data.remoteDebuggingPort` 字段中送达。本包用 `threading.Event` 把这个异步事件桥接成同步的 `launch()`。
## 四、快速开始
### 1. 配置 SDK(进程级,只需一次)
```python
import brosdk_playwright as bp
bp.configure(
api_key="your-api-key", # 或设置环境变量 BROSDK_API_KEY
work_dir="./.brosdk", # SDK 工作目录
# lib_path="...", # 可选:指定动态库路径(缺省时自动查找/下载)
# auto_download=True, # 可选:找不到库时自动下载(默认开启)
# lib_version="1.0.1.1", # 可选:指定下载的库版本(默认 latest)
# stealth=True, # 可选:反检测模式,默认 False
# port=0, # 可选:0=自动分配端口(默认)
# customer_id="default", # 可选
)
```
也支持纯环境变量配置(无需 `configure`):
```bash
export BROSDK_API_KEY=your-api-key
export BROSDK_WORK_DIR=./.brosdk
```
### 2. 像 Playwright 一样写代码
```python
from brosdk_playwright import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(env={
"kernel_version": "134"
})
page = browser.new_page()
page.goto("https://example.com")
print(page.title())
browser.close() # 断开 CDP + 关闭浏览器(自动持久化 cookie)
bp.shutdown() # 关闭 BroSDK,释放原生资源
```
### 3. 运行官方 Demo
```bash
# 交互式演示
python examples/demo.py --api-key YOUR_API_KEY
# 快速演示
python examples/demo.py --quick --api-key YOUR_API_KEY
```
## 五、`env` 配置详解
`p.chromium.launch(env={...})` 的 `env` 字典支持以下字段:
| 字段 | 类型 | 说明 |
|------|------|------|
| `env_id` | string | 直接指定 BroSDK 环境 ID,复用已有环境(自动恢复登录态)。省略则创建新环境 |
| `kernel_version` | string | Chrome 内核版本,如 `"134"`/`"131"`/`"127"`,默认 `"134"` |
| `proxy` | string | 代理地址,如 `socks5://user:pass@host:1080` |
| `region` | string | 国家代号(无法获取代理时生成对应区域 IP) |
| `system` | string | 操作系统,如 `"Windows 11"` |
| `finger` | dict | 完整指纹配置(整体覆盖,详见 BroSDK 文档) |
| `env_name` | string | 环境名称(默认自动生成) |
| `args` | list | 追加的 Chromium 启动参数 |
| `urls` | list | 启动后自动打开的 URL 列表 |
| `cookies` | list | 启动时注入的 Cookie(WebExtension API 格式) |
| `extensions` | list | 加载的扩展列表 |
| `forward` | string | 本次启动使用的前置跳板 |
| `launch_timeout` | float | 启动超时(秒),默认 60 |
### 会话复用示例
```python
# 第一次启动,创建环境
with sync_playwright() as p:
browser = p.chromium.launch(env={
"kernel_version": "134",
"proxy": "socks5://user:pass@host:1080"
})
page = browser.new_page()
page.goto("https://example.com/login")
# ... 执行登录操作 ...
env_id = browser.brosdk_env_id # 保存环境 ID
browser.close()
# 第二次启动,复用环境(自动恢复登录态)
with sync_playwright() as p:
browser = p.chromium.launch(env={
"env_id": env_id # 传入保存的环境 ID
})
page = browser.new_page()
page.goto("https://example.com/dashboard") # 已登录状态
browser.close()
```
> **关键点**:记住 `browser.brosdk_env_id`,下次 `launch(env={"env_id": ...})` 传入即可——BroSDK 环境本身持久化 cookie/storage,同一 envId 再次启动自动恢复登录态。省略 `env_id` 时创建新环境。
## 六、API 完整参考
### 模块级 API
| 名称 | 说明 |
|------|------|
| `configure(api_key=..., ...)` | 配置 SDK 认证与工作目录(进程级) |
| `sync_playwright()` | 与 Playwright 同名上下文管理器,返回包装后的 `Playwright` |
| `BroSDKError` | 本包抛出的所有错误的基类 |
| `list_envs()` | 返回当前账号下的环境列表 |
| `destroy_env(env_id)` | 销毁环境(删除环境及其所有持久化数据) |
| `shutdown()` | 关闭 BroSDK,释放原生资源 |
| `get_config()` | 读取当前配置 |
### Browser 增强字段
走 BroSDK 启动的 `browser` 对象额外暴露以下字段:
| 字段 | 说明 |
|------|------|
| `browser.brosdk_env_id` | 关联的 BroSDK 环境 ID |
| `browser.cdp_port` | 浏览器 CDP 调试端口 |
## 七、反检测模式(Stealth)
BroSDK 已经管理指纹和 Chromium 启动参数(如 `--disable-blink-features=AutomationControlled`),但 Playwright 通过 CDP 连接时仍会暴露自动化特征(`Runtime.enable`/`Console.enable` 泄漏等)。
开启 `stealth=True` 后,CDP 连接客户端从 Playwright 切换为 [patchright](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright-python)(undetected playwright fork),在 BroSDK 管理的浏览器之上叠加 driver 级反检测补丁,**可过 Cloudflare / Datadome / Akamai / CreepJS / Sannysoft 等检测**。
### 启用方式
```python
import brosdk_playwright as bp
bp.configure(
api_key="your-api-key",
stealth=True # 开启反检测模式
)
```
或通过环境变量:
```bash
export BROSDK_STEALTH=1
```
> **注意**:patchright 仅支持 Chromium 内核(与本项目的 BroSDK 流程一致,`firefox`/`webkit` 透传不受影响)。
## 八、进阶用法
### 多环境并发
每个环境自动分配独立 CDP 端口,规避端口冲突:
```python
from brosdk_playwright import sync_playwright
import threading
def run_env(env_id, proxy):
with sync_playwright() as p:
browser = p.chromium.launch(env={
"env_id": env_id,
"proxy": proxy,
"kernel_version": "134"
})
page = browser.new_page()
page.goto("https://example.com")
# ... 执行任务 ...
browser.close()
# 并发运行多个环境
threads = []
for i in range(5):
t = threading.Thread(target=run_env, args=(f"env_{i}", f"socks5://proxy{i}:1080"))
threads.append(t)
t.start()
for t in threads:
t.join()
```
### 混合用法
不传 `env` 时走原生 Playwright;`firefox`/`webkit` 透传给原生 Playwright:
```python
from brosdk_playwright import sync_playwright
with sync_playwright() as p:
# 走 BroSDK(Chromium + 指纹环境)
browser_chrome = p.chromium.launch(env={
"kernel_version": "134"
})
# 走原生 Playwright(不传 env)
browser_firefox = p.firefox.launch() # 需要 playwright install firefox
browser_webkit = p.webkit.launch() # 需要 playwright install webkit
```
### 环境管理
```python
import brosdk_playwright as bp
# 列出所有环境
envs = bp.list_envs()
print(envs)
# 销毁特定环境
bp.destroy_env("2070365861541056512")
# 关闭 SDK,释放资源
bp.shutdown()
```
## 九、适用场景
1. **多账号运营 SaaS**:每个账号用独立 `env_id` 隔离环境,独立指纹/代理/cookie
2. **自动化测试**:现有 Playwright 测试套件零改动获得指纹和代理能力
3. **AI Agent 浏览器任务**:在 LangChain/AutoGPT 工具链中为 Playwright 注入指纹环境
4. **ERP/CRM 集成**:企业 Playwright 脚本复用,带会话持久化
## 十、项目结构
```
brosdk-playwright-python/
├── brosdk_playwright/
│ ├── __init__.py # 公共 API 导出
│ ├── _config.py # 全局配置 + 认证
│ ├── _sdk.py # 环境管理 + 异步事件→同步 launch/close 桥接
│ ├── _downloader.py # 原生库自动下载(GitHub Releases)
│ ├── _playwright.py # Playwright API 包装层
│ └── sync_api.py # sync_playwright() 上下文管理器
├── examples/ # 使用示例 + 交互式 CLI Demo
├── config/ # E2E 测试配置
├── tests/ # 单元测试 + e2e/
└── pyproject.toml
```
## 十一、开发与测试
```bash
# 安装开发依赖
pip install -e ".[dev]"
# 运行测试(不依赖真实 SDK、浏览器或 API Key)
pytest
```
测试通过伪 `BrosdkManager` 注入,验证核心的异步→同步桥接逻辑。
## 十二、与 BroSDK 生态的关系
| 仓库 | 说明 |
|------|------|
| [brosdk](https://github.com/browsersdk/brosdk) | 原生 C/C++ SDK |
| [brosdk-python](https://github.com/browsersdk/brosdk-python) | Python 语言绑定(本包依赖) |
| [brosdk-docs](https://github.com/browsersdk/brosdk-docs) | 官方文档和 API 参考 |
| [brosdk-typescript](https://github.com/browsersdk/brosdk-typescript) | TypeScript 语言绑定 |
## 十三、常见问题
### Q1: 首次使用时提示找不到动态库?
A: `brosdk-playwright` 会自动从 GitHub Releases 下载对应平台的动态库。如网络受限,可手动下载并指定 `lib_path`。
### Q2: 如何指定特定版本的 BroSDK 库?
A: 在 `configure()` 中传入 `lib_version="1.0.0.5"`。
### Q3: 会话持久化是如何实现的?
A: 通过 `env_id` 复用已有环境,BroSDK 自动恢复该环境上次的 Cookie/Storage/登录态。
### Q4: 能否同时使用多个环境?
A: 可以。每个环境自动分配独立 CDP 端口,支持多环境并发。
### Q5: 反检测模式(Stealth)能过哪些检测?
A: 可过 Cloudflare / Datadome / Akamai / CreepJS / Sannysoft 等检测。