核心用法 / Core Usage
交互操作
读到页面之后,就该动手了。这一页覆盖驱动真实浏览器的全部交互动词——
点击、输入、勾选、下拉、上传、滚动、拖拽。
大多数命令的第一个参数是 snapshot -i 拿到的
@ref(例如 @e42);先定位元素,
再用这里的命令操作它。
点击与指针
最常用的一组动词,都作用在一个 @ref 上。click 会自动把元素滚动进视口,
若坐标点击被遮挡,会回退到 DOM 的 .click()。
$ chrome-use click @e1 # 点击
$ chrome-use click @e1 --new-tab # 在新标签页打开链接,而不是当前页导航
$ chrome-use dblclick @e1 # 双击
$ chrome-use hover @e1 # 悬停
$ chrome-use focus @e1 # 聚焦(键盘输入前常用)
<li> 在输入框失焦时就关掉了。
换成 DOM 派发的点击再试一次:
AGENT_BROWSER_CLICK_MODE=dom chrome-use click @e1,
或直接用 eval 在页面里选中那一项。
click <input> 之后 press Meta+a 落在这个输入框上,
不再落到上一个焦点字段。普通 <li> 没有可聚焦目标,上面的 autocomplete 技巧依然成立。
输入文本
fill 先清空再输入,type 在现有内容后追加。默认走
insertText(快),但很多带联想的字段只对真实按键有反应——这时加
--key-events。
$ chrome-use fill @e2 "hello" # 清空后输入
$ chrome-use type @e2 " world" # 不清空,直接追加
$ chrome-use type @e2 "hello" --clear # type 也能先清空字段再输入
$ chrome-use type @e2 "hello" --delay 80 # 每个按键之间间隔 80ms
# 真实按键(非 insertText)——用于只认按键事件的联想/组合框,
# 例如输入邮编后自动补全市区(Google Places 一类)
$ chrome-use type @e5 "201-0001" --key-events
# 真实按键并回车提交候选(--enter 隐含 --key-events)——
# 用于异步联想 / 标签控件,例如掘金「添加标签」
$ chrome-use type @e6 "ChatGPT" --enter
--enter 一步到位。
如果你更想从候选列表里挑一个,先 type … --key-events 触发下拉,
再 snapshot -i 找到候选并 click @ref。
--clear 让 type 也能先清空字段(不用再切回 fill);
--delay <ms> 在按键之间插入固定间隔,模拟更慢、更真实的打字节奏。
两者都是各自独立的 flag,不会污染实际打进去的文本。
type 打完会回读字段:如果里面没有刚输入的文本,会打印 ⚠ 警告,引用写入的内容和字段当前的值
(退出码仍为 0,JSON 多出 readBack)。fill 校验失败时的报错同样引用两边的值,
例如 read back "" after writing "狛江市";若非 ASCII 字符全部消失而 ASCII 仍在,
会指出页面过滤了非拉丁输入(仅限拉丁 / 带掩码的字段),重打一遍没有用。正常字段上两者都能正确输入中日韩文,
这些提示针对的是会改写输入的页面。
字段内部编辑与带格式粘贴
fill 是整体替换,type 是追加。改一段写好的文字里的某一处、
或者只把光标放到某个位置继续写,这两个都做不到 —— 这是 select-text 的活。
$ chrome-use select-text @e3 "确认" --prefix "请" # 选中「确认」,不含「请」
$ chrome-use select-text @e3 "Hi Sam," --cursor-after # 只放光标
$ chrome-use type @e3 " 顺便说一句:" # 从光标处继续输入
富文本编辑器里,敲字和粘贴的结果不一样:type "<b>粗体</b>"
得到的是这几个字符,paste --format html 得到的才是粗体。换行同理 ——
type 的换行会变成 Enter(在多数编辑器里等于提交或另起一块),paste 不会。
$ chrome-use paste $'第一行\n第二行' --selector "#notes" # $'...' 才是真换行
$ chrome-use paste "<b>粗体</b>文字" --format html --selector "#editor"
$ chrome-use paste "# 标题" --format md # Markdown 源码按纯文本插入
ClipboardEvent,不调用 navigator.clipboard,也不模拟 Ctrl+V。
这种事件是 untrusted 的、没有默认行为:监听 paste 的编辑器从自己的 handler 拿到内容,
不监听的则走一次真实插入 —— 回复里会写明走的是哪条。两条都没生效时它报错,不会打 ✓。
键盘
press 在当前焦点上按一个键(按下+抬起),也支持组合键。
keydown/keyup 把按下和抬起拆开,成对使用可以实现「按住」。
$ chrome-use press Enter # 在当前焦点按一个键,输出会报告落点
# ✓ Pressed Enter → textarea[name="q"]
$ chrome-use press Enter --selector @e2 # 先聚焦目标再按(别名 --on)——每次调用
# 都是独立进程,别假设焦点还在原处
$ chrome-use press Control+a # 组合键
$ chrome-use keydown d # 按住某键不放(不自动抬起)
$ chrome-use keyup d # 抬起——成对用来「按住移动」
# 游戏里:keydown d; sleep; keyup d
press 会探测从焦点元素、祖先到 document / window 有没有 keydown/keyup/keypress 监听器。
一个都没有时仍退出 0,但会打印 ⚠ 警告说明页面无法响应该键,建议直接 click 目标选项;
JSON 多出 keyListeners: <count>。组合键(Ctrl/Meta+键)、Tab、Backspace、可打印字符和原生默认行为不探测。
press d --hold 800 更好——按住时长在守护进程里计时,
比 keydown + shell sleep + keyup 每轮少 ~250ms 抖动。详见
Canvas 与游戏。
勾选、选择与下拉
复选框用 check/uncheck。下拉:原生 <select> 和
自定义组合框(react-select / ARIA 等)都可以用 select——
自 v1.5.72 起,select 遇到非原生控件会自动走 portal-aware 逻辑(开控件→等选项→按可见文本点);
pick 是同一能力的显式别名。
原生下拉使用平台自带的 value/selected setter,并同时触发 input 与
change,因此 React/Vue 受控表单也会提交新状态。
$ chrome-use check @e3 # 勾选复选框
$ chrome-use uncheck @e3 # 取消勾选
$ chrome-use select @e4 "Pageview" # 原生 <select> 或自定义组合框(v1.5.72+)
$ chrome-use select @e4 "a" "b" # 多选
# 任意组合框:打开它、等菜单出现(含 portal 渲染)、按可见文本匹配、
# 触发正确事件;若选项始终不出现会「报错」(不会静默无操作)
$ chrome-use pick @e4 --option "Europe"
select 对自定义下拉会「返回 ✓ 却没变化」(静默假成功)——现已修复:
非原生控件走 portal-aware 逻辑,选项始终不出现时明确报错并列出可见选项,不再静默。
fill 同样加固:通过 Monaco 的全局或 AMD model API 做一次原子的
setValue,并在返回成功前精确回读 model。若应用隐藏了该 API,则执行一次可信的编辑器
paste,通过编辑器自己的 copy 处理器精确回读,并在结束后恢复浏览器剪贴板;
操作无法校验或内容不一致时会明确报错。@ref 落在包裹元素上的受控输入仍会自动下钻到内部 editable。
eval。
请使用原生 select 与 fill 命令,以免要求页面开放
unsafe-eval。
点击之外的动作
有些控件不止能点:折叠块要展开、菜单按钮要弹出、数字框和滑块要按范围步进。
actions 告诉你这个元素此刻支持哪些,
do 只执行其中之一。
$ chrome-use actions @e15
@e15 DisclosureTriangle "Disclosure summary"
expand
$ chrome-use do @e15 expand
✓ expand on @e15
now: collapse
动作集是实时读的,不是从快照里带出来的 ——
它是状态而不是身份:你截图时收着的折叠块现在可能已经开了,
这时候再给它 expand 就是让你做反。
集合之外的动作会被拒绝并附上支持列表,而不是勉强做点相近的事。 执行完会再报一次动作集,所以一个没动的控件不会读起来像成功。
expand / collapse(折叠块)、showMenu(会弹出的控件)、
increment / decrement(有取值范围的控件)、
toggle(可按下的控件)。都由元素的无障碍属性推导,
disabled 的元素不提供任何动作。
上传文件
upload 给文件 <input> 或拖拽/粘贴式的编辑器(如 X 的输入框)投喂文件。
它在扩展中继模式下也能工作。
React dropzone 消费文件后立即清空或替换隐藏 input 时,命令会成功并给出提示,不再误报页面拒绝了上传。
$ chrome-use upload @e5 file1.pdf # 上传文件
chrome.debugger 禁止 setFileInputFiles,所以文件字节会被流式送进页面、
在页面里重建成一个 File(按 native-messaging 的 1 MiB 上限分块传输)。
因此文件 <input> 和 drop/paste 编辑器都能收到。
滚动
scroll 按方向滚动页面;scrollintoview 把某个元素滚进视口。
对跨源 iframe(支付 / 结算 / KYC 组件)里的内容,普通页面滚动够不着,用
--at x,y 在像素点上滚滚轮,或 --frame n 指定帧。
$ chrome-use scroll down 500 # 滚动页面(up/down/left/right)
$ chrome-use scroll down 700 --at 640,400 # 在某像素点滚滚轮——能滚到普通页面
# 滚不到的跨源 iframe(Stripe/结算/KYC)
$ chrome-use scroll down 700 --frame 2 # 滚 `chrome-use frames` 里的第 2 帧
$ chrome-use scrollintoview @e1 # 把元素滚进视口
拖拽与滑块验证码
drag 既能在两个 ref 之间拖放,也能把一个手柄按像素偏移拖动(滑块 / canvas)。
对无人值守登录常见的网易易盾滑块验证码,用 solve-slider 自动过。
$ chrome-use drag @e1 @e2 # 拖放
$ chrome-use drag @e1 60 # 把手柄拖 +60px(滑块/canvas);`+60,-3` 表示 dx,dy
$ chrome-use solve-slider # 自动解页面上的网易易盾滑块验证码
$ chrome-use solve-slider 5 # ……最多重试 5 次(每次失败会刷新拼图)
AGENT_BROWSER_HUMANIZE 影响。
下载
ab-connect 0.5.13 及以上版本会通过 Chrome downloads API 下载
HTTP(S) 链接。chrome-use 会先解析链接的 href,包括
snapshot -i 中能看到的动态 anchor,从而避免跨源
download 链接把当前标签页导航到媒体 URL。
$ chrome-use download @e2 ./video.mp4
$ chrome-use download-url https://example.com/report.pdf ./report.pdf
$ chrome-use downloads --limit 10 --json
$ chrome-use downloads --clear
download-url 省略目标路径时保留 Chrome 的默认下载位置。
downloads --clear 只清除历史,不会删除文件。
跨源 iframe:始终按 ref 操作
内嵌的支付 / 结算 / KYC 组件(Google Payments、Stripe 等)是跨进程的 out-of-process iframe。
用 ref 驱动它们,永远不要靠截图。
snapshot -i 会穿透这些 iframe,按 @ref 列出里面的元素(含输入框的值);
get text --all-frames 读它们的文本。拿到 ref 后照常操作即可。
# snapshot -i 列出跨源 iframe 内的元素,然后:
$ chrome-use click @e
$ chrome-use type @e "…"
$ chrome-use hover @e
$ chrome-use dblclick @e
$ chrome-use drag @a @b
# 帧内的邮编/联想框——用真实按键:
$ chrome-use type @e "201-0001" --key-events
Iframe ref 执行 focus / press,命中的是父文档里的
容器元素,按键会落到父页面而不是帧内的输入框。
现在这两个命令会返回一条指明帧边界的警告,而不是在错误目标上打一个干净的 ✓。
请从帧内部操作:先用 chrome-use frames 列出所有帧,再
chrome-use frame <id> 并操作帧内部的 ref,或者用
chrome-use eval --frame <id> "…"。
scroll down N --at x,y(帧上的一个像素点)或 --frame n。
find/选择器匹配的是页面 DOM(querySelectorAll),所以对这两类元素会报
「Element not found」——即便 snapshot -i 能列出它们(它走 CDP 可访问性树,能穿透两者)、
get text 能读到。这时请用快照里的 @ref 定位,而不是 find;
box @ref 可给出坐标兜底。另外,先核对准确的标签文案再断定它「不存在」:
LinkedIn 的「Save」按钮实际标注为 收藏 而非 保存,
snapshot -i 一直显示着 button "收藏" [ref=eN],直接 click @eN 即可。
接下来
交互只是核心循环的一环,搭配这几页一起看: