AI 自动化浏览器操作方案

1. 项目背景与设计目标

  • 背景:需要对大批量目标网址进行自动化操作(如提取邮箱/填写表单)。由于各网站 DOM 结构与交互逻辑差异极大,传统基于固定 CSS/XPath 的脚本无法统一兼容,需引入 AI Agent 动态决策。
  • 核心目标
    • 零 API 成本与高隐私:利用本地 RTX 3060 (12GB) 运行轻量模型,实现完全本地化的推理与执行。
    • 极致的 Token 控制:全量 HTML 会导致 Context 爆炸和 AI 幻觉,必须在输入给 AI 前对 DOM 进行极致降噪与切片。
    • 高并发与高可用:支持多任务并行抓取,具备完善的异常降级与防死循环机制。

2. 核心架构与选型

🚀 主选方案:Playwright-MCP 官方服务 + 指纹浏览器 CDP

  • 实现方式
    打开指纹浏览器 $\rightarrow$ 获取 CDP 端口 $\rightarrow$ 拉起 npx @playwright/mcp@latest 服务 $\rightarrow$ 代码(C# / SK)创建 MCP Client $\rightarrow$ 将 MCP Tools 与浏览器指挥权彻底托管给本地小模型。
  • 优点开箱即用,开发成本极低。网页打标、DOM 降噪、物理点击、Shadow DOM 与 Iframe 均由微软官方底层闭环处理,无需手写页面清洗逻辑。
  • 注意事项:多线程并发时,需在代码中为每个指纹环境动态分配独立 MCP 端口(如 8931, 8932),并控制好进程生命周期。

🥈 备选方案 A:原生 Accessibility Tree + 双向 ID 锚定 (Fallback 1)

  • 实现方式
    通过 Playwright 的 page.Accessibility.SnapshotAsync() 抓取极简 A11y 树,作为上下文传给 AI。
  • 解决 A11y 树“太简化导致无法定位 DOM”的技巧
    1. 操作前注入轻量 JS,为所有可交互 DOM 打上 data-ai-id="X"
    2. 顺手写入标准 ARIA 属性:el.setAttribute('aria-description', 'ai-id-X')(防止被 A11y 树过滤)。
    3. A11y 树会天然携带此 Description,AI 决策后返回 ai-id-X,代码通过 page.Locator("[aria-description='ai-id-X']") 执行物理点击。
  • 适用场景:当 Playwright-MCP 服务因特殊原因挂起,或需要更轻量级、无外部进程依赖的单机执行时。

🥉 备选方案 B:自定义 DOM 极简剪切脚本 (Fallback 2)

  • 实现方式
    在页面中注入自研 JS 脚本:给 <a>, <button>, [onclick] 绑定唯一 data-ai-id,强行剥离 script, style, svg, path 以及无用空标签,拼接成专供 AI 阅读的极简 JSON 树。AI 决策时直接带入 data-ai-id
  • 优点:高度定制。可以把业务逻辑(如“自动保留包含 @ 符号的文本”)写死在前端清洗脚本里,极致省 Token。
  • 缺点:调试成本极高,真实页面的边缘 Case(如隐藏元素、多层嵌套)需要大量时间适配。

🚷 弃用方案:OmniParser V2 纯视觉 Agent

  • 实现方式:Playwright 截图 $\rightarrow$ 视觉模型画框标注坐标 $\rightarrow$ 大模型根据坐标指示点击。
  • 弃用原因
    1. 显存爆掉:视觉模型 + 检测模型会吃满 3060 显存,无法做多线程并发。
    2. 长图盲区:无法一次性截取 Footer(底部)区域的联系方式,AI 容易在“向下滚动”指令中陷入死循环。
    3. 延迟极高:单步截图与图像推理需耗时数秒,效率远低于文本流。

3. 关键工程细节与避坑指南

3.1 MCP 并发与状态隔离 (防串线与崩溃)

  • 进程级隔离:由于 @playwright/mcp 默认是单实例状态,高并发时必须在 C# 端为每个抓取任务启动一个独立的 MCP Server 进程(通过 --port 分配不同的 SSE 端口,或使用 stdio 管道)。
  • 浏览器上下文隔离:通过 CDP 连接指纹浏览器时,必须在 C# 端通过 CDP 协议(Target.createBrowserContext)为每个任务创建独立的 Browser Context(相当于无痕模式的新窗口),并将该 Context 的 ID 传给 MCP,严防多个 AI Agent 操作同一个 Tab 导致“互相踩踏”。

3.2 Snapshot 后处理降噪 (防 Context 爆炸)

  • 痛点:Playwright-MCP 的 browser_snapshot 默认返回完整的 AX Tree。对于包含巨大导航菜单或 Footer 的官网,单次 Snapshot 可能高达 10k+ Tokens,直接撑爆小模型的 Context。
  • 对策:在 C# 端的 MCP Client 拦截层,对返回的 Snapshot 文本进行正则截断或裁剪。例如:移除所有 role="navigation" 且子节点超过 20 个的庞大菜单树,只保留核心内容区域的节点,强制将单次 Snapshot 控制在 3000 Tokens 以内。

3.3 Agent 防死循环硬性约束 (防算力空转)

  • 痛点:小模型在复杂 SPA 页面极易陷入“点击 -> 弹窗 -> 关闭 -> 再次点击”的死循环。
  • 对策
    1. 硬限制:在 System Prompt 和 C# 循环代码中双重限制 MaxSteps = 6
    2. URL 去重:在 C# 端维护一个 HashSet<string> visitedUrls。如果 AI 调用的 Tool 导致页面跳转到了已访问过的 URL,C# 端直接拦截并返回 Tool 错误信息:“该页面已访问过,请寻找其他链接”,强制 AI 改变策略。

4. 落地实施路线 (漏斗式执行流)

  1. 环境隔离与基础直达
    • 主程序调用指纹浏览器 API 唤醒环境(自带代理 IP 与伪装指纹)。
    • 主程序通过 CDP 驱动浏览器直达目标首页(不浪费 AI 算力做基础导航)。
  2. AI 攻坚 (主路线)
    • 启动 playwright-mcp,由本地小模型自动执行多轮工具调用,多跳深入 Contact Us 或社交媒体页面寻找邮箱。
  3. 降级兜底 (备选方案)
    • 若 MCP 在特殊异常页面挂起或返回无效 Snapshot,自动降级为“自定义 DOM 剪切脚本 (备选方案 B)”,吐出 JSON 树让 AI 做最后攻坚。
  4. 结果提取与清理
    • 提取到邮箱后,通过 CDP 关闭当前 Browser Context,释放显存与内存,进入下一个任务。

5. 硬件与部署建议

  • 硬件配置
    • GPU:NVIDIA RTX 3060 12GB (核心推理节点)。
    • CPU/内存:建议 8核16线程以上,32GB+ 系统内存 (Playwright 多开浏览器实例极其吃内存)。
  • 软件栈
  • 推理引擎:Ollama (本地部署 Phi-4-mini 与 Qwen2.5-Coder-7B mac air 上使用 qwen3.5:9b-mlx 在 3060 win 机器上使用 qwen3.5:9b)。
    • 浏览器控制:Node.js 环境 + @playwright/mcp
    • 业务代码:.NET 8 (使用 Microsoft.Extensions.AI 抽象层接入 MCP 与 LLM)。
    • 指纹浏览器:支持 CDP 协议导出的商业/开源指纹浏览器 (如 AdsPower, VMLogin 等)。
上一篇