5.8 KiB
5.8 KiB
CapSolver API 注入修复实施记录
修改完成时间
2025-11-17 14:47
实施的修改
文件: src/tools/account-register/sites/windsurf.js
方法: solveWithCapSolver() (第767-962行)
修改内容
1. 改进 Token 注入(第773-783行)
修改前: 仅简单设置 input.value
await this.page.evaluate((solution) => {
document.querySelector('input[name="cf-turnstile-response"]').value = solution;
}, token);
修改后: 注入 token 并触发事件
await this.page.evaluate((token) => {
const input = document.querySelector('input[name="cf-turnstile-response"]');
if (input) {
input.value = token;
// 触发各种事件以通知页面
['input', 'change', 'blur'].forEach(eventType => {
input.dispatchEvent(new Event(eventType, { bubbles: true }));
});
}
}, token);
改进: 触发 DOM 事件,让监听器检测到 token 变化
2. 添加回调函数触发(第787-862行)
新增功能: 多种方法查找并触发 Turnstile 回调
- 方法A: 查找 React 组件回调
window.cf__reactTurnstileOnLoad - 方法B: 从 DOM 元素
[data-callback]属性获取回调名 - 方法C: 使用
window.turnstile.reset()和window.turnstile.execute()API - 方法D: 遍历 window 对象查找包含 'turnstile' 的函数
日志输出: 显示每个方法的触发结果(成功 ✓ 或失败 ✗)
3. 添加按钮强制激活(第876-906行)
新增功能: 后备方案,确保按钮可点击
const buttonActivated = await this.page.evaluate(() => {
const buttons = Array.from(document.querySelectorAll('button'));
buttons.forEach(btn => {
if (btn.textContent.trim() === 'Continue' ||
btn.textContent.trim() === 'Submit') {
if (btn.disabled) {
btn.disabled = false;
btn.removeAttribute('disabled');
btn.classList.remove('disabled');
}
}
});
});
改进: 即使回调失败,也能确保按钮可点击
4. 改进验证完成检测(第908-962行)
修改前:
- 检查 iframe 状态(可能无法访问)
- 超时时间 20 秒
- 失败时等待 30 秒手动操作
修改后:
- 检查1: 按钮必须激活
- 检查2: hidden input 必须有值
- 检查3: iframe 状态(可选)
- 超时时间 10 秒(缩短)
- 轮询间隔 500ms(更频繁)
- 失败时输出详细调试信息
- 如果按钮已激活且有 token,认为成功
- 失败时等待 10 秒(缩短)
调试信息输出:
{
buttonDisabled: false,
buttonText: "Continue",
hasToken: true,
tokenLength: 2000
}
关键改进点
1. 完整的验证流程模拟
- ✅ Token 注入
- ✅ 事件触发
- ✅ 回调调用
- ✅ 按钮激活
- ✅ 状态验证
2. 多重保障机制
- 4 种回调触发方法
- 强制按钮激活(后备)
- 灵活的状态检测
3. 详细的调试信息
- Token 长度显示
- 每个回调的触发结果
- 按钮激活状态
- 最终状态快照
4. 更合理的超时处理
- 缩短等待时间(10秒而非30秒)
- 提供详细的失败原因
- 智能判断是否继续
测试步骤
-
运行注册流程:
node src/cli.js register -s windsurf --keep-browser-open -
观察日志输出:
[CapSolver] 注入 token 到页面 (长度: XXX)...[CapSolver] 回调触发结果:- 查看哪些方法成功(✓)
- 查看哪些方法失败(✗)
[CapSolver] 已强制激活按钮或按钮已经是激活状态[CapSolver] ✓ 验证完成确认通过
-
检查浏览器:
- Turnstile checkbox 是否勾选?
- Continue 按钮是否可点击?
- 是否自动进入下一步?
-
如果失败:
- 查看
[CapSolver] 当前状态:输出 - 判断是回调问题、按钮问题还是 iframe 问题
- 根据具体问题选择下一步方案
- 查看
预期结果
成功场景
[Windsurf] [CapSolver] ✓ 获取到token: 0.kDqN3tMdKWreLsL90...
[Windsurf] [CapSolver] 注入 token 到页面 (长度: 2048)...
[Windsurf] [CapSolver] ✓ Token 已注入到 hidden input
[Windsurf] [CapSolver] 尝试触发 Turnstile 回调...
[Windsurf] [CapSolver] 回调触发结果:
[Windsurf] ✓ cf__reactTurnstileOnLoad
[Windsurf] ✓ window.turnstileCallback
[Windsurf] [CapSolver] 按钮已经是激活状态
[Windsurf] [CapSolver] ✓ 验证完成确认通过
[Windsurf] [CapSolver] ✓ 已点击 Continue 按钮
[Windsurf] 步骤 2 完成
部分成功场景
[Windsurf] [CapSolver] 回调触发结果:
[Windsurf] ✗ cf__reactTurnstileOnLoad: not a function
[Windsurf] ✓ data-callback: onTurnstileComplete
[Windsurf] [CapSolver] ✓ 已强制激活按钮
[Windsurf] [CapSolver] ✓ 验证完成确认通过
→ 至少一个回调成功即可
失败场景
[Windsurf] [CapSolver] ⚠️ 未找到任何回调函数
[Windsurf] [CapSolver] ✓ 已强制激活按钮
[Windsurf] [CapSolver] 验证完成检测超时
[Windsurf] [CapSolver] 当前状态: {"buttonDisabled":false,"buttonText":"Continue","hasToken":true,"tokenLength":2048}
[Windsurf] [CapSolver] ✓ 状态检查通过,继续执行
→ 按钮已激活且有 token,继续执行
后续方案
如果当前修改仍然失败,下一步考虑:
方案3: 提前拦截 Turnstile 初始化
在 initBrowser() 中使用 evaluateOnNewDocument() 提前注入拦截代码
方案2: 使用 CDP 操作 iframe
通过 Chrome DevTools Protocol 直接访问 Turnstile iframe
方案4: 混合方案
不用完整扩展,只注入 inject-turnstile.js 脚本
备注
- 此修改不影响扩展加载方式(第214-300行)
- 废弃的 API 方法仍保留但已标记
@deprecated - 步骤2(密码设置)中的扩展等待逻辑(第507-542行)保持不变