name: chrome-devtools description: 使用Puppeteer CLI脚本进行浏览器自动化、调试和性能分析。用于自动化浏览器、截图、分析性能、监控网络流量、Web爬取、表单自动化和JavaScript调试。 license: Apache-2.0 version: 1.1.0
Chrome开发者工具代理技能
通过Puppeteer脚本进行浏览器自动化,支持持久会话。所有脚本输出JSON。
技能位置
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
# 检测技能位置
SKILL_DIR=""
if [ -d ".claude/skills/chrome-devtools/scripts" ]; then
SKILL_DIR=".claude/skills/chrome-devtools/scripts"
elif [ -d "$HOME/.claude/skills/chrome-devtools/scripts" ]; then
SKILL_DIR="$HOME/.claude/skills/chrome-devtools/scripts"
fi
cd "$SKILL_DIR"
选择方法
| 场景 | 方法 |
|---|---|
| 开源可用的网站 | 首先阅读源代码,直接编写选择器 |
| 未知布局 | 使用aria-snapshot.js进行语义发现 |
| 视觉检查 | 截图以验证渲染 |
| 调试问题 | 收集控制台日志,使用会话存储进行分析 |
| 可访问性审核 | 使用ARIA快照进行语义结构分析 |
ARIA快照(元素发现)
当页面结构未知时,使用aria-snapshot.js获取YAML格式的可访问性树,包含语义角色、可访问名称、状态和稳定的元素引用。
获取ARIA快照
# 生成ARIA快照并输出到stdout
node aria-snapshot.js --url https://example.com
# 保存到快照目录中的文件
node aria-snapshot.js --url https://example.com --output ./.claude/chrome-devtools/snapshots/page.yaml
示例YAML输出
- banner:
- link "Hacker News" [ref=e1]
/url: https://news.ycombinator.com
- navigation:
- link "new" [ref=e2]
- link "past" [ref=e3]
- link "comments" [ref=e4]
- main:
- list:
- listitem:
- link "Show HN: My new project" [ref=e8]
- text: "128 points by user 3 hours ago"
- contentinfo:
- textbox [ref=e10]
/placeholder: "Search"
解释ARIA表示法
| 表示法 | 含义 |
|---|---|
[ref=eN] |
交互元素的稳定标识符 |
[checked] |
复选框/单选按钮被选中 |
[disabled] |
元素处于非活动状态 |
[expanded] |
手风琴/下拉菜单已打开 |
[level=N] |
标题层级(1-6) |
/url: |
链接目标 |
/placeholder: |
输入占位符文本 |
/value: |
当前输入值 |
通过引用交互
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
使用select-ref.js通过引用与元素交互:
# 点击引用为e5的元素
node select-ref.js --ref e5 --action click
# 填写引用为e10的输入框
node select-ref.js --ref e10 --action fill --value "search query"
# 获取文本内容
node select-ref.js --ref e8 --action text
# 截图特定元素
node select-ref.js --ref e1 --action screenshot --output ./logo.png
# 聚焦元素
node select-ref.js --ref e10 --action focus
# 悬停在元素上
node select-ref.js --ref e5 --action hover
存储快照
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
将快照存储在<project>/.claude/chrome-devtools/snapshots/进行分析:
# 创建快照目录
mkdir -p .claude/chrome-devtools/snapshots
# 捕获并存储,带时间戳
SESSION="$(date +%Y%m%d-%H%M%S)"
node aria-snapshot.js --url https://example.com --output .claude/chrome-devtools/snapshots/$SESSION.yaml
工作流程:未知页面结构
-
获取快照以发现元素:
node aria-snapshot.js --url https://example.com -
从YAML输出中识别目标(例如,按钮的
[ref=e5]) -
通过引用交互:
node select-ref.js --ref e5 --action click -
通过截图或新快照验证结果:
node screenshot.js --output ./result.png
本地HTML文件
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
重要:切勿通过file://协议浏览本地HTML文件。始终通过本地服务器服务:
原因:file://协议阻止了许多浏览器功能(CORS、ES模块、fetch API、服务工作者)。本地服务器确保正确的HTTP行为。
# 选项1: npx serve(推荐)
npx serve ./dist -p 3000 &
node navigate.js --url http://localhost:3000
# 选项2: Python http.server
python -m http.server 3000 --directory ./dist &
node navigate.js --url http://localhost:3000
注意:当端口3000繁忙时,使用lsof -i :3000查找可用端口并使用其他端口。
快速开始
# 安装依赖
cd .claude/skills/chrome-devtools/scripts
npm install # 安装puppeteer、sharp、debug、yargs
# 测试(浏览器保持运行以重用会话)
node navigate.js --url https://example.com
# 输出: {"success": true, "url": "...", "title": "..."}
仅限Linux/WSL:首先运行./install-deps.sh安装Chrome系统库。
环境配置
- 检测当前操作系统,仅在Linux、WSL或CI环境中以无头模式启动浏览器。
- 对于macOS/Windows上的本地开发,浏览器以有头模式运行,便于调试。
- 并行运行多个脚本/会话以模拟真实用户交互。
- 并行运行多个脚本/会话以模拟不同设备类型(移动、平板、桌面)。
- 技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
会话持久性
浏览器状态通过WebSocket端点文件(.browser-session.json)在脚本执行之间持久化。
默认行为:脚本断开连接但保持浏览器运行以重用会话。
# 第一个脚本:启动浏览器、导航、断开连接(浏览器保持运行)
node navigate.js --url https://example.com/login
# 后续脚本:连接到现有浏览器,重用页面状态
node fill.js --selector "#email" --value "user@example.com"
node fill.js --selector "#password" --value "secret"
node click.js --selector "button[type=submit]"
# 完成时关闭浏览器
node navigate.js --url about:blank --close true
会话管理:
--close true:关闭浏览器并清除会话- 默认(无标志):保持浏览器运行以供下一个脚本使用
可用脚本
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
所有脚本位于.claude/skills/chrome-devtools/scripts/:
| 脚本 | 目的 |
|---|---|
navigate.js |
导航到URL |
screenshot.js |
捕获截图(通过Sharp自动压缩大于5MB) |
click.js |
点击元素 |
fill.js |
填写表单字段 |
evaluate.js |
在页面上下文中执行JS |
snapshot.js |
提取交互元素(JSON格式) |
aria-snapshot.js |
获取ARIA可访问性树(YAML格式带引用) |
select-ref.js |
通过ARIA快照中的引用与元素交互 |
console.js |
监控控制台消息/错误 |
network.js |
跟踪HTTP请求/响应 |
performance.js |
测量核心Web指标 |
工作流程循环
- 执行专注于单个任务的脚本
- 观察JSON输出
- 评估完成状态
- 决定下一步操作
- 重复直到完成
编写自定义测试脚本
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
对于复杂自动化,将脚本写入<project>/.claude/chrome-devtools/tmp/:
# 为测试脚本创建临时目录
mkdir -p $SKILL_DIR/.claude/chrome-devtools/tmp
# 编写测试脚本
cat > $SKILL_DIR/.claude/chrome-devtools/tmp/login-test.js << 'EOF'
import { getBrowser, getPage, disconnectBrowser, outputJSON } from '../scripts/lib/browser.js';
async function loginTest() {
const browser = await getBrowser();
const page = await getPage(browser);
await page.goto('https://example.com/login');
await page.type('#email', 'user@example.com');
await page.type('#password', 'secret');
await page.click('button[type=submit]');
await page.waitForNavigation();
outputJSON({
success: true,
url: page.url(),
title: await page.title()
});
await disconnectBrowser();
}
loginTest();
EOF
# 运行测试
node $SKILL_DIR/.claude/chrome-devtools/tmp/login-test.js
自定义脚本的关键原则:
- 单一目的:一个脚本,一个任务
- 始终在末尾调用
disconnectBrowser()(保持浏览器运行) - 仅在完全结束会话时使用
closeBrowser() - 输出JSON以便解析
- 仅在
page.evaluate()回调中使用纯JavaScript
截图
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
将截图存储在<project>/.claude/chrome-devtools/screenshots/进行分析:
# 基本截图
node screenshot.js --url https://example.com --output ./.claude/chrome-devtools/screenshots/page.png
# 完整页面
node screenshot.js --url https://example.com --output ./.claude/chrome-devtools/screenshots/page.png --full-page true
# 特定元素
node screenshot.js --url https://example.com --selector ".main-content" --output ./.claude/chrome-devtools/screenshots/element.png
自动压缩(Sharp)
大于5MB的截图使用Sharp自动压缩(比ImageMagick快4-5倍):
# 默认:如果大于5MB则压缩
node screenshot.js --url https://example.com --output ./.claude/chrome-devtools/screenshots/page.png
# 自定义阈值(3MB)
node screenshot.js --url https://example.com --output ./.claude/chrome-devtools/screenshots/page.png --max-size 3
# 禁用压缩
node screenshot.js --url https://example.com --output ./.claude/chrome-devtools/screenshots/page.png --no-compress
将截图存储在<project>/.claude/chrome-devtools/screenshots/进行分析。
控制台日志收集与分析
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
捕获日志
# 捕获所有日志10秒
node console.js --url https://example.com --duration 10000
# 按类型过滤
node console.js --url https://example.com --types error,warn --duration 5000
会话存储模式
将日志存储在<project>/.claude/chrome-devtools/logs/<session>/进行分析:
# 创建会话目录
SESSION="$(date +%Y%m%d-%H%M%S)"
mkdir -p .claude/chrome-devtools/logs/$SESSION
# 捕获并存储
node console.js --url https://example.com --duration 10000 > .claude/chrome-devtools/logs/$SESSION/console.json
node network.js --url https://example.com > .claude/chrome-devtools/logs/$SESSION/network.json
# 查看错误
jq '.messages[] | select(.type=="error")' .claude/chrome-devtools/logs/$SESSION/console.json
根本原因分析
# 1. 检查JavaScript错误
node console.js --url https://example.com --types error,pageerror --duration 5000 | jq '.messages'
# 2. 与网络故障关联
node network.js --url https://example.com | jq '.requests[] | select(.response.status >= 400)'
# 3. 检查特定错误堆栈跟踪
node console.js --url https://example.com --types error --duration 5000 | jq '.messages[].stack'
查找元素
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
在交互前使用snapshot.js发现选择器:
# 获取所有交互元素
node snapshot.js --url https://example.com | jq '.elements[] | {tagName, text, selector}'
# 查找按钮
node snapshot.js --url https://example.com | jq '.elements[] | select(.tagName=="button")'
# 按文本内容查找
node snapshot.js --url https://example.com | jq '.elements[] | select(.text | contains("Submit"))'
错误恢复
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。 如果脚本失败:
# 1. 捕获当前状态(无需导航以保持状态)
node screenshot.js --output ./.claude/skills/chrome-devtools/screenshots/debug.png
# 2. 获取控制台错误
node console.js --url about:blank --types error --duration 1000
# 3. 发现正确的选择器
node snapshot.js | jq '.elements[] | select(.text | contains("Submit"))'
# 4. 如果CSS失败,尝试XPath
node click.js --selector "//button[contains(text(),'Submit')]"
常见模式
Web爬取
node evaluate.js --url https://example.com --script "
Array.from(document.querySelectorAll('.item')).map(el => ({
title: el.querySelector('h2')?.textContent,
link: el.querySelector('a')?.href
}))
" | jq '.result'
表单自动化
node navigate.js --url https://example.com/form
node fill.js --selector "#search" --value "query"
node click.js --selector "button[type=submit]"
性能测试
node performance.js --url https://example.com | jq '.vitals'
脚本选项
所有脚本支持:
--headless false- 显示浏览器窗口--close true- 完全关闭浏览器(默认:保持运行)--timeout 30000- 设置超时(毫秒)--wait-until networkidle2- 等待策略 技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
故障排除
技能可以存在于项目范围或用户范围。优先级:项目范围 > 用户范围。
| 错误 | 解决方案 |
|---|---|
Cannot find package 'puppeteer' |
在脚本目录中运行npm install |
libnss3.so missing(Linux) |
运行./install-deps.sh |
| 元素未找到 | 使用snapshot.js查找正确的选择器 |
| 脚本挂起 | 使用--timeout 60000或--wait-until load |
| 截图大于5MB | 自动压缩;使用--max-size 3降低阈值 |
| 会话过期 | 删除.browser-session.json并重试 |
截图分析:图像缺失
如果图像未出现在截图中,它们可能正在等待动画触发:
-
滚动触发动画:首先将元素滚动到视图中
node evaluate.js --script "document.querySelector('.lazy-image').scrollIntoView()" # 等待动画 node evaluate.js --script "await new Promise(r => setTimeout(r, 1000))" node screenshot.js --output ./result.png -
顺序动画队列:等待更长时间并重试
# 第一次尝试 node screenshot.js --url http://localhost:3000 --output ./attempt1.png # 等待动画完成 node evaluate.js --script "await new Promise(r => setTimeout(r, 2000))" # 重试截图 node screenshot.js --output ./attempt2.png -
交叉观察器动画:通过滚动页面触发
node evaluate.js --script "window.scrollTo(0, document.body.scrollHeight)" node evaluate.js --script "await new Promise(r => setTimeout(r, 1500))" node evaluate.js --script "window.scrollTo(0, 0)" node screenshot.js --output ./full-loaded.png --full-page true
参考文档
./references/cdp-domains.md- Chrome开发者工具协议域./references/puppeteer-reference.md- Puppeteer API模式./references/performance-guide.md- 核心Web指标优化./scripts/README.md- 详细脚本选项