ワンクリックで
browser-harness-auto-launch
当需要使用 browser-harness 进行浏览器自动化、网页爬取、CDP 操作、数据提取时触发。核心原则是:自己启动浏览器,不询问用户。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
当需要使用 browser-harness 进行浏览器自动化、网页爬取、CDP 操作、数据提取时触发。核心原则是:自己启动浏览器,不询问用户。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
当用户希望整理需求、明确目的、描述问题,或要求"生成文档"、"整理意图"、"明确现象"时触发。用于通过多轮对话收集和整理需求,不执行任何代码修改。
当用户说 "boot work-flow"、"初始化 work-flow"、"为这个仓库创建 work-flow skill"、"创建 <仓库名>-work-flow" 时触发。这是一个元skill:自动检测 git 仓库名 → 在项目本地创建 <repo>-work-flow skill → 仅写入项目启动方法和启动信息作为最小骨架 → 标注后续通过 /key_board_3 添加 references 增强。
清理git嵌套仓库,保持仓库隔离性,让 git add . 干净无污染。 适用于 .claude/repo/ 或其他包含克隆仓库的目录。 当用户提到"清理git"、"处理嵌套仓库"、"git隔离"、"保持干净"、 "部分跟踪"、"白名单子目录"、"忽略但保留子目录"、"gitignore 否定规则"、 "忽略 .tool/"、"工具目录不入库"时触发。
当用户要求"总结成skill"、"保存对话为skill"、"提取提示词"、"做成技能"时触发。这是元技能模板,用于指导创建其他技能,而非被创建的技能本身。
当用户要求"拆分到references"、"给skill加ref引导"、"把xx沉淀为reference"、"优化skill结构"、"重构skill"、"skill膨胀了"、"合并skill"、或要求"探索/扫描现有skill看哪些可合并"时触发。本 skill 专用于按主题把已有 skill 组织成渐进式指导文档——主 SKILL.md 承担主干主题、references/ 承担特化专项的特化指导,整个 skill 包高内聚、单文档承担一个主题;长度只是边缘参考。不创建新 skill、不改变前置 skill (key_board / key_board_2) 的职责。探索模式详见 [[场景E-合并审计]]。
阅读任意代码库目录(不限语言/框架),分析模块与代码结构,生成防腐蚀规范 SKILL.md、更新已有 skill 使其与代码库一致、或在使用 skill 后反思同步项目经验。覆盖"创建"、"同步"、"反思"三个场景。不生成孤儿文档。
| name | browser-harness-auto-launch |
| description | 当需要使用 browser-harness 进行浏览器自动化、网页爬取、CDP 操作、数据提取时触发。核心原则是:自己启动浏览器,不询问用户。 |
加载依赖的 /browser-harness 这个skill 启动浏览器
不要问用户 Chrome 是否已打开。自己去启动、自己去连接、自己去重试。
browser-harness -c 'print(page_info())'
run.py 内部会调用 ensure_daemon(),它会自动:
--remote-debugging-port=9222)你不需要、也不应该手动启动 Chrome。
Windows 下手动兜底命令(固定 user-data-dir 路径为 $env:TEMP\chrome_dev):
Start-Process "chrome" -ArgumentList "--remote-debugging-port=9222","--user-data-dir=$env:TEMP\chrome_dev"
为什么固定 user-data-dir?
- 让 CDP 端口(9222)有唯一对应的 Chrome 实例,避免和用户日常 Chrome 冲突
- 关闭调试 Chrome 时不会影响用户的书签/历史
$env:TEMP\chrome_dev是临时目录,重启系统自动清理
启动后先 sleep 3 秒等待 Chrome 就绪,再执行 browser-harness:
sleep 3 && browser-harness -c 'new_tab("https://example.com"); print(page_info())'
browser-harness -c 参数对引号和转义极度敏感。复杂脚本不要内联,先写文件再执行:
# 错误:内联多行字符串,转义地狱
browser-harness -c 'js("""...""")' # 极易失败
# 正确:写 .py 文件后执行
browser-harness -c "exec(open('extract.py').read())"
当 browser-harness 内联脚本反复因转义失败时,切换到 mcp__chrome-devtools__evaluate_script:
// 直接执行,无 shell 转义问题
() => {
const links = new Set();
document.querySelectorAll('a[href*="/video/BV"]').forEach(a => {
const href = a.getAttribute('href');
const match = href.match(/\/video\/BV[a-zA-Z0-9]+/);
if (match) links.add('https://www.bilibili.com' + match[0]);
});
return Array.from(links);
}
from agent_helpers import *
# 1. 导航
goto_url("https://example.com")
wait_for_load()
sleep(2)
# 2. 滚动加载(如需)
for i in range(5):
scroll_down(800)
sleep(1)
# 3. 提取
result = js("""
// DOM extraction logic
""")
print(result)
SPA 分页(无刷新):点击后 sleep(2) 等待 DOM 更新,再提取。
while True:
# extract current page
result = js("...")
# check next
has_next = js("...")
if not has_next: break
# click next
js("document.querySelector('.next-page').click()")
sleep(2) # wait for XHR + re-render
| 错误操作 | 实际后果 | 正确做法 |
|---|---|---|
| 问用户"Chrome 打开了吗" | 打断用户、降低效率 | 直接执行 browser-harness,ensure_daemon() 会自动处理 |
内联复杂 JS 到 browser-harness -c | 引号转义失败,SyntaxError | 写 .py 文件再 exec(open('file').read()),或改用 CDP evaluate_script |
直接拼接 href 和 origin | Bilibili 的 href 可能已带 //www.bilibili.com,导致 https://www.bilibili.com//www.bilibili.com/... | 用正则提取 path:href.match(/\/video\/BV[a-zA-Z0-9]+/),再拼接 |
| SPA 分页点击后立即提取 | 拿到的是旧页面数据 | 点击后 sleep(2) 或等待特定元素变化 |
| 假设页面一次性渲染全部内容 | 懒加载导致漏数据 | 先 scroll_down(800) 多次再提取 |
用 goto_url 替代 new_tab | 覆盖用户当前正在使用的标签页 | 首导航用 new_tab(url) |
Step 1:提取 BV 号链接
从 B站合集页 / UP主空间 / 收藏夹页面提取所有视频链接:
from agent_helpers import *
goto_url("https://space.bilibili.com/xxxx/channel/collectiondetail?sid=xxxx")
wait_for_load()
sleep(2)
# 先滚动加载全部内容
for i in range(10):
scroll_down(800)
sleep(1)
# 提取 BV 号链接
links = js("""
const set = new Set();
document.querySelectorAll('a[href*="/video/BV"]').forEach(a => {
const href = a.getAttribute('href');
const m = href.match(/\\/video\\/(BV[a-zA-Z0-9]+)/);
if (m) set.add('https://www.bilibili.com/video/' + m[1]);
});
return Array.from(set);
""")
print(links)
Step 2:保存为 txt
with open('course_videos.txt', 'w', encoding='utf-8') as f:
for url in links:
f.write(url + '\\n')
Step 3:输出规范 txt 文件
Agent 只需输出规范的 course_videos.txt,每行一个视频链接,用户自行在 TabBoard 中导入:
https://www.bilibili.com/video/BV1PS4y1A7za
https://www.bilibili.com/video/BV1hF411M7b5
https://www.bilibili.com/video/BV1J44y1o7gf
...
用户拿到 txt 后,在 TabBoard 视频进度页点击「批量导入」→ 选择课程组 → 上传文件即可。TabBoard 会自动打开每个链接检测视频元数据(标题、时长)并添加到课程组。
| 页面类型 | 提取方式 | 注意 |
|---|---|---|
| 合集页 | a[href*="/video/BV"] | 可能混有推荐视频,需按 DOM 结构过滤(如只取 .video-list 内的链接) |
| 收藏夹 | 同上 | 收藏夹可能跨页,需翻页提取 |
| UP主空间-投稿 | 同上 | 投稿视频可能非常多,按时间范围筛选后再提取 |
| 单个视频页 | a[href*="/video/BV"](推荐区) | 不推荐,推荐区混有大量无关视频 |
合集页底部或侧边栏常有「推荐视频」,需过滤:
// 只取合集列表容器内的链接(选择器因页面结构而异)
const container = document.querySelector('.video-list, .collection-list, #video-list');
const anchors = container ? container.querySelectorAll('a[href*="/video/BV"]') : document.querySelectorAll('a[href*="/video/BV"]');
B站 href 可能已带 //www.bilibili.com,直接拼接会出双域名:
// 错误
const url = 'https://www.bilibili.com' + href; // href="//www.bilibili.com/video/BV1xx" → 双域名
// 正确
const m = href.match(/\\/video\\/(BV[a-zA-Z0-9]+)/);
const url = m ? 'https://www.bilibili.com/video/' + m[1] : null;
ensure_daemon(),run.py 已内置goto_url 会覆盖用户当前标签页wait_for_load() alone<a> 标签(标题 + 缩略图)scroll_down(800) 才能加载全部视频