网络表单填报技能 — 从信息搜集到浏览器填报的完整工作流,确保框架受控组件正确写入、页面切换前暂存、最终提交由用户确认。
58
68%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Fix and improve this skill with Tessl
tessl review fix ./skills/web-form-fill/SKILL.md面向在线表单填报场景:申报系统、比赛报名、补贴申请、信息登记等。核心原则:先看后填、模拟真人、切页必存、提交由人。
依赖技能:browser-guide(浏览器操作最佳实践)
主力后端 =
target=camoufox(camoufox-cli)。下方「§3 浏览器填报」的命令 / 示例 / 控件填写方法只针对target=camoufox。target=host/target=node:§1 信息搜集 / §2 字段清单 / §4 提交前确认 这些后端无关的步骤照本 skill 执行;§3 浏览器填报只按「流程 + 提示事项」走,不要照搬camoufox-cli ...命令——用你当前后端自带的浏览器工具语义调用即可。「逐字 type」「切页必暂存」「提交由人」这些约定是后端无关的,照本 skill 执行。
打开浏览器后,先完整浏览整个表单,不要急着填。
form-fields-{项目简称}.md),保持与表单相同的页面/段落结构markdown 文件结构示例:
# XX大赛申报 — 字段清单
## 概要
- 项目名称 [必填] [text] [限50字]
- 行业分类 [必填] [级联下拉] 一级→二级
- 科技创新领域 [必填] [下拉单选]
- 参赛渠道 [必填] [下拉多选]
- 以投代评 [必填] [radio: 是/否]
- 服务需求 [多选] 最多3项
- 期望融资金额 [必填] [number] 万元
- 股权释放比例 [必填] [number] %
## 参赛项目情况
- 项目名称 [必填] [text] (概要中已填,此处联动)
- 前沿技术热点归属 [必填] [text] 最多5个关键词,逗号分隔
- 项目主要技术、产品及服务 [必填] [富文本] 2000字以内,可插入图片
- 项目产品市场分析及竞争优势 [必填] [富文本] 2000字以内
- 商业模式 [必填] [富文本] 1000字以内
## 企业基本信息表
...
## 附件
- 营业执照 [必填] [PDF/图片]
- ...回到 markdown 文件,逐项填写准备好的内容:
问用户的典型场景:
信息齐全后,开 camoufox-cli session 逐页填报。
session 约定:申报系统这类不涉及平台登录态长期化的站点走临时性 session(不带 --persistent,每次随机指纹,关闭自清)。如果该表单本身需登录(如某政务网账号),先按 browser-guide 流程登录态就绪。
强制有头模式:本 skill 一律 --headed——表单填报需用户时刻观察填报情况,可随时介入纠正(browser-guide 显式有头场景规则第 3 条)。不要用无头模式跑填报。
SESSION="formfill-$(date +%s)"
camoufox-cli --session "$SESSION" --headed --json open "<表单首页 URL>"
# …snapshot / click / type / select / upload 填报…
# 任务结束 close
camoufox-cli --session "$SESSION" --json close涉及扫码 / 短信 / 验证码的申报站点同样必须
--headed(browser-guide 显式有头场景规则),用户能在浏览器里手动过。
click 点暂存核心原则:统一用 camoufox-cli 的 type 子命令逐字符输入,对所有站点、所有输入框一视同仁。
唯一方法:camoufox-cli --session <s> --json type <ref> "<文本>"
type 走浏览器真实输入管线(逐字符 keydown → char → keyup),与真人键盘输入完全一致snapshot 拿到输入元素的 ref(如 @e7),再 type @e7 "<文本>"。不要自己 hack CSS selector填写流程:
对每个文本字段:
1. snapshot 拿到该字段的 ref
2. click <ref> 聚焦(顺带 scrollIntoView)
3. 清空已有内容(见下方清空方式)
4. camoufox-cli --session <s> --json type <ref> "要填入的文本"
5. 验证写入是否生效(见 3-C 节)
6. 如果验证失败:
a. 清空内容
b. 重新聚焦后重试一次 type
c. 仍然失败 → 记录该字段为"无法自动填写",继续下一个字段为什么 type 就够了:
| 场景 | type 是否生效 | 原因 |
|---|---|---|
| 原生 input/textarea | ✅ | 逐字符 keydown/char/keyup 走浏览器真实输入管线 |
| Vue/React v-model 受控组件 | ✅ | 框架监听 input 事件,type 触发的 keydown → input 事件链完整 |
| Slate/wangEditor/Tiptap 编辑器 | ✅ | 逐字符 keydown 会触发浏览器的 beforeinput 事件,Slate 监听的就是这个 |
| 有输入 mask 的字段 | ✅ | 逐字符输入让 mask 逻辑逐字处理,不会跳过格式化 |
| 防机器人检测的站点 | ✅ | 默认 delay 模拟真人节奏,不触发异常检测 |
禁止的方式:
eval 直接设 innerHTML / textContent — 框架不感知,placeholder 不消失,暂存后内容丢失eval 直接赋值 el.value = "xxx" 不发事件 — 框架完全无感知camoufox-cli fill <ref> "<文本>" — 一次性塞入整段文本,不触发逐字事件链,受控组件和 mask 字段容易出问题逐级尝试:
| 级别 | 方法 |
|---|---|
| A | snapshot 拿到 select 的 ref → click <ref> 打开下拉面板 → snapshot 拿目标选项 ref → click <选项-ref> |
| B | click <ref> 打开 → press <ref> "ArrowDown" 方向键选择 → press <ref> "Enter" 确认 |
| C | fallback:eval 设 native setter + dispatchEvent('change') |
自定义下拉(非原生 <select>,如 Element Plus el-select、Ant Design Select):
click 触发按钮打开弹层snapshot 找目标选项 clicksnapshot 拿到目标选项 ref → click <ref>click <ref> 聚焦 → press <ref> "Space" 切换逐级尝试:
| 级别 | 方法 |
|---|---|
| A | click 日期输入框 → snapshot 拿日历面板里年/月/日 ref → 逐个 click |
| B | click 日期输入框聚焦 → type 输入日期字符串 |
| C | fallback:eval 设 native setter + dispatchEvent |
snapshot 拿到 <input type="file"> 或上传按钮的 refcamoufox-cli --session <s> --json upload <ref> <file-path>(fork 加的 upload 命令,底层 Playwright setInputFiles,穿透 shadow DOM)upload <ref> <file1> <file2> <file3>| 控件类型 | 验证方式 | 通过条件 |
|---|---|---|
| 普通 input | snapshot 看 ref 的 value / placeholder 可见性 | value 包含预期内容 且 placeholder 不可见 |
| contenteditable / Slate 编辑器 | snapshot 看 textContent 和 placeholder 元素 | textContent 包含预期内容 且 placeholder 元素 display: none。延迟 50ms 再验证 — Slate DOM 更新有延迟 |
| 下拉 select | snapshot 看选中项文本 | 选中项文本与预期一致 |
| radio/checkbox | snapshot 看选中状态 | 选中状态符合预期 |
验证失败的处理:
type切换页面/栏位前,必须执行:
snapshot 检查当前页面是否有 暂存 / 保存 / 保存草稿 按钮click 点暂存,等待"保存成功"提示click 切换页面如果当前页没有暂存按钮:
所有页面填写完成后:
snapshot 检查所有字段值是否正确camoufox-cli --session <s> --json screenshot /tmp/final-form.png 截图,或 eval 导出表单内容,发送给用户审阅click "提交"按钮,必须等用户明确指令原因:框架内部状态未更新。
解决:确保用 type 逐字输入(会触发完整事件链),而非直接操作 DOM。type 失败时重新聚焦重试。
原因:框架内部状态为空,暂存提交的是空值。
验证方法:暂存后,导航到其他页面再回来,检查字段是否仍有值。
原因:Slate 处理 beforeinput 后,文本已写入数据模型但 DOM 还没渲染完。
解决:验证前延迟 50ms+,等 Slate 微任务队列跑完再读 textContent。
对策:
click 的是编辑器内容区域([contenteditable="true"]),而非工具栏document.activeElement 是编辑器或其子节点(eval 看)click 工具栏按钮(如加粗)激活编辑器,再重新 type对策:
scroll 下拉面板使目标选项可见press 方向键选择目标项 → press "Enter" 确认对策:
type 节奏调慢(在 camoufox-cli 默认基础上手动多停顿:每个字段间 sleep 0.5-1)browser-guide 的 CAPTCHA 处理流程操作1. snapshot 拿到目标元素的 ref(如 @e7)
2. camoufox-cli --session <s> --json click @e7 (顺带 scrollIntoView + 聚焦)1. click <ref> 聚焦
2. camoufox-cli --session <s> --json press <ref> "Control+a" (全选)
3. camoufox-cli --session <s> --json press <ref> "Backspace" (删除)
4. snapshot 验证:ref 的 value 为空1. click <ref> 聚焦编辑器
2. camoufox-cli --session <s> --json press <ref> "Control+a"
3. camoufox-cli --session <s> --json press <ref> "Backspace"
4. sleep 0.05
5. snapshot 验证:编辑器 textContent 为空1. 聚焦 + 清空
2. camoufox-cli --session <s> --json type <ref> "要填入的内容"
3. 验证(见 3-C 节)防机器人检测场景,节奏调慢:每输入一段 sleep 0.3-1,字段间 sleep 1。
1. snapshot 拿到 <input type="file"> 或上传按钮 ref
2. camoufox-cli --session <s> --json upload <ref> <file-path> [<更多文件>...]
3. snapshot 验证缩略图 / "上传成功" 文本出现bcef823
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.