千问浏览器原生 CDP 驱动
用原生 Chrome DevTools Protocol 驱动千问浏览器(qianwen.exe),复用真实登录态做办公自动化。当用户要让"千问浏览器"自动打开网页、填表、点击、抓取内容、截图,或提到 xbrowser/agent-browser 驱动千问失败时,使用本技能。
SKILL.md
千问浏览器原生 CDP 驱动
为什么不用 xbrowser / agent-browser
xbrowser(底层 agent-browser)驱动不了千问。实测 agent-browser --cdp <port> 连千问(真实或干净 profile 都试过)后,驱动已存在的页面 target 会静默/挂死(空 profile 跑 2m35s 零输出,最终报 Auto-launch failed ...:9407)。xb 的 run.cjs 对本地浏览器一律传 --cdp,所以 xb run --browser qianwen 彻底走不通,不要浪费时间在这条路上。
根因 & 解法(已验证)
- 千问对「外部 CDP 连接」操作已存在的页面 target(通义千问桌面页、AI插件页等)一律静默。
- 但用 browser 级 WebSocket →
Target.createTarget自己新建的页面 target 完全可控(Runtime / DOM / Input 全可用)。 - 因此驱动千问必须「原生 CDP + 自建新 target」,绝不用
--cdp连旧实例。
工具
qw.cjs(本 skill 目录内)。依赖 ws 模块(环境变量 QW_WS_PATH 指定,或自动探测 ~/.workbuddy/skills/xbrowser/... / ~/.openclaw/tools/xbrowser/... 常见位置)。
调用示例(用 managed node):
NODE="C:/Users/<用户名>/.workbuddy/binaries/node/versions/22.22.2/node.exe"
$NODE qw.cjs check # 先诊断:9666 是否就绪 / 千问是否在跑
$NODE qw.cjs ensure # 9666 在就直接连(不起实例);不在则提示用 launch 或自行从 lnk 打开
$NODE qw.cjs launch # 仅当确认要起实例时:先优雅关在跑的千问,再起带 9666 的
$NODE qw.cjs open "https://www.baidu.com" # 新建 tab 并导航,输出 targetId
$NODE qw.cjs navigate <id> "https://..." # 已有 tab 导航
$NODE qw.cjs eval <id> "document.title" # 执行 JS
$NODE qw.cjs snapshot <id> [css选择器] # 取标题/文本/链接/输入框
$NODE qw.cjs click <id> "#su" # 点击元素(按坐标派发鼠标事件)
$NODE qw.cjs type <id> "#kw" "机器人 ROS2" # 向输入框填入文本
$NODE qw.cjs screenshot <id> [out.png] # 截图
$NODE qw.cjs list # 列出所有 target
$NODE qw.cjs close <id> # 关闭 tab
$NODE qw.cjs relaunch # 实例挂掉时:taskkill + 重拉 9666
每个命令都是独立进程,连接到常驻的千问 CDP 实例(默认 9666)操作,所以可多次调用串起多步自动化。
关键常量
- 千问 exe:
C:\Users\<用户名>\AppData\Local\Programs\QianwenApp\qianwen.exe(Chromium 130;环境变量QW_EXE可覆盖) - 真实 profile:
C:\Users\<用户名>\AppData\Local\Qianwen\User Data(登录态/标签页在这里,驱动走的也是这个实例;环境变量QW_PROFILE可覆盖) - CDP 固定端口:
9666(cdp_default_port是 9407,是 agent-browser 默认回退端口,报错里见到的就是它)
已验证的端到端能力
open 百度 → type 搜索框 → click 搜索 → 搜索结果正文读出 ✅。即「开页 + 输入 + 点击 + 读内容」真实交互全通。
读钉钉文档「多维表」(已验证 2026-08-04)
钉钉多维表(alidocs.dingtalk.com/i/nodes/<nodeId>?...sheetId=...)在千问里由同域 iframe #wiki-notable-iframe 承载,contentDocument 可直接读(非跨域)。数据不是 canvas,是真实 DOM:[role=grid] 网格 + 虚拟化行/列(只渲染可见窗口)。
读取步骤:
qw.cjs list找标题含「多维表」的 page target(取 id)。qw.cjs eval <id> "document.getElementById('wiki-notable-iframe').contentDocument.querySelector('[role=grid]').innerText"→ 直接拿整表文本(表头+可见行)。- 取行数/列数:
contentDocument内querySelectorAll('[role=row]')/[role=cell]。 - 全表需翻页/滚动累加:虚拟化只渲染窗口(实测约 42 行/次),要对 iframe 内网格容器逐屏 scroll 并拼接,才能拿全量行。
- 注意:钉钉文档外层 page 的
innerText只含左侧知识库文件树,「研发项目管理多维表」本身是 iframe 里的 grid,必须进 iframe 读。 - 该表即记忆里的「ROS软件项目管理表」:nodeId=
amweZ92PV6mrnN5mIeGyNM3GWxEKBD6p、sheet=O4kXTnQ,字段≈项目名称/负责人/优先级/项目进度细节登记/进度示意/小批量跟进。
读微信读书正文(实测 2026-08-04)
微信读书网页版(weread.qq.com)分两层:
- 目录 / 章节标题 / 元数据:纯 DOM 文本,可读。全书 TOC 可直接从
.wr_page_reader(style/script 剔除后)textContent抽出。 - 正文 prose:页面栅格化为 canvas(
.readerChapterContent里有renderTargetContainer+<canvas>),直接 DOMtextContent只能拿到「JS复制代码」等 UI 文本,正文不暴露为文本。想读正文必须qw.cjs screenshot截取页面 → OCR。innerText返回 0/空:微信读书把每一页做成绝对定位的「页」块,Chromium 的innerText算不出可见文本。- 读整本书:截图每一页 + OCR,或利用 weread 的「文本选择/复制」层(如果存在)逐段模拟选中,成本更高。
- 环境:工作目录有
chi_sim.traineddata(中文 OCR 数据),但本机缺 tesseract 主程序,装完后即可 OCR。
坑(必记)
-
🚨 重要更正(2026-07-30):
49666端口不是千问!它是 svchost.exe(Windows 系统服务,PID 2400) 监听的,与千问无关(曾误判为"千问内部端口/日常实例",已纠正)。千问自身 CDP 端口固定 9666。- lnk 注入早已生效:4 个千问快捷方式(开始菜单 / 桌面 / 任务栏 / Quick Launch)的 ARGS 均含
--remote-debugging-port=9666(UTF16 编码,ASCIIgrep "9666"搜不到,必须用 LNK 二进制解析确认,曾因此误判"未注入")。日常千问从 lnk 双击即带 9666。 - 🚨 核心纪律(老板明确要求):老板的快捷方式/自启动/菜单入口已全注入 9666,日常千问本就该自带 CDP 端口。脚本启动前必须先
check现状:- 9666 已在监听 → 直接连,绝对不另起实例(最常见情况,连老板日常千问即可)。
- 9666 没在、但千问在跑(无端口)→ 不要 spawn 第二个实例(单例冲突、占窗口、刷回收站)。提示老板关掉后从带 9666 的 lnk 重开,或显式调
launch(launch 会先优雅关在跑的千问再起)。 - 9666 没在、千问也没跑 → 让老板从 lnk/菜单/自启动打开(自带 9666),或显式
launch。
ensure已改为「只连不起」:9666 在即alreadyUp直连;不在则返回needLaunch提示,不再 spawn 裸实例。launch才是真正起实例的命令,且会先关在跑的千问避免单例冲突。- ⚠️ PowerShell
Start-Process在 WorkBuddy 沙箱里拉不起 GUI 进程,不要自己 Start-Process。
- 回收站刷文件(千问自身行为,2026-07-30 确认):只要千问在跑,就持续把临时缓存/上报文件(
1'jssdkidx'/'pctrace'/'api'/'jserr'、Browser_.ulog、network.mojom、DXCACHE-)以「可恢复删除」移入回收站 → 回收站一直涨。这是千问客户端自身行为,并非强杀导致(强杀只是加剧脏残留)。关掉千问即停止增长。治标=定时清回收站;根治=反馈千问团队/关闭诊断上报。 - 🚨 不要起后台千问实例占单例锁:
qw.cjs ensure起的 9666 实例若一直不关,会占着 SingletonLock + 显示,导致用户从桌面双击图标走单例激活这个无正常窗口的后台实例 → 表现为「打不开/看不到登录态」。需驱动千问时优先连已有实例;临时起用完即关(Browser.close / Stop-Process 不带 -Force),绝不留后台孤儿实例。 patch_lnk.py已落库,用于检视/补注入 lnk 端口(正确解析 LNK 二进制,绕开被拦的 WScript.Shell COM)。
- lnk 注入早已生效:4 个千问快捷方式(开始菜单 / 桌面 / 任务栏 / Quick Launch)的 ARGS 均含
-
必须建新 target:永远用
open/Target.createTarget开新 tab,别去驱动千问自带的桌面页(静默)。 -
实例挂掉恢复:千问主进程可被
Stop-Process -Force杀掉,但WpkService孤儿进程(--type=utility,引用真实 profile)从 WorkBuddy 沙箱杀不掉(taskkill 返回 exit 1)。它们不占主 SingletonLock,新主实例仍能起,只是堆积会拖慢冷启动。恢复用qw.cjs relaunch。 -
路径正斜杠:千问对
--user-data-dir反斜杠路径会秒退,必须正斜杠(脚本内已处理)。 -
强制窗口模式:千问无头不稳定,必须 headed(脚本内已默认)。
-
登录态由真实 profile 保留 → 自动化时就是老板本人已登录的千问,对外操作(发消息/发帖)仍遵循"先问再动"。
-
诊断登录态看
Default/Network/Cookies:新版 Chromium(M120+) 把 Cookies 从Default/Cookies移到Default/Network/Cookies。查Default/Cookies不存在是正常现象,会误判「登录态丢失」;真正判断登录态完好与否要读Network/Cookies(大小正常即未丢)。 -
对外「清理/关闭/删文件」操作极度谨慎:曾因反复强杀/清回收站/删 User Data 文件把老板日常千问搞到「打不开」。动手前先确认影响范围,拿证据说话,不嘴硬。
何时用
用户要在千问里做自动操作(查资料、填表、抓页面、定时任务等),且要求保留登录态。直接调 qw.cjs,不要走 xbrowser。
评论与讨论
还没有评论,分享你的体验吧。