| name | browser-automation |
| description | 通过 Playwright CDP 连接用户本机 Chrome,提供页面感知 JSON(链接、输入框、按钮等)与类人操作(点击、填写、滚动、截图)。 业务逻辑由消费该技能的 AI 决策,脚本不做站点硬编码。用于网页调研、表单填写、可控交互抓取; 涉及发布评论、点赞、关注、私信、表单提交等写入外部系统的操作前须先向用户确认执行计划。 |
Browser Automation(通用网页交互与控制框架)
通过 Playwright CDP 连接用户本机 Chrome,提供无偏见的原始页面感知与安全的人类行为模拟执行。
设计哲学:脚本不负责理解页面,只负责"报告所见"与"安全操作"。
AI 读取感知输出(JSON),推理出目标元素的选择器,再指挥脚本执行点击、填写、滚动等动作。
依赖与环境
| 项 | 说明 |
|---|
| Node.js | 18+ |
| 包 | 在技能目录执行一次:cd <技能路径>/scripts && npm install(安装 playwright) |
| 浏览器 | 本机 Chrome / Chromium,以 --remote-debugging-port=9222 启动(见文末 §启动 Chrome) |
| Playwright 浏览器 | 不需要 npx playwright install chromium(走 CDP,不自启 headless) |
| 工作目录 | 在使用者工作区根目录执行 CLI,使 .config/ 落在项目根;若技能安装在其它路径,先 cd 到工作区根再调用 node <技能路径>/scripts/browser_ctrl.mjs |
| 状态文件 | 工作区 .config/:截图、经验索引、操作日志;Chrome Profile 在用户目录(见 §启动 Chrome) |
execute 结束后脚本仅断开 Playwright 与 CDP,不会退出用户已打开的 Chrome 进程。
脚本不做的事(也不应该做):
- ❌ 不硬编码任何网站的选择器(如
.comment-item, .reply)
- ❌ 不根据中文字符匹配按钮(如
text === '发送')
- ❌ 不内置任何业务逻辑(如"这是评论区"、"这是潜在客户")
- ❌ 不假设页面结构(如"xsec_token 在 href 里才是真实链接")
脚本做的事:
- ✅ 对页面执行中性观察:获取链接、输入框、按钮、容器、滚动位置、文本预览
- ✅ 对 AI 指定的选择器执行操作(点击、填写、滚动、新标签页打开)
- ✅ 每次操作前自动高亮目标元素并截图
- ✅ 模拟人类阅读速度与点击间隔
- ✅ 出错时自动截屏
1. 工作流程(AI 驱动)
收到任务
→ AI 决策第一步(通常是 navigate + perceive_all)
→ 脚本执行 navigate → 返回新页面 URL
→ 脚本执行 perceive_all → 返回 JSON 结构感知
→ AI 分析感知结果
→ "第 5 个链接看起来是文章封面" → 决策:highlight selector
→ "第 3 个 input 的 placeholder 是搜索…" → 决策:fill + type_js
→ "class 包含 'btn' 的第 2 个 button 面积最大" → 决策:click
→ 脚本执行动作(自动施加 human behaviour)
→ success → 继续下一步
→ error → 自动截屏 → AI 重新分析
关键:AI 主动要求 perceive_all / perceive_region / perceive_clickable 来"看"页面,而不是脚本自动推断。
1.1 执行前确认(强制)
收到涉及浏览器交互的任务后,代理必须先完成下列交互,再执行对应步骤(只读调研可默认进行,但若用户明确「仅分析、不操作」须遵守):
- 汇报计划:用简短编号列出本轮拟执行步骤(例如:① 启动/连接 Chrome ② 导航与感知 ③ 填写表单 ④ 发布评论 ⑤ 记录操作日志)。
- 逐项确认,至少覆盖:
- 是否进行写入类操作(发布/评论/点赞/关注/私信/删改内容/提交业务表单)?
- 是否批量或高频抓取/点击(可能触发平台风控)?
- 目标站点是否与用户指定一致(不得擅自换源)?
- 等待用户明确答复后再执行;用户可在过程中收紧范围(例如「只调研不发布」),代理须立即调整。
未确认前:不得执行发布、点赞、关注、私信等写入操作;不得假设用户需要完整流水线。
2. 感知动作(Percepts)
这些操作返回原始 JSON,供 AI 分析。它们不执行任何点击或填写。
2.1 perceive_all — 页面全景
返回页面中所有主要元素的元数据:
links:所有 <a> 的文本、href、面积、可见性、class
inputs:所有 input, textarea, [contenteditable] 的类型、placeholder、area、value 预览
buttons:所有 button, [role=button] 的文本、title、aria-label、area
images:图片的 src、alt、面积
scroll:当前滚动位置、页面总高
textPreview:页面正文前 800 字符(供 AI 判断当前状态)
node scripts/browser_ctrl.mjs execute --steps '[
{"action":"navigate","target":"https://example.com"},
{"action":"perceive_all"}
]'
2.2 perceive_region — 区域聚焦
当 AI 已定位到一个容器(如"第 7 个 class 包含 'list' 的 div"),可以用 perceive_region 深入查看容器内的子元素。
{"action":"perceive_region","selector":".item:nth-child(3)"}
2.3 perceive_clickable — 可交互元素清单
返回所有可能是可点击的元素(面积、可见性、文本)。
{"action":"perceive_clickable"}
3. 执行动作(Actions)
所有执行动作都会自动施加:
- 目标高亮:操作前红色/绿色/蓝色 outline 显示目标
- 平滑滚动:长距离分步滚动,20% 概率中间停留
- 点击间隔:同类型操作间隔 ≥15 秒
- 阅读模拟:
read_and_close 自动计算停留时长(200-350 WPM + 图片浏览时间)
- 错误截屏:任何异常自动保存截图
3.1 基础导航与点击
| 动作 | 参数 | 说明 |
|---|
navigate | target | 导航到 URL |
click | selector | 点击元素(先 highlight + scroll + delay) |
click_new_tab | selector | 在新标签页打开链接(保留当前页) |
scroll_to | selector, position | 平滑滚动到元素(start / center / end) |
scroll_by | pixels | 按像素滚动 |
read_and_close | min_seconds (可选) | 模拟阅读后关闭标签页 |
3.2 填写与输入
| 动作 | 参数 | 说明 |
|---|
fill | selector, value | 标准 fill,结束后触发 input/change 事件 |
type_js | selector, value | JS 级文本写入(支持 contenteditable、复杂输入框) |
使用建议:
- 标准
input / textarea:用 fill
contenteditable div / p:先用 perceive_all 确认 isContentEditable,再用 type_js
3.3 提取
| 动作 | 参数 | 说明 |
|---|
extract | container_selector, fields_json | 按 AI 提供的容器选择器和字段选择器提取结构化数据 |
前提:AI 必须先通过 perceive_region 或 perceive_clickable 确认选择器正确,再执行 extract。
4. 安全与验证
4.1 不点击未验证的元素
AI 在 perceive_all 中看到多个候选元素时,应先执行 highlight 确认目标位置,再执行 click。
正确流程:
perceive_all → AI 推理候选索引 → highlight 该选择器 → screenshot 确认
→ click → screenshot 确认状态变化
4.2 链接验证
脚本不假设哪些链接是真实的。AI 应基于 perceive_all 输出的 area + visible 判断:
area > 0 && visible == true:可能可点击
area == 0 || visible == false:潜在陷阱
4.3 异常与回退
操作失败
→ 脚本自动截屏
→ AI 收到 error message + screenshot path
→ AI 重新执行 perceive_all,判断页面是否已变
→ 调整策略后重试
4.4 提交前位置验证(防止误操作)
在执行任何数据提交动作(如:提交评论、发布回答、发送私信、填写表单)之前,必须执行截图验证。
- 截图确认上下文:填入内容后,点击发布前,先调用
screenshot 动作。
- 人工/AI 核验:AI 必须分析截图,确认当前焦点所在的区域确实是目标位置。
- 错误示例:在 A 答主的评论区填完内容,未移动光标,直接给 B 答主的评论区发送了(导致内容发重了位置)。
- 正确示例:截图显示当前页面包含 B 答主的头像或名字,且输入框位于 B 答主回答下方,确认为正确位置后,再执行提交。
- 禁止盲目提交:如果你没有看到明确的视觉证据(截图)表明你当前正处于正确的交互区域,绝对不要按下 Enter 或点击提交按钮。
4.5 防重复操作(操作幂等性检查)
严禁短时间内在同一位置重复发送相同内容。
- 检查日志:在执行写入/评论操作前,查阅
.config/ACTION_LOG.jsonl。
- 比对目标:如果日志中显示最近刚刚对当前 URL 或当前答主执行过相同类型的操作,立即停止。
- 后果:重复留言会被平台判定为机器人 spam,导致封号。
5. 人类行为模拟
| 维度 | 参数 | 说明 |
|---|
| 阅读速度 | 200–350 字/分钟(随机) | 自动按页面字数计算停留时长 |
| 点击间隔 | 同类型 ≥15 秒 | 防止被识别为机器人 |
| 平滑滚动 | 3–15 步,25–55ms/步 | 长距离分步,20% 概率中间停留 |
| 滚动后稳定 | 1.5–3 秒 | 滚动到位后再执行下一步 |
| 高亮时长 | 1.5–2 秒 | 操作前红色 outline,操作后自动移除 |
6. 经验索引
存储位置:.config/BROWSER_EXPERIENCE_INDEX.json
脚本只记录中性结构信息(如该域名有多少 links/inputs/buttons、viewport 尺寸),不记录业务含义。
| 命令 | 示例 |
|---|
save_experience | {"action":"save_experience","domain":"example.com"} |
get-experience CLI | node scripts/browser_ctrl.mjs get-experience --domain example.com |
7. 操作日志(Action Log)
所有数据交互动作必须记录到操作日志中,用于审计、复盘、问题排查和行为追踪。
存储位置:.config/ACTION_LOG.jsonl(JSON Lines 格式,每行一条独立 JSON 记录)
7.1 记录时机
以下动作必须在完成后追加 log_action 步骤(或单独调用 view-log 前写入):
| 动作类型 | 说明 |
|---|
| 发布内容 | 回答问题、发表文章、发表评论、发帖 |
| 点赞/收藏 | 点赞回答、收藏问题、点赞文章 |
| 关注/取关 | 关注用户、关注话题、关注问题 |
| 填写表单 | 提交任何表单(登录除外,敏感信息不记具体内容) |
| 发送消息 | 私信、评论回复 |
| 删除/编辑 | 删除已有内容、编辑已有内容 |
| 导航访问 | 首次访问某域名的关键页面(可选,默认不记每次导航) |
7.2 日志格式
每条记录为单行 JSON,包含以下字段:
{"timestamp":"2026-05-09T01:37:25+08:00","domain":"example.com","action":"publish_answer","page_url":"https://www.example.com/question/123","detail":"在问题「示例问题标题」下发布回答","result":"success","screenshot":".config/browser-screenshots/20260509_013725_publish_answer.png"}
| 字段 | 类型 | 必填 | 说明 |
|---|
timestamp | string | ✅ | ISO 8601 格式,精确到秒,含时区 |
domain | string | ✅ | 操作所在域名 |
action | string | ✅ | 动作类型:publish_answer、publish_comment、publish_article、like、follow、unfollow、bookmark、submit_form、send_message、delete、edit |
page_url | string | ✅ | 操作所在页面完整 URL |
detail | string | ✅ | 动作简要描述(中文,说明"在什么地方做了什么") |
result | string | ✅ | success 或 failed |
screenshot | string | ❌ | 操作后截图路径(如有) |
content_preview | string | ❌ | 发布内容的前 50 字(仅发布类动作) |
7.3 CLI 命令
| 命令 | 说明 | 示例 |
|---|
log_action | 写入类动作完成后由代理调用(action_type 为日志字段名,勿与步骤的 action 混淆) | {"action":"log_action","domain":"example.com","action_type":"publish_answer","page_url":"...","detail":"...","result":"success"} |
view-log | 查看操作日志 | node scripts/browser_ctrl.mjs view-log [--domain example.com] [--date 2026-05-09] [--limit 20] |
7.4 使用规范
- 每次完成数据交互后立即记录,不要批量补记
- 失败也要记录,
result 设为 failed,便于排查
- 敏感信息不记:登录密码、token、cookie 等不写入 detail 或 content_preview
- 截图关联:发布类、表单提交类动作应附带
screenshot 字段
- 定期清理:超过 90 天的日志可归档,避免文件过大
8. 使用示例
示例 1:首次访问陌生网站(标准探索流)
在工作区根目录执行(将 SKILL_DIR 换成本地技能安装路径):
node SKILL_DIR/scripts/browser_ctrl.mjs execute --steps '[
{"action":"navigate","target":"https://example.com"},
{"action":"perceive_all"},
{"action":"screenshot","description":"initial_percept"}
]'
AI 分析 perceive_all 输出后,决定下一步:
{"action":"highlight","selector":"a:nth-of-type(5)","color":"#ff0000"}
{"action":"click_new_tab","selector":"a:nth-of-type(5)"}
{"action":"perceive_all"}
示例 2:填写表单并提交
{"action":"fill","selector":"input[name='email']","value":"user@example.com"}
{"action":"fill","selector":"input[name='password']","value":"secret"}
{"action":"click","selector":"button[type='submit']"}
示例 3:内容阅读后关闭
{"action":"click_new_tab","selector":".article-title"}
{"action":"read_and_close","min_seconds":12}
示例 4:高级—滚动加载并提取
{"action":"scroll_by","pixels":800}
{"action":"perceive_all"}
{"action":"extract","container_selector":".feed-item","fields_json":'{"title":"h3","author":".author-name"}'}
9. 强制规范
与目标站点的交互(需登录态、JS 渲染、表单、发布)须通过本脚本在本机 Chrome 中完成;默认不得用 curl、wget、requests 等直接请求同一站点的页面或 API 以替代浏览器操作。
例外(须用户明确要求或任务本身与浏览器无关):下载已公开的静态文件、调用与站点无关的第三方 API、本地文件处理等。
原因:
- 行为一致性:与类人节奏、截图审计一致
- SPA 兼容:现代网站大量使用 JS 渲染
- Cookie/Session:浏览器自动管理登录态
- 可审计性:截图 + 日志完整记录每一步
9.1 前置条件检查
执行用户任务前,必须先检查前置条件,不可自行假设或跳过:
- 检查目标网站是否需要登录:通过
navigate + perceive_all 判断页面状态
- 若发现需要登录:立即停止后续动作,截图并提醒用户手动登录
- 不要主动替换数据源:用户指定知乎就搜知乎,指定 Google 就搜 Google,不得自行切换
- 不要自行构造替代方案:除非用户明确要求,不要在某个路径走不通时自作主张换方法
正确流程:
收到任务
→ 明确任务目标网站
→ 导航到目标网站
→ 感知页面状态
→ 判断是否需要登录或其他前置条件
→ 若需要:停下来提醒用户,等待确认后再继续
→ 若不需要:继续执行任务
9.2 登录提醒模板
当检测到需要登录时,应向用户发送类似如下提醒:
⚠️ 目标网站需要登录才能继续操作。
请手动完成登录后,回复「已登录」,我将继续执行任务。
等待用户明确确认后再继续。
10. 能力边界(不做什么)
- 不替代人工完成登录验证码、2FA 等强人机验证
- 不绕过付费墙或访问需合法权限的内容
- 不进行高频大规模采集
- 不修改浏览器内核或注入第三方插件
- 不在脚本中硬编码任何业务规则
11. 文件结构
| 文件 | 说明 |
|---|
scripts/browser_ctrl.mjs | 主实现:Playwright CDP 控制(Node,v4) |
scripts/package.json | Node 依赖(playwright) |
references/anti-detection.md | 反检测与类人节奏原理(CDP 与自启浏览器场景分开说明) |
references/experience-index-example.json | 经验索引格式示例 |
references/human-like-comment-style.md | 可选:仅当用户要求拟人化社区评论/回复文风时阅读 |
.config/ACTION_LOG.jsonl | 操作日志(log_action / 工作区根目录,自动生成) |
.config/BROWSER_EXPERIENCE_INDEX.json | 经验索引(save_experience,自动生成) |
启动 Chrome(一次性)
Chrome 用户数据目录放在本机(与项目 .config/ 分离),便于保留登录态:
PROFILE_DIR="$HOME/.config/skills/browser-automation/chrome-profile"
mkdir -p "$PROFILE_DIR"
DEBUG_PORT=9222
macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port="$DEBUG_PORT" --no-first-run --user-data-dir="$PROFILE_DIR"
Linux(可执行路径因发行版而异)
google-chrome --remote-debugging-port="$DEBUG_PORT" --no-first-run --user-data-dir="$PROFILE_DIR"
Windows(PowerShell)
$PROFILE_DIR = "$env:USERPROFILE\.config\skills\browser-automation\chrome-profile"
& "C:\Program Files\Google\Chrome\Application\chrome.exe" `
--remote-debugging-port=9222 --no-first-run --user-data-dir="$PROFILE_DIR"
确保只启动一次,脚本通过 CDP 复用该实例;execute 不会关闭此 Chrome 窗口。
截图说明(CDP)
部分 Chrome + CDP 环境下 screenshot 可能在「等待字体」阶段超时(约 8s 后报错,不阻塞后续步骤)。感知类动作(perceive_*)不受影响;若截图失败,可依赖 perceive_all 与 highlight 继续操作。