2.3.1
更新日志
v2.3.1 — 隐身模式反检测增强 + 预设系统
发布日期:2026-02-20
感谢测试者@喵团子爱摸鱼
🎯 核心新特性
预设系统
为每个站点配置引入多预设支持,允许在同一站点的不同标签页使用不同的工作流、选择器和参数配置。
典型应用场景:
- 标签页 A:使用预设 "Pro模型对话" → 启用 new_chat_btn、复杂工作流、较长超时
- 标签页 B:使用预设 "快速识图" → 禁用 new_chat_btn、简化工作流、图片提取优先
功能特性:
- 每个站点可创建多个预设(克隆自现有预设)
- 标签页池支持为单个标签页指定预设(通过
/api/tab-pool/tabs/{index}/preset) - Dashboard UI 支持可视化管理预设(新建、删除、切换)
- 配置文件格式自动迁移(旧版扁平结构 → 新版预设结构)
配置结构示例:
{
"gemini.google.com": {
"presets": {
"主预设": {
"selectors": { "input_box": "...", "send_btn": "..." },
"workflow": [...],
"image_extraction": { "enabled": false },
"file_paste": { "threshold": 50000 }
},
"快速识图": {
"selectors": { "input_box": "...", "send_btn": "..." },
"workflow": [...],
"image_extraction": { "enabled": true, "mode": "first" },
"file_paste": { "threshold": 10000 }
}
}
}
}🔴 关键修复
Cloudflare 高强度盾检测绕过
通过系统性隔离测试,定位并修复了两个独立的 CF 检测向量:
| 检测向量 | 发现方式 | CF 检测原理 | 修复方案 |
|---|---|---|---|
PointerEvent.pressure=0 |
对比有/无 force 参数的 CDP 点击 |
真实鼠标按下时 pressure≈0.5,CDP 默认 pressure=0 |
mousePressed 事件传递 force=0.5 |
| 额外 CDP Session | 对比 network/dom 监听模式 | DrissionPage tab.listen 创建独立 WebSocket + Target.attachToTarget,异常 Session 计数 |
补丁 DrissionPage Listener 复用主连接 |
1. 修复 CDP 点击 pressure=0 检测
-
问题根因:CDP
Input.dispatchMouseEvent的mousePressed事件默认force=0,导致页面PointerEvent.pressure=0(真实鼠标按下时pressure≈0.5)。Cloudflare 高强度盾通过此差异识别自动化点击。 -
修复方案:隐身模式下所有点击操作的
mousePressed事件传递force=0.5,匹配真实设备行为。
2. 修复网络监听暴露额外 CDP Session
-
问题根因:DrissionPage 的
tab.listen功能在启动时会创建独立的 WebSocket 连接并调用Target.attachToTarget建立新的 CDP Session。Cloudflare 可检测到异常的 Session 数量和Network.enable活动。 -
修复方案:新增 DrissionPage 自动补丁(
patch_drissionpage.py),让 Listener 复用 tab 主连接,消除额外连接和 Session。- 补丁支持幂等执行(重复运行不会重复打补丁)
- 自动备份原文件,支持
--restore一键恢复 start.bat启动脚本在依赖安装后自动执行补丁
3. 消除 ele.click() 降级路径
-
问题:隐身模式下部分异常场景会降级回退到
ele.click()和tab.actions.click(),这两者均会触发 CF 检测。 -
修复:所有点击路径统一使用
cdp_precise_click(),彻底移除降级回退。
关键测试结论
- ✅
tab.ele()、ele.rect、ele.states.is_displayed均使用纯 CDP 命令,不注入 JS(Runtime.evaluate调用次数 = 0) - ✅ 纯 CDP 操作(鼠标移动、元素查找、rect 读取)即使重复多轮也不触发 CF
- ❌ DrissionPage 的
tab.listen创建独立 WebSocket 连接 +Target.attachToTarget,这是 CF 检测的主要来源(已修复)
🟡 隐身模式增强
人类化鼠标行为改进
-
按压期间微移
- CDP 点击在
mousePressed→mouseReleased之间插入 1-2 个mouseMoved(buttons=1)微移事件 - 模拟真实手指按压时鼠标的微小位移(±1px 范围内随机),消除"事件沙漠"
- CDP 点击在
-
释放坐标偏移
mouseReleased的坐标允许与mousePressed有 ±1px 偏差,匹配真实人类行为
-
移除危险的降级路径
_dispatch_mouse_move()不再降级到tab.actions.move_to()(测试证明tab.actions系列操作会触发 CF)
-
空闲微漂移不规则化
idle_drift()的移动频率改为:- 30% 概率:连续快速微动(模拟手部抖动)
- 70% 概率:长静止期(3-8秒无移动)
- 更接近真实人类的无意识手部抖动模式
滚轮滚动改用纯 CDP
human_scroll()改用Input.dispatchMouseEvent(type='mouseWheel')替代tab.actions.scroll()- 避免
actions系列的参数差异导致的检测
🛠️ 配置引擎重构
预设架构迁移
- 自动迁移:启动时自动将旧版扁平配置迁移为预设结构(
_migrate_to_presets()) - 残留清理:清理预设外的冗余字段(
_cleanup_preset_residuals()),修复旧 bug 导致的配置重复 - 向后兼容:旧版单预设配置在迁移后自动包装为 "主预设"
文件粘贴配置层级修复
- 修复 BUG:
FilePastePanel.js错误地读写站点顶层的file_paste配置,而非预设内配置 - 修复方案:改为通过
_getActivePresetData()获取活跃预设的可变引用,正确读写预设内配置 - 影响范围:所有通过 Dashboard 修改的文件粘贴配置现在会正确保存到预设内
保存机制优化
- 修复 BUG:
POST /api/config端点直接覆写文件导致_global数据丢失 - 修复方案:改用
config_engine.save_config()保存,自动包含_global(元素定义、回退选择器) - 前端清理:
normalizeConfig()现在会过滤预设外的残留字段,确保保存数据干净
🏊 标签页池增强
标签页扫描优化
- 修复 BUG:
_known_tab_ids永久记录chrome://newtab/等页面的 raw_tab_id,导致用户在同一标签页导航到新网站后仍被跳过 - 修复方案:
- 不再永久标记可导航的空白页(
chrome://newtab/、about:blank) - 扫描时使用
tabs_in_pool(实时计算的池内标签页集合)而非_known_tab_ids判断是否跳过 - 每次扫描时清理已关闭的标签页映射
- 不再永久标记可导航的空白页(
实时响应性增强
- 修复延迟感:
get_tabs_with_index每次查询都强制扫描新标签页(不受 10 秒间隔限制) - 首次获取立即扫描:
acquire()首次进入循环时立即扫描(不等待_should_scan()) - 关闭检测实时化:扫描时检测已关闭的标签页并立即清理映射,避免访问旧标签页导致超时
预设切换 API
- 新增端点:
PUT /api/tab-pool/tabs/{tab_index}/preset— 为指定标签页设置预设 - Dashboard UI:标签页池页面显示预设选择器,支持可视化切换
新增 patch_drissionpage.py
DrissionPage Listener 连接复用补丁脚本。
功能:
- 自动检测 DrissionPage 安装路径
- 备份原文件(
.bak后缀) - 修改
_listener.py让 Listener 复用 tab 主连接 - 支持
--restore恢复原文件
使用方式:
# 自动应用补丁(start.bat 已内置)
python patch_drissionpage.py
# 恢复原文件
python patch_drissionpage.py --restore⚠️ 破坏性变更
-
配置文件格式变更
- 旧版:
{ "domain": { "selectors": {...}, "workflow": [...] } } - 新版:
{ "domain": { "presets": { "主预设": { "selectors": {...}, ... } } } } - 兼容性:启动时自动迁移,无需手动操作
- 旧版:
-
API 响应格式变更
GET /api/config/{domain}默认返回整个站点结构(含所有预设)- 传递
?preset_name=xxx参数可获取单个预设的扁平配置
🐛 其他修复
- 修复
normalizeConfig未清理残留字段导致的配置重复 - 修复标签页池关闭检测不及时导致的卡死问题
- 修复
_cleanup_unhealthy_tabs删除 session 但未清理映射表的内存泄漏 - 修复前端 token key 不一致(
auth_tokenvsapi_token)
📝 已知问题
- DrissionPage 补丁需在每次升级 DrissionPage 后重新执行
- 部分 AI 站点的图片提取配置需手动测试验证
🔧 开发者说明
测试环境:
- Python 3.13
- DrissionPage 4.1.0.11
关键文件变更:
app/core/tab_pool.py— 标签页池扫描逻辑重写app/services/config/engine.py— 预设系统实现 + 迁移逻辑app/api/config_routes.py— 预设相关 APIstatic/js/components/panels/FilePastePanel.js— 预设感知修复static/js/dashboard.js—normalizeConfig清理逻辑patch_drissionpage.py— 新增
如有问题请提交 Issue 或加入交流群