Web RPA:登录系统 → 点击数据 → 查询数据
用声明式 YAML 任务文件驱动真实 Chromium 浏览器,完成「登录系统 → 点击菜单/数据 → 填写查询条件 → 触发查询 → 截图留档 → 抓取结果」的完整闭环。
核心执行引擎:scripts/rpa_runner.py(Playwright 同步 API)。不要另写 Selenium / Puppeteer / 油猴脚本,统一走这个引擎。
何时使用
- 「帮我登录 XX 系统,查一下 XX 数据」
- 「每天去后台导出 XX 列表」
- 「自动点进数据中心 → 数据查询,按条件查完把表格存下来」
- 任何需要真实浏览器、需要过 JS 渲染、需要登录态的网页取数场景
不适用:纯公开 API 可取数的场景(直接用 HTTP 请求更稳);桌面客户端软件(本技能只覆盖浏览器)。
执行流程
严格按下面五步走,不要跳步。
第 1 步:环境自检
bash /Users/liuzhiqiang/.workbuddy/skills/web-rpa-login-query/scripts/bootstrap.sh
输出 环境就绪 ✔ 即可继续。若提示缺 chromium,等它下完(首次约 150MB,之后复用缓存)。
第 2 步:问清三件事(缺一不可)
- 系统地址:登录页完整 URL 是什么?
- 账号密码:不要写进配置文件。让用户以环境变量方式提供,或写入
~/.rpa/credentials.json(见「凭据管理」)。 - 查询动作:点哪个菜单、填哪些条件、看到什么算查询成功?
再补一句:base_url、是否 iframe 嵌套、结果表格在哪个位置。
第 3 步:生成任务配置
PY=/Users/liuzhiqiang/.workbuddy/binaries/python/envs/default/bin/python
$PY /Users/liuzhiqiang/.workbuddy/skills/web-rpa-login-query/scripts/rpa_runner.py --init ./<任务名>.yaml
然后按 assets/task-template.yaml 的注释填充。字段含义见 references/task-config.md。
选择器是成败关键。 若不知道选择器,先跑一次「探测」,拿到真实 DOM:
# 探测配置示例:打开页面后 dump 可交互元素
name: 探测页面元素
base_url: https://your-system.example.com
steps:
- action: goto
url: /login
- action: eval
js: "Array.from(document.querySelectorAll('input,button,a,select')).slice(0,80).map((e,i)=>i+'|'+e.tagName+'|'+(e.id||'')+'|'+(e.name||'')+'|'+(e.innerText||'').slice(0,20)).join('\\n')"
- action: screenshot
name: 探测页
full_page: true
选择器写法与常见套路见 references/selector-guide.md。
第 4 步:校验配置
$PY .../rpa_runner.py ./<任务名>.yaml --check
通过后再执行。首次务必加 --headed,人工确认点击路径正确、没跑偏。
第 5 步:执行并交付
RPA_USERNAME='xxx' RPA_PASSWORD='yyy' \
$PY .../rpa_runner.py ./<任务名>.yaml --headed
产物落在 output.dir(默认 ./rpa_output/):
<任务名>_<时间戳>.json—— 结构化结果 + 截图清单 + 来源 URL<任务名>_<时间戳>.csv—— UTF-8-BOM,Excel 直接双击不乱码screenshots/*.png—— 查询结果页 / 验证码 / 失败现场截图
执行结束会打印「RPA 执行报告」JSON(status / steps_done / 各表行数 / 产物路径)。把报告里的产物路径和行数汇报给用户,并用 present_files 把 JSON/CSV/截图展示出来。
凭据管理(重要)
绝不要把账号密码写进 YAML 或提交到任何仓库。 三种方式,按推荐顺序:
- 环境变量(推荐,配置里写
${RPA_USERNAME}/${RPA_PASSWORD}) - 命令行覆盖:
--set RPA_PASSWORD=xxx - 凭据文件
~/.rpa/credentials.json,按 profile 分组:
{
"default": { "RPA_USERNAME": "zhangsan", "RPA_PASSWORD": "***" },
"prod": { "RPA_USERNAME": "svc_robot", "RPA_PASSWORD": "***" }
}
用 --profile prod 切换。日志会对手填的密码自动脱敏为 ********。
登录态默认缓存在 ~/.rpa/state/<profile>.json,第二次执行会自动复用,跳过登录。要强制重新登录加 --no-state。
关键参数速查
| 参数 | 作用 |
|---|---|
--headed |
显示窗口。首次调试、验证码场景必加 |
--slow-mo 300 |
每步放慢 300ms,肉眼跟得上 |
--check |
只校验配置不执行 |
--init FILE |
生成配置模板 |
--skip-login |
跳过账号密码填充,直接用缓存登录态 |
--set K=V |
覆盖任意变量(含密码、查询条件) |
--profile NAME |
切换凭据 profile,同时切换登录态文件 |
--no-state |
不读也不存登录态,每次全新登录 |
--output-dir DIR |
覆盖产物目录 |
--screenshot-all-steps |
每步截图,排查问题时用 |
--keep-open |
跑完不关浏览器,人工检查用 |
--debug |
打印完整异常堆栈 |
输出目录约定
rpa_output/
├── <任务名>_20260929-173000.json
├── <任务名>_20260929-173000.csv
└── screenshots/
├── 20260929-173000_查询结果页.png
└── 20260929-173000_失败现场-step5.png
常见坑(先看这里再排查)
- 登录成功判定缺失 → 加
success_selector(如「退出」按钮、用户名区),否则会在登录页就开始点菜单。 - 企业系统 iframe 嵌套 → 登录页或菜单在 iframe 内时,加
frame步骤进入,frame_exit退出。见references/selector-guide.md。 - 结果表格懒加载 → 查询后加
wait等tbody tr出现,再加sleep 1兜底。 - 分页只拿到第一页 → 见
references/advanced-recipes.md的「翻页抓取」配方。 - 验证码 → 先区分类型:滑块验证码用
drag动作自动拖(见advanced-recipes.md配方 4.1,实测多数前端校验可过);图形码/短信/扫码用captcha_selector+--headed人工输入,或让用户先手动登录一次,之后靠storage_state复用。 - 点击被遮罩层挡住 → 引擎已做
scroll_into_view,仍失败则在点击前加sleep 1等弹窗消失。 goto超时但页面其实已打开 → 页面挂了百度统计 / 高德地图等第三方脚本,这些请求被网络黑洞化会拖死domcontentloaded。引擎已默认拦截统计域名并自动降级为wait_until=commit重试;降级后记得补wait等一个稳定元素,否则 SPA 还没渲染。- 复用登录态却卡在启动加载页 → 探测类任务(没配
login段)也会写storage_state,产生只有统计 Cookie 的"假登录态"。首次真实登录务必--no-state;登录段要显式指定url(登录页 hash),否则引擎会开base_url的/。 - 列表页字段多、有分页和嵌套子表时,优先走接口 → 在页面上下文里
fetch(用实时读取的 token),比 UI 点击导出拿到的列更全。见advanced-recipes.md配方 8;注意芋道的ACCESS_TOKEN是双层 JSON,只解一层会 401。
完整排错表见 references/troubleshooting.md。
参考文件
references/task-config.md—— 任务配置全字段说明(先读这个)references/selector-guide.md—— 选择器写法、iframe、动态 ID、企业系统套路references/advanced-recipes.md—— 翻页抓取、导出下载、页面内 fetch 直取接口(配方 8)、多条件遍历、定时批量references/troubleshooting.md—— 报错对照表assets/task-template.yaml—— 可直接改的起点模板