chrome-devtools-skill
Chrome DevTools Skill
使用 Chrome DevTools Protocol 进行网页数据获取和分析。
工作流程(AI 自动执行)
当用户使用此 skill 时,AI 应该自动完成以下所有步骤,而不是让用户手动执行:
1. 自动启动 Chrome 远程调试
AI 自动检测操作系统并启动 Chrome:
Windows:
start chrome --remote-debugging-port=9222 --user-data-dir="%TEMP%\chrome-devtools-profile" [URL]
重要提示: 使用固定的
--user-data-dir(如chrome-devtools-profile),不要每次使用不同的文件夹。这样 Chrome 会记住登录状态、Cookie 和缓存,下次启动更快。
macOS:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir="$TMPDIR/chrome-profile-stable" [URL]
Linux:
google-chrome --remote-debugging-port=9222 --user-data-dir="/tmp/chrome-profile-stable" [URL]
2. 自动启动 MCP 服务器
AI 自动启动 MCP 服务器(在后台运行):
npx -y chrome-devtools-mcp@latest --browser-url=http://127.0.0.1:9222
3. 执行用户请求的操作
使用以下 MCP 工具完成用户任务:
mcp__chrome-devtools__navigate_page- 导航到页面mcp__chrome-devtools__wait_for- 等待页面加载mcp__chrome-devtools__take_snapshot- 获取页面快照mcp__chrome-devtools__evaluate_script- 执行 JavaScript 提取数据mcp__chrome-devtools__screenshot- 截取屏幕截图mcp__chrome-devtools__list_network_requests- 列出网络请求
标准操作流程(AI 使用)
当用户要求打开/分析/抓取某个网页时,AI 按以下顺序执行:
1. 启动 Chrome(调试模式)
2. 启动 MCP 服务器
3. 导航到目标 URL
4. 等待页面加载
5. 执行用户请求的操作(截图/提取数据/监控网络等)
6. 返回结果给用户
数据提取技巧
提取列表数据:
() => {
const items = document.querySelectorAll(".item");
return Array.from(items).map((item) => ({
title: item.querySelector(".title")?.innerText,
link: item.querySelector("a")?.href,
}));
};
提取表格数据:
() => {
const rows = document.querySelectorAll("table tr");
return Array.from(rows).map((row) =>
Array.from(row.querySelectorAll("td, th")).map((cell) => cell.innerText)
);
};
常见用例
- 打开网页并截图: 启动 Chrome → 导航 → 截图 → 返回结果
- 商品信息抓取: 导航 → 滚动加载 → 提取列表
- 表单自动化: 导航 → fill_form → click → wait_for
- API 监控: 导航 → list_network_requests → get_network_request
- 性能分析: performance_start_trace → 操作 → performance_stop_trace
最佳实践
- 自动处理所有前置步骤 - 不要要求用户手动启动 Chrome 或 MCP 服务器
- 使用固定的用户数据目录 - 保持
--user-data-dir一致,避免每次都重新加载 - 先用
take_snapshot了解页面结构 - 复杂提取用
evaluate_script执行 JavaScript - 确保返回 JSON 可序列化的数据
- 处理动态内容时使用
wait_for
技术原理
Chrome DevTools Protocol (CDP) 通信方式
| 方式 | 协议 | 用途 |
|---|---|---|
| HTTP | http://127.0.0.1:9222/json/list |
获取页面列表、基本信息 |
| WebSocket | ws://127.0.0.1:9222/devtools/page/{pageId} |
实时控制页面、执行脚本 |
WebSocket 通信流程
import asyncio
import websockets
import json
async def cdp_example():
# 1. 连接到 Chrome DevTools WebSocket
ws_url = "ws://127.0.0.1:9222/devtools/page/{pageId}"
async with websockets.connect(ws_url) as ws:
# 2. 启用 Runtime 域
await ws.send(json.dumps({
"id": 1,
"method": "Runtime.enable"
}))
# 3. 执行 JavaScript
await ws.send(json.dumps({
"id": 2,
"method": "Runtime.evaluate",
"params": {
"expression": "document.title",
"returnByValue": True
}
}))
# 4. 循环接收响应,匹配 id
while True:
msg = await ws.recv()
data = json.loads(msg)
if data.get('id') == 2: # 匹配请求 id
return data['result']['result']['value']
关键注意事项
- 响应匹配: WebSocket 会收到多种消息(
consoleAPICalled、executionContextCreated等),必须通过id匹配请求和响应 - 等待页面加载: 执行操作后使用
await asyncio.sleep(2)或等待特定元素 - 编码问题: Windows 终端需要
sys.stdout.reconfigure(encoding='utf-8')来正确显示中文
实战经验与踩坑记录
问题 1: Windows 中文输出乱码
现象: 抓取的中文内容显示为乱码或抛出 UnicodeEncodeError: 'gbk' codec can't encode character
原因: Windows 终端默认使用 GBK 编码,而 Python 输出 UTF-8 中文时会冲突
解决: 在 Python 脚本开头添加编码配置:
import sys
sys.stdout.reconfigure(encoding='utf-8')
重要: 所有示例脚本(baidu_search_example.py、cdp_helper.py)都已添加此编码配置,直接运行不会产生乱码。
问题 2: HTML 字符实体转义
现象: JavaScript 代码中的 => 箭头函数在通过 JSON 传输时被转义为 =>
原因: JSON 标准会对某些字符进行 Unicode 转义
解决: 这是正常现象,不影响实际执行。如果需要在 Python 中处理,可以使用:
import codecs
decoded = codecs.decode(string, 'unicode_escape')
问题 3: 页面 ID 获取
现象: 不知道当前页面的 WebSocket URL 解决: 通过 HTTP 接口获取页面列表:
curl -s http://127.0.0.1:9222/json/list
然后提取 webSocketDebuggerUrl 字段
注意: 页面 ID 是动态生成的,每次启动 Chrome 都会变化。应该在代码中动态获取而不是硬编码:
import urllib.request
import json
def get_ws_url():
req = urllib.request.Request('http://127.0.0.1:9222/json/list')
with urllib.request.urlopen(req) as response:
pages = json.loads(response.read().decode())
return pages[0]['webSocketDebuggerUrl'] if pages else None
问题 4: Windows 等待命令跨平台兼容性问题
现象: 在 Git Bash 中使用 timeout /t 3 /nobreak 报错 invalid time interval
原因: timeout 是 Windows CMD 命令,在 Bash 中语法不兼容
解决: 使用跨平台的等待方案:
# Windows CMD
timeout /t 3 /nobreak >nul
# Git Bash / Linux
sleep 3
# 跨平台通用(Windows)
ping -n 4 127.0.0.1 > nul
问题 5: Claude Code 文件写入限制
现象: 直接使用 Write 工具创建新文件时提示 "File has not been read yet" 原因: Claude Code 要求必须先读取文件才能写入(安全机制) 解决:
- 先使用 Read 工具读取文件(如果不存在会报错,需要用 Bash 创建空文件)
- 或者使用 Bash 的
echo或cat命令直接写入 - 或者使用 Python 脚本动态生成并执行代码
问题 6: 动态内容提取不完整
现象: 提取的搜索结果中某些字段(如摘要)为空 原因:
- 页面使用了动态加载,需要滚动才能显示全部内容
- 不同网站使用不同的 class 名称
- 某些内容是异步加载的
解决:
- 使用多个选择器匹配:
const abstract = item.querySelector('.c-abstract, .abstract, [class*="abstract"]')?.innerText;
- 滚动页面加载更多内容:
window.scrollTo(0, document.body.scrollHeight);
- 增加等待时间确保异步内容加载完成
问题 7: 前台 vs 后台操作浏览器
CDP 支持两种操作模式,根据用户需求选择:
后台操作(默认):
- 通过 WebSocket 发送 JavaScript 命令直接操作 DOM
- 浏览器界面不会显示操作过程(用户看不到输入、点击等动作)
- 适合数据抓取、自动化测试等不需要可视化反馈的场景
- 代码示例:
# 直接设置输入框的值(用户看不到输入过程)
await ws.send(json.dumps({
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').value = '美女';"
}
}))
前台操作(可视化):
- 使用 CDP 的 Input 域模拟真实用户输入
- 浏览器会显示完整的操作过程(键盘输入、鼠标点击等)
- 适合演示、教学、需要用户观察操作过程的场景
- 代码示例:
# 1. 先聚焦输入框
await ws.send(json.dumps({
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').focus();"
}
}))
# 2. 模拟键盘输入(用户能看到逐字输入)
for char in "美女":
await ws.send(json.dumps({
"method": "Input.dispatchKeyEvent",
"params": {
"type": "char",
"text": char
}
}))
await asyncio.sleep(0.1) # 模拟真实打字间隔
# 3. 模拟点击搜索按钮(用户能看到点击效果)
await ws.send(json.dumps({
"method": "Input.dispatchMouseEvent",
"params": {
"type": "mousePressed",
"x": 100,
"y": 200,
"button": "left"
}
}))
选择建议:
| 场景 | 推荐模式 | 原因 |
|---|---|---|
| 数据抓取 | 后台 | 速度快,不需要可视化 |
| 自动化测试 | 后台 | 稳定可靠,不受UI影响 |
| 搜索类任务 | 后台 | 直接构造URL更简单可靠 |
| 操作演示 | 前台 | 用户能看到完整过程 |
| 教学演示 | 前台 | 便于观察和理解 |
| 表单填写 | 两者皆可 | 后台更快,前台更直观 |
搜索类任务推荐方案:
- 后台方式(推荐):直接构造搜索URL,如
https://www.baidu.com/s?wd=关键词 - 前台方式:仅当用户明确要求"可视化"、"能看到操作过程"时使用
问题 8: 搜索类任务的最佳实践
场景: 用户要求"在百度/谷歌搜索某某关键词并抓取结果"
方案对比:
| 方案 | 实现方式 | 优点 | 缺点 | 推荐度 |
|---|---|---|---|---|
| A | 后台直接访问搜索URL | 简单、快速、稳定 | 用户看不到过程 | ⭐⭐⭐⭐⭐ |
| B | 前台模拟输入点击 | 可视化、有反馈 | 复杂、慢、需处理坐标 | ⭐⭐⭐ |
推荐方案 A(后台方式):
# 直接构造搜索URL,一步到位
url = f"https://www.baidu.com/s?wd={urllib.parse.quote(keyword)}"
await client.navigate(url)
await asyncio.sleep(3) # 等待加载
results = await client.evaluate(extract_script)
何时使用方案 B(前台方式):
- 用户明确要求"可视化操作"、"让我看到过程"
- 教学演示场景
- 需要展示自动化操作过程
前台方式注意事项:
- 必须先
focus()输入框 - 打字间隔 0.1-0.15 秒最合适
- 百度搜素按钮坐标约 x:650, y:230(1920x1080分辨率)
- 需要启用 Input 域:
Input.enable
前台输入文字详细步骤(以百度搜索框为例):
# 步骤 1: 启用 Input 域(必须先启用才能发送键盘事件)
await ws.send(json.dumps({
"id": 1,
"method": "Input.enable"
}))
# 步骤 2: 聚焦输入框(关键步骤,否则键盘事件可能无效)
await ws.send(json.dumps({
"id": 2,
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').focus();", # '#kw' 是百度搜索框ID
"returnByValue": True
}
}))
await asyncio.sleep(0.5) # 等待聚焦完成
# 步骤 3: 清空输入框(可选,确保输入框为空)
await ws.send(json.dumps({
"id": 3,
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').value = '';",
"returnByValue": True
}
}))
# 步骤 4: 逐字输入文字(用户能看到逐字输入动画)
text = "hello 你好呀"
for i, char in enumerate(text):
await ws.send(json.dumps({
"id": 10 + i,
"method": "Input.dispatchKeyEvent",
"params": {
"type": "char", # 输入字符
"text": char # 要输入的字符
}
}))
await asyncio.sleep(0.15) # 打字间隔,让用户能看到动画
关键要点:
type: "char"用于输入普通字符- 必须先
focus()输入框,否则输入可能无效 - 间隔时间建议 0.1-0.2 秒,太短可能漏字,太长用户等待久
- 支持中文输入,无需额外编码处理
问题 9: 表单自动化执行顺序
正确顺序:
- 启用 Runtime → 2. 填充输入框 → 3. 点击按钮 → 4. 等待页面加载 → 5. 提取数据
示例代码(百度搜索后台方式):
# 1. 填充搜索词
await ws.send(json.dumps({
"id": 2,
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#kw').value = '搜索词';",
"returnByValue": True
}
}))
# 2. 点击搜索按钮
await ws.send(json.dumps({
"id": 3,
"method": "Runtime.evaluate",
"params": {
"expression": "document.querySelector('#su').click();",
"returnByValue": True
}
}))
# 3. 等待加载
await asyncio.sleep(3)
# 4. 提取结果
await ws.send(json.dumps({
"id": 4,
"method": "Runtime.evaluate",
"params": {
"expression": """
(() => {
const items = document.querySelectorAll('.result');
return Array.from(items).map(item => ({
title: item.querySelector('h3')?.innerText,
link: item.querySelector('a')?.href
}));
})()
""",
"returnByValue": True
}
}))
用户使用指南
如何使用此 Skill
用户可以通过以下方式触发此 skill:
- 直接说明需求 - 描述你想对网页做什么
- 使用
/chrome-devtools-skill命令 - 显式调用 skill - 提及网页操作 - 任何涉及"打开网页、抓取数据、截图"等关键词
提示词示例
以下是一些用户可以使用的提示词模板:
基础操作
打开 https://www.example.com 并截图
抓取 https://www.example.com 的页面内容
分析一下这个网页:https://github.com/xxx/xxx
数据提取
打开 https://www.jd.com,提取首页所有商品标题和价格
访问 https://www.zhihu.com/explore,获取热门问题列表
抓取 https://www.example.com 页面中的所有链接
监控和分析
打开 https://www.example.com,监控页面加载的所有 API 请求
分析 https://www.example.com 的页面性能
访问 https://www.example.com,提取页面中的所有图片地址
自动化操作
打开 https://www.example.com,在搜索框输入"关键词"并搜索
访问 https://www.example.com,点击"加载更多"按钮,抓取所有列表数据
提示词技巧
- 明确 URL - 提供完整的网页地址
- 说明目标 - 清楚描述你想获取什么数据或执行什么操作
- 指定格式 - 如果需要特定格式,可以说明(如"以表格形式返回")
- 复杂任务分步 - 对于多步骤任务,可以分步描述
示例对话
用户: 帮我打开百度,看看热搜榜有什么内容
AI: [自动启动 Chrome → 打开百度 → 提取热搜数据 → 返回结果]
用户: 抓取 https://news.ycombinator.com 的前 10 条新闻标题和链接
AI: [自动启动 Chrome → 打开 Hacker News → 提取新闻数据 → 返回表格]
用户: 分析一下淘宝首页都加载了哪些接口
AI: [自动启动 Chrome → 打开淘宝 → 监控网络请求 → 返回 API 列表]
参考资源
- 示例脚本: 见
scripts/目录baidu_search_example.py- 百度搜索完整示例cdp_helper.py- CDP 客户端封装类README.md- 快速开始指南
Chrome DevTools MCP 配置信息
如果用户询问chrome-devtools MCP怎么配置,提供以下 JSON 配置信息:
{
"mcpServers": {
"chrome-devtools": {
"command": "npx",
"args": [
"chrome-devtools-mcp@latest",
"--browser-url=http://127.0.0.1:9222"
]
}
}
}
// 测试修改 // 另一个测试修改 // 测试修改 pre-push 方案