feat(val-blog): add 2026-04-30 dream journey post
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
# Browser Automation Skill
|
||||
|
||||
使用 Playwright 调用本地 Chrome 进行反检测浏览器自动化。
|
||||
|
||||
## 简介
|
||||
|
||||
此 Skill 封装了浏览器自动化功能,专门设计用于规避常见的爬虫检测机制(如 Cloudflare、DataDome 等)。通过使用本地安装的 Chrome 并配置反检测参数,可以模拟真实用户行为。
|
||||
|
||||
## 特点
|
||||
|
||||
- ✅ **反检测模式**:禁用 `navigator.webdriver` 标记,绕过自动化检测
|
||||
- ✅ **本地 Chrome**:使用系统安装的 Google Chrome,而非 Playwright 自带的 Chromium
|
||||
- ✅ **两种模式**:
|
||||
- **launch 模式**:直接启动 Chrome(带反检测参数)
|
||||
- **cdp 模式**:连接已运行的 Chrome 实例
|
||||
- ✅ **简洁 API**:navigate, click, type, snapshot, scroll, screenshot, close
|
||||
|
||||
## 安装依赖
|
||||
|
||||
```bash
|
||||
# 安装 Playwright
|
||||
pip install playwright
|
||||
|
||||
# 安装 Chromium(playwright 需要,虽然我们使用本地 Chrome)
|
||||
playwright install chromium
|
||||
```
|
||||
|
||||
## 使用方式
|
||||
|
||||
### 1. 基础用法(Launch 模式)
|
||||
|
||||
```python
|
||||
from browser_tool import BrowserTool
|
||||
|
||||
# 创建浏览器实例
|
||||
browser = BrowserTool(mode="launch", headless=False)
|
||||
|
||||
# 导航到页面
|
||||
snapshot = browser.navigate("https://example.com")
|
||||
print(snapshot)
|
||||
|
||||
# 点击元素
|
||||
browser.click("@e5")
|
||||
|
||||
# 输入文本
|
||||
browser.type("@e3", "search query")
|
||||
browser.press("Enter")
|
||||
|
||||
# 滚动页面
|
||||
browser.scroll("down")
|
||||
|
||||
# 截图
|
||||
path = browser.screenshot()
|
||||
|
||||
# 关闭
|
||||
browser.close()
|
||||
```
|
||||
|
||||
### 2. 使用上下文管理器
|
||||
|
||||
```python
|
||||
from browser_tool import BrowserTool
|
||||
|
||||
with BrowserTool(mode="launch", headless=False) as browser:
|
||||
snapshot = browser.navigate("https://example.com")
|
||||
print(snapshot)
|
||||
# 自动关闭
|
||||
```
|
||||
|
||||
### 3. CDP 模式(连接已运行的 Chrome)
|
||||
|
||||
首先启动 Chrome 并开启调试端口:
|
||||
|
||||
```bash
|
||||
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
|
||||
--remote-debugging-port=9222 \
|
||||
--user-data-dir=/tmp/chrome_debug
|
||||
```
|
||||
|
||||
然后在代码中连接:
|
||||
|
||||
```python
|
||||
from browser_tool import BrowserTool
|
||||
|
||||
browser = BrowserTool(mode="cdp", cdp_url="http://localhost:9222")
|
||||
snapshot = browser.navigate("https://example.com")
|
||||
```
|
||||
|
||||
### 4. 使用快捷函数
|
||||
|
||||
```python
|
||||
from browser_tool import create_browser
|
||||
|
||||
browser = create_browser(mode="launch", headless=False)
|
||||
```
|
||||
|
||||
### 5. 启动 Chrome 调试实例
|
||||
|
||||
```python
|
||||
from browser_tool import launch_chrome_debug_port
|
||||
|
||||
# 启动 Chrome 并开启 9222 端口
|
||||
proc = launch_chrome_debug_port(port=9222)
|
||||
|
||||
# 之后可以用 CDP 模式连接
|
||||
```
|
||||
|
||||
## API 参考
|
||||
|
||||
### BrowserTool 类
|
||||
|
||||
#### 构造函数
|
||||
|
||||
```python
|
||||
BrowserTool(
|
||||
mode: Literal["launch", "cdp"] = "launch",
|
||||
cdp_url: str = "http://localhost:9222",
|
||||
headless: bool = False,
|
||||
chrome_path: Optional[str] = None,
|
||||
)
|
||||
```
|
||||
|
||||
参数:
|
||||
- `mode`: 启动模式,`"launch"` 直接启动 Chrome,`"cdp"` 连接已运行的 Chrome
|
||||
- `cdp_url`: CDP 连接地址(仅 mode="cdp" 时使用)
|
||||
- `headless`: 是否无头模式(建议 False 规避检测)
|
||||
- `chrome_path`: Chrome 可执行文件路径(默认使用 `/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`)
|
||||
|
||||
#### 方法
|
||||
|
||||
##### navigate(url, wait_until="networkidle") -> str
|
||||
|
||||
导航到指定 URL,返回页面快照。
|
||||
|
||||
- `url`: 目标网址
|
||||
- `wait_until`: 等待条件 (`load`, `domcontentloaded`, `networkidle`)
|
||||
|
||||
返回:页面快照文本,包含交互元素列表
|
||||
|
||||
##### snapshot(full=False) -> str
|
||||
|
||||
获取当前页面快照。
|
||||
|
||||
- `full`: 是否返回完整页面内容(默认只返回交互元素)
|
||||
|
||||
##### click(ref, wait_for_navigation=False)
|
||||
|
||||
点击元素。
|
||||
|
||||
- `ref`: 元素引用 ID,如 `@e5`
|
||||
- `wait_for_navigation`: 是否等待页面跳转
|
||||
|
||||
##### type(ref, text, clear=True)
|
||||
|
||||
在输入框填入文本。
|
||||
|
||||
- `ref`: 元素引用 ID
|
||||
- `text`: 要输入的文本
|
||||
- `clear`: 是否先清空输入框
|
||||
|
||||
##### scroll(direction="down", amount=500)
|
||||
|
||||
滚动页面。
|
||||
|
||||
- `direction`: `"up"` 或 `"down"`
|
||||
- `amount`: 滚动像素数
|
||||
|
||||
##### screenshot(path=None) -> str
|
||||
|
||||
截取页面截图。
|
||||
|
||||
- `path`: 截图保存路径(默认自动命名)
|
||||
|
||||
返回:截图文件路径
|
||||
|
||||
##### press(key)
|
||||
|
||||
按下键盘按键。
|
||||
|
||||
- `key`: 按键名称 (`Enter`, `Tab`, `Escape`, `ArrowDown`, 等)
|
||||
|
||||
##### back()
|
||||
|
||||
返回上一页。
|
||||
|
||||
##### close()
|
||||
|
||||
关闭浏览器会话。
|
||||
|
||||
##### check_detection() -> Dict
|
||||
|
||||
检查反检测效果,访问 https://bot.sannysoft.com/ 并返回检测结果。
|
||||
|
||||
返回:包含 `webdriver`, `plugins`, `languages`, `userAgent`, `chrome` 等字段的字典
|
||||
|
||||
## 页面快照格式
|
||||
|
||||
`snapshot()` 和 `navigate()` 返回的快照文本格式如下:
|
||||
|
||||
```
|
||||
URL: https://example.com
|
||||
Title: Example Domain
|
||||
|
||||
=== Interactive Elements ===
|
||||
|
||||
[@e1] <a href="https://example.com/page">Link text</a>
|
||||
[@e2] <button type="submit">Submit</button>
|
||||
[@e3] <input type="text" placeholder="Search...">
|
||||
[@e4] <textarea name="content">
|
||||
```
|
||||
|
||||
使用 `@e1`, `@e2` 等引用 ID 进行点击和输入操作。
|
||||
|
||||
## 反检测原理
|
||||
|
||||
1. **使用本地 Chrome**:而非 Playwright 自带的 headless Chromium,避免被识别为自动化浏览器
|
||||
2. **禁用 webdriver 标记**:通过 `Object.defineProperty` 将 `navigator.webdriver` 设为 `undefined`
|
||||
3. **配置启动参数**:
|
||||
- `--disable-blink-features=AutomationControlled`:禁用自动化控制特征
|
||||
- `--disable-web-security`:禁用 web 安全(可选)
|
||||
- `--window-size`:设置正常 viewport
|
||||
4. **非无头模式**:`headless=False` 让 Chrome 真实显示
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: Chrome 路径不对?
|
||||
|
||||
在创建 BrowserTool 时指定路径:
|
||||
|
||||
```python
|
||||
browser = BrowserTool(chrome_path="/path/to/chrome")
|
||||
```
|
||||
|
||||
### Q: 如何查找 Chrome 路径?
|
||||
|
||||
```bash
|
||||
# macOS
|
||||
ls /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome
|
||||
|
||||
# 或使用 mdfind
|
||||
mdfind -name "Google Chrome.app"
|
||||
```
|
||||
|
||||
### Q: CDP 模式连接失败?
|
||||
|
||||
确保 Chrome 已启动并开启调试端口:
|
||||
|
||||
```bash
|
||||
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
|
||||
--remote-debugging-port=9222
|
||||
```
|
||||
|
||||
检查端口是否监听:
|
||||
|
||||
```bash
|
||||
curl http://localhost:9222/json/version
|
||||
```
|
||||
|
||||
### Q: 还是被检测到了?
|
||||
|
||||
尝试以下方法:
|
||||
1. 确保 `headless=False`
|
||||
2. 使用 CDP 模式连接手动启动的 Chrome
|
||||
3. 添加更多延迟:`browser._page.wait_for_timeout(2000)`
|
||||
4. 使用代理或 VPN 更换 IP
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
browser-automation/
|
||||
├── SKILL.md # 本文档
|
||||
└── browser_tool.py # 核心封装
|
||||
```
|
||||
|
||||
## 依赖
|
||||
|
||||
- Python 3.8+
|
||||
- Playwright
|
||||
- Google Chrome(本地安装)
|
||||
|
||||
## 参考
|
||||
|
||||
- [Playwright Documentation](https://playwright.dev/python/)
|
||||
- [bot.sannysoft.com](https://bot.sannysoft.com/) - 浏览器自动化检测测试
|
||||
Reference in New Issue
Block a user