AI Developer Blog

AI Agent浏览器自动化的5个天坑:血泪教训总结

May 1, 2026

在过去的几个月里,我一直在开发基于浏览器自动化的AI Agent技能。云电脑、CDP协议、PyAutoGUI......这些技术听起来很美好,但真正落地时遇到的坑,让我整整踩了两周。今天把我总结的5个核心天坑分享出来,避免大家重蹈覆辙。

坑1:CAPTCHA/极验滑块根本过不去

这是最让人崩溃的坑。我原本以为AI视觉识别+模拟滑动能搞定一切,结果发现:

残酷真相:反自动化是这些服务的核心商业模式,他们的团队专门研究如何识别Bot。你用AI过验证码,等于在挑战一个每年研发投入上亿的团队。

我尝试过滑块识别算法、轨迹生成模型、打码平台API......最终承认:有些验证码,只能靠人。

坑2:浏览器只能串行用——多任务并发是个噩梦

我在开发云电脑自动化技能时,最初的设计是"多子任务并行":一个任务处理登录,另一个处理数据录入,第三个做截图......

实际运行时发生了什么?


// 错误示范:同时操作多个标签页
async function parallelBrowserTasks() {
  const tabs = await browser.createTargets(); // 创建多个标签页
  
  // 这三个任务同时执行CDP命令
  await Promise.all([
    executeLogin(tab1),    // CDP: 输入用户名、密码、点击登录
    fillForm(tab2),        // CDP: 填写表单、点击提交
    takeScreenshot(tab3)   // CDP: 截图
  ]);
}
      

结果:

根本原因:Chrome DevTools Protocol是同步单会话协议,多个客户端同时发送命令会互相干扰。

坑3:DNS劫持——云电脑的隐形杀手

这个问题隐蔽到我花了3天才定位出来。

症状:CDP连接正常,但所有HTTP请求都失败,curl和浏览器都打不开任何网站。


# 测试DNS
nslookup api.openai.com
# 返回: 127.0.0.1 或者奇怪的IP地址

# 检查hosts文件
cat /etc/hosts
# 发现大量被劫持的域名

原因:某些云电脑服务商的镜像默认修改了hosts文件,用于"安全审计"或"流量控制"。

解决方案


# 备份并清理hosts
sudo cp /etc/hosts /etc/hosts.backup
sudo echo "127.0.0.1 localhost" > /etc/hosts
sudo sh -c 'cat /etc/hosts.backup | grep -v "# CLOUD" >> /etc/hosts'

坑4:React组件CDP交互失败——DOM存在但点击无效

这个问题坑了我整整一周。

目标:点击一个"删除"按钮,触发确认对话框。


// CDP点击按钮
await cdp.DOM.getDocument();
const button = await cdp.DOM.querySelectorAll({
  selector: 'button[data-action="delete"]'
});
await cdp.DOM.dispatchEvent(button.nodeId, 'click');

结果:按钮高亮了,但对话框没出来。

检查DOM,按钮确实存在。再看React DevTools,发现这个按钮用的是Radix UI的Dialog组件。

问题本质:现代React组件不直接绑定DOM事件,而是通过Virtual DOM state管理。CDP的dispatchEvent触发了原生click事件,但React的SyntheticEvent没有收到。

解决方案:需要注入JavaScript来触发React的事件系统。


// 正确方式:注入JS触发React事件
await cdp.Runtime.evaluate({
  expression: `
    const button = document.querySelector('button[data-action="delete"]');
    button.click(); // 原生click会冒泡到React
    // 或者使用React的测试API
    const reactInstance = button[Object.keys(button).find(k => k.startsWith('__react'))];
    if (reactInstance) {
      reactInstance.props.onClick();
    }
  `
});

坑5:文件上传——选择器对了但上传失败

文件上传是CDP的老大难问题。

问题1:系统对话框无法弹出

CDP没法触发系统文件选择对话框,这是Chrome的安全限制。

问题2:input[type=file]选择器定位困难

很多上传按钮实际是自定义UI,真正的input被隐藏:


<!-- 常见的隐藏上传控件 -->
<div class="upload-area">
  <input type="file" style="display:none" id="hidden-upload">
  <button onclick="document.getElementById('hidden-upload').click()">
    上传文件
  </button>
</div>

问题3:CDP upload需要精确的CSS选择器


// CDP上传命令
await cdp.Page.setInputFiles({
  files: ['/path/to/file.pdf'],
  payload: null
});
// ❌ 错误:没有指定选择器,CDP不知道上传到哪个input

// 正确方式
await cdp.DOM.getDocument();
const input = await cdp.DOM.querySelector({
  nodeId: root.nodeId,
  selector: 'input[type="file"]'
});
await cdp.Page.setInputFiles({
  files: ['/path/to/file.pdf'],
  elementId: input.elementId
});

终极解决方案:Human-in-the-Loop

经过两个月的踩坑,我的结论是:纯自动化有极限,人机协作是正解

我设计的混合架构:


class HumanInTheLoopController {
  async execute(task) {
    try {
      // 1. AI先尝试自动化
      await this.autoExecute(task);
    } catch (error) {
      if (this.isHumanRequired(error)) {
        // 2. 检测到需要人类介入
        await this.pauseAndNotify();
        
        // 3. 截图通知用户
        const screenshot = await this.takeScreenshot();
        await this.notifyUser('需要人工操作', screenshot);
        
        // 4. 等待用户完成
        await this.waitForUserAction();
        
        // 5. 恢复自动化
        await this.resume();
      } else {
        throw error;
      }
    }
  }
}

总结

原因解法
CAPTCHA反自动化是商业模式人机协作/打码平台
多标签冲突CDP同步协议任务队列串行执行
DNS劫持云电脑hosts污染清理hosts文件
React组件无响应Virtual DOM事件隔离JS注入触发SyntheticEvent
文件上传失败系统对话框安全限制定位隐藏input+CDP upload

相关开源项目

Coze技能推荐

如果你正在开发浏览器自动化相关的Coze技能,推荐使用我的云电脑自动化技能,它已经内置了: