- method_l_shape: OK 候选尺度 ±0.0375 精修(步长 0.0125 + ±6px 窗口), GT live_165204 Δ 179→176(真人 177),离线 9/10 保持 - 插桩 JSON.stringify 捕获 SDK 日志明文;指针 probe 排除 coalesced/pressure - 拖动不跟手指标作废:post_pos 晚于 SDK 重置滑块,鼠标事件流始终完整 - 剩余 VerifyErr = 候选整体选错(视觉确证),方向:多候选质量评估 - docs: experiments/solution/retrospective 同步收尾
75 lines
3.0 KiB
Markdown
75 lines
3.0 KiB
Markdown
# 经验:拟人拖动路径生成算法(反检测三要素)
|
||
|
||
> 场景:验证码行为风控会检测拖动轨迹的「机器特征」。人手拖动的轨迹与
|
||
> CDP `Input.dispatchMouseEvent` 生成的匀速直线完全不同。
|
||
> 代码:`try/human_drag.py`(`gen_human_path(distance_px)` → 增量事件序列)。
|
||
|
||
## 三要素(用户需求 → 实现机制)
|
||
|
||
### 1. 不能是直线 → 贝塞尔弓形骨架 + 高斯抖动
|
||
|
||
```
|
||
主冲程路径 = 三次贝塞尔 P0(0,0) → P3(过冲点)
|
||
P1/P2 控制点带 y 轴弓形偏移(±8~14px,随机方向)
|
||
每步叠加 = gauss 抖动(x: σ≈0.8, y: σ≈1.1)
|
||
抖动幅值随速度变化:中段速度快 → 手更不稳(σ 放大)
|
||
```
|
||
|
||
弓形是关键:不是噪声围绕着直线,而是整体轨迹带自然弧度(人手腕转动)。
|
||
y 轴全程摆动 ±5px 左右,终点收敛回 0。
|
||
|
||
### 2. 不能匀速 → 三段速度结构
|
||
|
||
```
|
||
主冲程 (55-70% 时长):ease-in-out(加速→巡航→减速),14-22ms/步
|
||
回拉 (15-22% 时长):ease-out 快速回退
|
||
微调 (剩余时长) :步长递减的小步逼近 + 末尾 40-120ms 停顿确认
|
||
```
|
||
|
||
速度统计上呈「快-慢-停」节奏,`v_max ≈ 0.5-0.95 px/ms`、`v_min ≈ 0.001`
|
||
(慢两个数量级),与匀速(速度方差≈0)完全可区分。
|
||
|
||
### 3. 不能一次到位 → 过冲-回拉-瞄准
|
||
|
||
```
|
||
阶段1 主冲程 → 目标 + 过冲量(3~9px 随机)
|
||
阶段2 回拉 → 目标 - 欠量(0.5~2.5px)
|
||
阶段3 微调 → 1~2 小步逼近精确目标,每步 15ms+
|
||
```
|
||
|
||
人类视觉反馈回路的标配:先冲过头,再修正。位移曲线 x-t 上
|
||
可见明显的「超过目标 → 拉回 → 精确落点」三段形态。
|
||
|
||
## 用法
|
||
|
||
```python
|
||
from human_drag import gen_human_path, path_stats
|
||
|
||
pts = gen_human_path(distance_px=227.9, seed=42) # seed 可复现
|
||
# pts = [(dx, dy, dt_ms), ...] 相对上一点增量
|
||
for dx, dy, dt in pts:
|
||
cur_x += dx; cur_y += dy
|
||
cdp("Input.dispatchMouseEvent", type="mouseMoved", x=cur_x, y=cur_y,
|
||
button="left", buttons=1)
|
||
time.sleep(dt / 1000)
|
||
```
|
||
|
||
拖动距离换算:solve 的 `distance_px` 是原图(552 宽)坐标,
|
||
乘缩放系数 `UI宽/552`(如 340/552≈0.616)得 UI 像素。
|
||
|
||
## 自检(已内置)
|
||
|
||
`python try/human_drag.py` 断言五项:终点精确(<0.5px)、时长 0.4-2.5s、
|
||
速度起伏(vmax > vmin×5)、y 摆动(>2px)、存在回拉(x 序列非单调)。
|
||
10 样本联合烟测(solve → 换算 → 路径)全通过。
|
||
|
||
可视化:`python try/human_drag.py --plot` →
|
||
`src/out/human_drag_path.png`(三种距离的轨迹)、`src/out/human_drag_xt.png`(x-t 曲线)。
|
||
|
||
## 可调参数(按需)
|
||
|
||
- 短距离(<100px):弓形幅值降到 ±8、过冲 ×0.3(小拖距人不甩)
|
||
- `duration`:默认按距离自估算 0.6-1.4s;拖钮场景可传 `duration=800` 固定
|
||
- 未做:轨迹级鼠标事件 hook 采集真人样本对拍(当前参数为文献常识值,
|
||
如需过高级风控,用 CDP 录制 10 条真人轨迹做分布拟合替换)
|