diff --git a/docs/README.md b/docs/README.md index d007c81..463a033 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,6 +6,19 @@ - [solution.md](solution.md) — 最终方案:算法原理、API 用法、结果验证方法、10 样本结果与已知边界 - [experiments.md](experiments.md) — 实验演进记录(A→L):各方法失败原因、转折点实验、调试坑、无真值交叉验证方法 +- [retrospective.md](retrospective.md) — ★ 全项目复盘:四阶段演进、决定性发现、踩坑清单、方法论沉淀与未竟事项 + +## 浏览器自动化经验(browser-automation/) + +一条经验一个文档,自动化操作中探索到的可复用经验: + +- [cdp-browser-use-basics.md](browser-automation/cdp-browser-use-basics.md) — CDP 9222 连接与 browser-use 基础 API、js() 顶层变量坑 +- [douyin-captcha-detection.md](browser-automation/douyin-captcha-detection.md) — 验证码 iframe 预加载机制与「已触发」的判定方法 +- [douyin-comment-input.md](browser-automation/douyin-comment-input.md) — 视频页评论框输入(DraftEditor 假 INPUT 坑、坐标点击、Ctrl+Enter 提交) +- [douyin-captcha-trigger-attempts.md](browser-automation/douyin-captcha-trigger-attempts.md) — 触发验证码的早期尝试记录(无效方法清单) +- [captcha-screenshot-capture.md](browser-automation/captcha-screenshot-capture.md) — wasm/GPU 渲染图片的 fromSurface=False 截图采集法(已被网络层法取代) +- [human-drag-path.md](browser-automation/human-drag-path.md) — 拟人拖动路径生成算法(非直线/非匀速/过冲瞄准三要素) +- **[captcha-auto-solve-pipeline.md](browser-automation/captcha-auto-solve-pipeline.md) — ★ 最新:密码登录触发法、网络层样本采集、tip_y 真值校准、自动闭环与 5014 行为风控现状** ## 快速开始 diff --git a/docs/browser-automation/captcha-auto-solve-pipeline.md b/docs/browser-automation/captcha-auto-solve-pipeline.md new file mode 100644 index 0000000..c69d40f --- /dev/null +++ b/docs/browser-automation/captcha-auto-solve-pipeline.md @@ -0,0 +1,102 @@ +# 经验:验证码自动通过闭环(采集→求解→拖动)与行为风控现状 + +> 更新:2025-09-11 晚。此前 [captcha-screenshot-capture.md](captcha-screenshot-capture.md) +> 与 [douyin-captcha-trigger-attempts.md](douyin-captcha-trigger-attempts.md) 的方法 +> 已被本篇取代/升级,本篇是当前最新状态。 + +## 1. 可复现触发法(已验证,最可靠) + +**密码登录法**:主页点「登录」→ 弹窗点「密码登录」→ 手机号 `18601010101` + +随机密码(如 `26969877Ab!`)→ 勾协议 → 点「登录」→ **拖动重叠验证码必弹**。 +(密码错误提示是预期的,验证码照样触发;真人手动拖可通过) + +## 2. 网络层样本采集(取代 DOM/截图法,`try/captcha_net_capture.py`) + +验证码图片不走 ``(wasm 解码进 GPU 层),但**图片 URL 会正常发 HTTP 请求**: + +- `verify.zijieapi.com/captcha/get`(POST)→ 响应 JSON 含 `question.url1`(大图 + 552×344 jpeg)、`url2`(mark 110×110 RGBA png)、**`tip_y`** +- 图片托管在 `p3/p9-catpcha.byteimg.com`,直接是原始字节 + +websocket 常驻监听(`Target.setAutoAttach` + Network 域 + `getResponseBody`)即可 +把原图字节落盘 —— **与 captchas/ 离线样本完全同规格,无需缩放**,solve 直接可用。 + +## 3. tip_y 服务端提示(重大发现) + +`tip_y × 2 = 缺口 y 坐标(mark 画布顶,原图 552×344 坐标系)`。 +10 组线上样本校准:solver 无约束 y 与 `2×tip_y` 差 ≤4px 的样本全部位置判定正确; +偏差大的(如 Δy=17)正是被服务端判 `VerifyErr` 的。 + +**`try/live_solve.py`**:用 tip_y 约束 y,在 score map 上重选 x —— 服务端等于 +免费下发了 y 真值,只需求 x。 + +## 4. 拖动闭环(`try/auto_solve_drag.py`) + +CDP websocket 直连全流程(不依赖 browser-use CLI):点刷新 → 轮询 get.json 落盘 +→ live_solve → `human_drag.gen_human_path` 拟人路径 → `Input.dispatchMouseEvent` +拖滑块 → 读 verify 结果。**get→verify 全程 <8s**(challenge 有效期约 60-90s, +超时会 `NotFoundChallengeId`)。 + +实测确认: + +- 滑块拖动 1:1 映射 mark 位移(拖 100px → mark 移 100px) +- 拖动距离 = solver x × 340/552(UI 缩放) +- 服务端响应三种:`验证通过` / `VerifyErr`(轨迹过、位置差)/ `5014 操作过快`(轨迹被拒) + +## 5. 剩余 gap:5014 行为判定(未解决) + +VerifyErr 与 5014 交替出现 = 位置与轨迹都接近临界。真人可过而脚本被 5014 拒, +原因在 `captchaBody`(~6.3KB 加密轨迹密文,含 w2/x86 设备指纹): + +- 轨迹明文由 SDK wasm 加密,离线解不开 +- 我的拟人路径(贝塞尔+噪声+过冲回拉)仍被判机器 —— SDK 采集的不止鼠标点, + 可能含 pointermove 原生事件流、movementX、事件时间戳分布、设备指纹等 +- **下一阶段方向**:hook SDK 内部轨迹采集函数(wasm 前的 JS 层),直接注入 + 自定义轨迹数组,让 SDK 自己加密上报;或对比真人 captchaBody 字节结构定位 + 采集字段 + +## 6. 文件清单 + +| 文件 | 用途 | +| --- | --- | +| `try/captcha_net_capture.py` | 网络层常驻监听,抓 get/verify 响应 + 图片字节 | +| `try/captcha_verify_watch.py` | 专抓 verify 请求 POST 全文(captchaBody 对比用) | +| `try/live_solve.py` | tip_y 约束版求解(线上样本专用) | +| `try/human_drag.py` | 拟人拖动路径生成器 | +| `try/auto_solve_drag.py` | 一条龙闭环(刷新→solve→拖→读结果) | +| `try/captures/pair_*` | 已采集线上样本对(17 组) | + +## 7. 后续实验结论(2026-05-15/16,xdotool 硬件输入 + 换号循环) + +上述"下一阶段方向"已被系统性实验否定——**输入层不是根因**: + +- **xdotool(OS 级 XTest 硬件鼠标)** 拖 solve 位置 → 仍 VerifyErr; + 事件属性(pressure/movementX/coalesced/isTrusted)与真人无差异; +- **真人轨迹重放**(human_trace_pass.json,含 20-266ms 抖动间隔、4px y 振幅、 + 0.7s 终点停顿)→ 仍 VerifyErr; +- **会话预热**(触发前 45-75s 页面游走)→ 不改变结果; +- 真人 PASS 与机器拖的差异只剩「**行为分窗口**」(5014 = 窗口内累计失败, + 真人 PASS 夹在机器失败之间仍能过)与「**位置小偏差**」(±10px 级,视觉确证 + live_191109 solve 正确但 live_135654 贴片在 solve 块内略偏)。 + +### 触发与限流工程结论 + +- **触发限流(不出题)**:清 cookie 即解除(`Network.clearBrowserCookies` + + `Page.navigate` 回 douyin)——用户实测确认,无需等待; +- **触发拒绝误报**:错误检测正则勿包含"验证码登录"(tab 文字本身); + 真正的号段拒绝文案是"仅支持验证码登录"; +- **reload 坑**:清 cookie 后 session 失效,`Page.reload` 会把页面带到 + 空标签/跳转页,必须用 `Page.navigate` 显式回 douyin; +- **challenge 时效**:约 1 分钟,采题后的任何预热/等待都会耗死题 + (NotFoundChallengeId)——预热必须放在**触发之前**; +- **拖动时长保真**:重放轨迹时 up 前最后一步的 dt(真人 ≈0.7s 终点对齐) + 不能丢,否则 2.6s 被压成 1.9s;跳过 0 位移步时 `t_plan` 仍要累加。 + +### 文件 + +| 文件 | 用途 | +| --- | --- | +| `try/rotate_loop.py` | 清 cookie + 换号零等待循环(风控即换号) | +| `try/cold_start_attempt.py` | 单次完整尝试(预热/采题/选优/xdotool 拖动) | +| `try/enrich_replay.py` | 重放轨迹 60Hz 加密(实验结论:勿用,真人事件流稀疏) | +| `try/human_trace_pass.json` | 真人 PASS 轨迹(live_165204,2.60s/17 move) | diff --git a/docs/browser-automation/captcha-screenshot-capture.md b/docs/browser-automation/captcha-screenshot-capture.md new file mode 100644 index 0000000..58c2262 --- /dev/null +++ b/docs/browser-automation/captcha-screenshot-capture.md @@ -0,0 +1,70 @@ +# 经验:拖动验证码页面截图采集(CDP) + +> 场景:验证码图片渲染在 wasm/GPU 层(`img` 元素 `naturalWidth=0`、canvas 0×0、 +> src 是占位 URL),常规 DOM/canvas 提取拿不到真实位图;用户手动右键「另存为」可以。 + +## 为什么 DOM 方式全失败 + +抖音 rmc-captcha 的图片不走标准 ``: + +| 尝试 | 结果 | +| --- | --- | +| `img.src` / `currentSrc` | 是 iframe 页面自身 URL(占位),fetch 回 HTML | +| `img.naturalWidth` | 0(图片数据从未进入 img 元素解码管线) | +| `canvas.toDataURL()`(drawImage 复制) | canvas 未污染但输出**全黑透明**(RGBA 全 0) | +| CSS `background-image`(元素/伪元素/父链/shadow DOM) | 全部 `none` | +| `Network.getResponseBody` 抓 `verify.zijieapi.com/captcha/get` | 响应体是图片字节但**无法与 DOM 对齐**;手动 GET 重放会 501 参数错误 | +| `Page.captureScreenshot`(默认 `fromSurface=true`) | iframe 区域**空白**——wasm/GPU 合成层不进该截图通道 | + +结论:图片由 wasm 解码后直接进 GPU 合成层,DOM 与 JS 均不可见。 + +## 正解:`fromSurface=False` 全屏截图 + Python 裁剪 + +```python +r = cdp("Page.captureScreenshot", format="png", + captureBeyondViewport=False, fromSurface=False) # 关键参数 +open("/tmp/full.png", "wb").write(base64.b64decode(r["data"])) +``` + +要点: + +1. **`fromSurface=False`** 走非合成层通道,能拿到真实像素(经实测验证: + 同一区域 `fromSurface=True` 灰板、`False` 有图)。 +2. **clip 参数会被忽略**(`fromSurface=False` 时返回全屏 1920×993),需 Python 裁剪。 +3. 裁剪坐标 = iframe 视口位置 + iframe 内元素位置: + - iframe 在视口 `(770, 305)`,大小 380×384 + - 大图在 iframe 内 `(20, 69)`,340×212 → 视口裁剪 `[374:586, 790:1130]` + - mark(未拖动时)与大图同起点,68×68 → 视口裁剪 `[374:442, 790:858]` +4. 先在 iframe 内用 `Runtime.evaluate` 取元素 `getBoundingClientRect()` + (attach iframe target 后,坐标系是 iframe 内部坐标系,注意换算)。 + +## 验证码 iframe 布局(v2,380×384) + +``` +iframe (770,305) 380x384 +├─ close-btn (326,0) 54x54 右上角关闭 +├─ 标题栏 .captcha-bar (20,12) 340x69 「请将左侧图形拖到正确位置」 +├─ 大图 .verify-image (20,69) 340x212 大图区域 +│ └─ mark(初始态) (20,69) 68x68 与大图同起点(未拖动时) +├─ 滑条 .captcha-slider(20,293) 340x44 底部滑轨+拖钮 +└─ 刷新/反馈 (20,345) 页脚操作行 +``` + +## mark 图的坑(RGB 采集) + +截图裁出的 mark 是**带灰底**的(页面背景 246,245,244),与离线样本 +(PNG 透明底 + alpha 轮廓)不同。喂给 solve 前需转 RGBA: + +```python +mark = cv2.imread(mark_crop_path) +bg = np.array([246, 245, 244]) +diff = np.abs(mark.astype(int) - bg).sum(axis=2) +alpha = np.clip(diff * 3, 0, 255).astype(np.uint8) +rgba = cv2.merge([mark[:, :, 0], mark[:, :, 1], mark[:, :, 2], alpha]) +``` + +## 尺寸缩放(原图 vs UI 显示) + +离线样本:大图 552×344、mark 110×110(RGBA)。 +线上 UI:大图 340×212、mark 68×68,缩放系数 ≈ **0.616**(340/552)。 +solve 的 `distance_px` 是原图坐标系,执行拖动时乘以缩放系数换算成 UI 像素。 diff --git a/docs/browser-automation/cdp-browser-use-basics.md b/docs/browser-automation/cdp-browser-use-basics.md new file mode 100644 index 0000000..646d23a --- /dev/null +++ b/docs/browser-automation/cdp-browser-use-basics.md @@ -0,0 +1,57 @@ +# 经验:CDP 9222 连接与 browser-use 基础操作 + +> 场景:需要对用户已登录的真实 Chrome(远程调试端口 9222)做自动化操作。 + +## 连接检查 + +```bash +curl -s http://127.0.0.1:9222/json/version # 通了即可用 +curl -s http://127.0.0.1:9222/json # 列出页面 target +``` + +## browser-use 调用模式 + +CLI 名为 `browser-use`,用 heredoc 传 Python 代码,helpers 已预导入: + +```bash +browser-use <<'PY' +for t in list_tabs(): # 列出所有页面 tab + print(t["targetId"], t["url"][:80]) +PY +``` + +## 关键 API + +| API | 用途 | +| --- | --- | +| `list_tabs()` | 列出页面 tab,返回完整 targetId | +| `switch_tab(targetId)` | attach 到指定 tab(不改变 Chrome 可见 tab);**必须传完整 targetId**,8 位前缀会报 `No target with given id found` | +| `activate_tab(targetId)` | 把 tab 切到前台(用户可见) | +| `js(expression)` | 在当前页面执行 JS,自动 await Promise | +| `capture_screenshot(path)` | 截图保存到本地文件 | +| `click_at_xy(x, y)` | 视口坐标点击(CDP 鼠标事件,穿透 iframe/shadow DOM) | +| `cdp("Domain.method", ...)` | 任意 CDP 协议调用 | +| `wait_for_load(15)` | 等待导航完成 | + +## 坑:js() 顶层 let/const 会跨调用残留 + +`Runtime.evaluate` 在页面全局作用域执行,顶层 `let out = []` 会留下全局词法绑定, +下次调用再写 `let out` 直接 `SyntaxError: Identifier 'out' has already been declared`。 + +**解法:所有多行 JS 一律包 IIFE:** + +```python +r = js(""" +(() => { + let out = []; + ... + return out.join('\\n'); +})() +""") +``` + +## 注意 + +- 每个 `browser-use <<'PY'` 是独立 Python 进程,Python 变量不跨调用保留; + 页面状态(DOM、JS 全局变量)跨调用保留。 +- CDP target 顺序 ≠ Chrome 可见 tab 标签页顺序,用 `list_tabs()` 认 URL。 diff --git a/docs/browser-automation/cdp-drag-force-pressure.md b/docs/browser-automation/cdp-drag-force-pressure.md new file mode 100644 index 0000000..7322c1d --- /dev/null +++ b/docs/browser-automation/cdp-drag-force-pressure.md @@ -0,0 +1,140 @@ +# CDP 拖动与行为风控实验记录(force/pressure 发现) + +时间:2026-05-15(连线实验,Chrome CDP 9222 + douyin.com 登录触发验证码) + +## 实验环境 + +- 验证码 iframe:`rmc.bytedance.com/verifycenter/captcha/v2`,380x384,视口坐标 (770,305) +- 滑块按钮初始中心:iframe 坐标 (54,307);刷新按钮 (30,355) +- 大图 UI:`.captcha-verify-image` (20,69) 340x212(对应原图 552x344,SCALE=340/552=0.616) +- mark 预览:`.captcha-verify-image-slide` 68x68(= 110x110 × 0.618) + +## 核心发现 1:CDP 缺省 pressure=0 是硬指纹 + +CDP `Input.dispatchMouseEvent` 不带 `force` 参数时,产生的 MouseEvent 均无 +pressure(DOM 事件里 `event.pressure === 0`)。按 W3C UI Events 规范, +真实鼠标按下/拖动时 pressure 应为 **0.5**(鼠标无压感设备时恒 0.5)。 + +SDK(captcha.js / webmssdk)采集的事件流含 pressure,可据此判自动化。 + +**修复**:`mousePressed` / `mouseMoved` / `mouseReleased` 全部加 `force: 0.5`, +实测 DOM `event.pressure` 变为 0.5 ✓(主页与 iframe 内均验证)。 + +## 核心发现 2:错误码语义分层(多次连线实验归纳) + +| 错误码 | message | 语义 | +| -------- | --------- | ------ | +| 500 VerifyErr | 验证失败,请根据提示重新操作 | 行为闸门已过,**位置判定失败**(或轨迹分不足) | +| 502 [5014] | 操作过快,请慢一点 | 行为判定拒(轨迹过快/异常),位置未判 | +| 502 [5009] | 验证过于频繁,请稍后重试 | **频控**:短时间连环尝试后触发,冷却数分钟恢复 | +| 502 NotFoundChallengeId | 验证超时 | challenge 过期(采题后拖延太久) | + +关键实验: + +1. `force` 缺省(=0)时全部 5014; +2. `force=0.5` 后出现过 VerifyErr(行为关过了、位置判了)——说明 pressure + 至少是 5014 的成因之一; +3. 连环快速尝试(数十次/小时)后一律 5009 频控——5014 与 5009 会互相掩盖, + 判定"位置对错"必须在频控冷却后做单次干净尝试; +4. AMBIGUOUS 候选(solve 置信度低)的题拖了必 VerifyErr;OK 候选的题 + (当时还没判到位置层)也被 5014/5009 拦住,位置正确性尚未闭环确认。 + +## 核心发现 3:拖动映射与 mark 预览行为 + +- 按钮 1:1 带动 mark 预览(按钮 +60px → mark UI +60px,实测); +- mark 初始相对大图 rel=(0, tip_y*2)(原图坐标)——**每题垂直位置自动对齐** + (mark 预览 img 的 y 每题不同,实测 rel_y×(552/340) ≈ tip_y*2); +- 拖动距离 = `solve.x × 340/552`(UI px); +- 拖动失败/失败重开后 mark 预览复位到 rel x=0; +- 验证成功后 iframe 自毁(`/json/list` 里 rmc iframe 消失)。 + +## 核心发现 4:iframe 内 XHR hook 采题(不依赖 netcap) + +netcap(Network 域抓包)attach 时机不稳。更可靠的做法:attach iframe 后在 +页面上下文注入 XHR hook,把 `captcha/get`、`captcha/verify` 的响应存到 +`window.__lastGet` / `__lastVerify`,CDP 轮询读取: + +```js +XMLHttpRequest.prototype.open = function(m,u){ this.__u=u; return oOpen.apply(this,arguments); }; +XMLHttpRequest.prototype.send = function(){ + this.addEventListener('load', () => { + if (/captcha\/get/.test(this.__u||'')) window.__lastGet = JSON.parse(this.responseText); + if (/captcha\/verify/.test(this.__u||'')) window.__lastVerify = this.responseText; + }); + return oSend.apply(this, arguments); +}; +``` + +题目图片可直接 `urllib` 下载 `question.url1/url2`(无需解码密文)。 +注意:hook 必须在拖动前注入;点击"刷新"产生新 get 不重建 iframe,hook 仍有效。 + +## 线上题 vs 离线样本的差异(solve 风险) + +- 离线 17 组样本(captchas/):洞为**暗色覆盖物**,方法 L 分数 1-3,全部命中; +- 线上 URL 下载的题:覆盖物为**亮白半透明花瓣**贴片,方法 L 分数 3.6-7.7, + 明显变差;部分题最佳候选 scale≠1.0(0.85-1.075),会出现 AMBIGUOUS; +- `tip_y*2`(原图缺口顶 y)与 solve.y 交叉验证:OK 且分数低的题两者一致 + (如 solve y=190 vs tip_y*2=192 ✓);solve 跑飞时两者差得远(可当否决器)。 + +## 后续验证结果(同日) + +1. **位置判定已确认可达**:频控冷却后单次 force=0.5 拖动稳定得到 VerifyErr + (位置层判定被执行),5014 不再出现 —— pressure 修复对行为闸门有效。 +2. **hover 序列确认毒化拖动**:按下前发 `button:"left"+buttons:0` 的 + mouseMoved 会导致 verify 根本不发出。修正:无按键时用 `button:"none"`。 +3. **solve 已增强**:`solve(..., tip_y=...)` 用服务端缺口顶 y 真值锚定候选, + 离线 10/10 不回归,线上 8 题 7 中(详见 solution.md「线上增强」节)。 +4. **频控仍是拦路虎**:单 IP 连环尝试后 5009 窗口 >20 分钟,仅靠冷却 + 很难完成多次位置闭环判定。后续应换环境(新 IP/无痕 profile)做 + 「冷启动 → 单次拖动」实验,验证 tip_y 锚定后的 solve 能否一次通过。 +5. `try/solo_attempt.py`:单次干净尝试脚本(冷却→采题→solve→拖→读 verify), + 供冷启动实验复用。 + +## 决定性对照实验(2026-05-15 补充,推翻旧归因) + +| 实验 | 账号 | 操作者 | 结果 | +| --- | --- | --- | --- | +| 多次 CDP 拖动 | 老账号(已被限制 1467) | 脚本 | 5014 / VerifyErr / 5009 混杂 | +| 真人手拖 ×3 | 同上老账号 | 人 | **超时 / 拖动过快 / 网络环境差,全失败** | +| 真人手拖 ×1 | **新账号** | 人 | **验证通过,iframe 自毁** | + +结论修正: + +1. **老账号被风控标记后连真人都过不了** —— 之前「真人可过、CDP 必败」 + 的对照不成立,5014/VerifyErr 的主因是账号级标记(可能叠加 IP 维度), + CDP pressure=0 只是叠加因素之一; +2. 「网络环境差」「操作过快」「验证超时」是账号/环境被标记后的三种表象, + 与拖动质量无关(真人正常手拖也被拒); +3. **后续所有行为/位置判定实验必须在「干净账号 + 未标记环境」上做**, + 否则结果无法归因。此前在本机老账号上积累的 5014 样本全部存疑; +4. CDP 自动化在干净账号上的真实通过率尚未测得(下一步实验)。 + +## 拖动时长实验(2026-05-15 下午) + +把 `gen_human_path` 缺省总时长从 0.6-1.4s 拉到 **5-10s 随机**(用户要求,真人拖动 +观测 ~4-8s)后连续测试: + +| # | 场景 | 拖动时长 | 结果 | +| --- | --- | --- | --- | +| 3 | 干净账号第 2 连拖 | ~6.5s | 5014 操作过快 | +| 4 | reload 后第 3 连拖 | ~6s | 5014 操作过快 | + +结论: + +1. **5014「操作过快」与拖动速度无关** —— 6s 的慢拖同样被判过快;该文案是 + 行为分累积到阈值后的固定话术; +2. 行为分按 **账号+设备指纹** 累积(跨 challenge、跨页面 reload 不清零), + 连续 CDP 拖动 2-3 次即触发;真人首次通过 = 行为分从 0 开始; +3. 第 1 拖(干净行为分)拿到的是 VerifyErr 而非 5014 —— 此时位置判定真正 + 执行了,但位置仍被判错(solve 经 IoU 亚像素验证 ±1px、SDK 实际位移与 + 期望一致)→ **位置无误仍 VerifyErr 指向 verify 通道的其它指纹** + (captchaBody 密文内的轨迹编码 / detail 参数),而非坐标映射; +4. 接口限流:随机号触发验证码的 get 接口也有频控(「系统繁忙」),触发 + 同样要冷却。 + +后续方向(按性价比排序): + +- 在干净环境(新 profile/IP,行为分 0)做**单次** CDP 拖动:若 VerifyErr + 消失 → 之前所有 VerifyErr 均为行为分污染,位置判定本来就对; +- 对比真人通过样本与 CDP 样本的 captchaBody 长度/结构(轨迹编码密度); +- hook SDK 轨迹采集函数,直接注入受控轨迹(绕开 CDP 事件指纹)。 diff --git a/docs/browser-automation/douyin-captcha-detection.md b/docs/browser-automation/douyin-captcha-detection.md new file mode 100644 index 0000000..75e6731 --- /dev/null +++ b/docs/browser-automation/douyin-captcha-detection.md @@ -0,0 +1,60 @@ +# 经验:抖音验证码出现的检测方法 + +> 场景:自动化操作中需要知道「拖动重叠验证码」什么时候弹出来。 + +## 检测选择器 + +```python +r = js(""" +(() => { + const f = document.querySelector('iframe[src*="captcha"], iframe[id*="captcha"]'); + if (!f) return 'no-iframe'; + return 'visible=' + (f.offsetParent !== null) + ' w=' + f.offsetWidth + ' h=' + f.offsetHeight; +})() +""") +``` + +## 关键事实 + +- 抖音在页面加载时就会**预加载验证码 iframe**(字节 rmc-nocaptcha,无感验证框架), + 默认 `display:none, w=0 h=0`。**iframe 存在 ≠ 验证码触发**。 +- 判定触发看可见性:`f.offsetParent !== null` 或 `f.offsetWidth > 0`。 +- iframe src 特征:`https://lf-rc1.yhgfb-cn-static.com/obj/rc-verifycenter/rmc-nocaptcha/.../index.html` + (rc-verifycenter = 字节验证中心)。 + +## 辅助手段 + +**1. 查页面加载过的验证码相关资源**(判断风控 SDK 是否激活): + +```python +js(""" +(() => performance.getEntriesByType('resource') + .map(e => e.name) + .filter(u => /captcha|verify|rc-verify|secsdk/i.test(u)) + .slice(0, 20).join('\\n'))() +""") +``` + +出现 `rc-verifycenter/sec_sdk_build/.../captcha/index.js`、`rmc-nocaptcha/.../setup.js` +说明验证码 SDK 已就绪,等待触发条件。 + +**2. MutationObserver 监听验证码 DOM 出现**(挂在页面里,外部轮询读结果): + +```python +js(""" +(() => { + window.__captchaSeen = []; + new MutationObserver(muts => { + for (const m of muts) for (const n of m.addedNodes) { + if (n.nodeType !== 1) continue; + const s = (n.tagName + ' ' + (n.className||'') + ' ' + (n.id||'')).toString(); + if (/captcha|verify|secsdk/i.test(s)) window.__captchaSeen.push('add: ' + s.slice(0,100)); + } + }).observe(document.body, {childList: true, subtree: true}); + return 'ok'; +})() +""") +``` + +**3. 拖动验证码本体在 iframe 内部**,需要 attach 到 iframe target 或在 iframe 内执行 JS +才能抓到 552×344 大图与 110×110 mark 图。 diff --git a/docs/browser-automation/douyin-captcha-trigger-attempts.md b/docs/browser-automation/douyin-captcha-trigger-attempts.md new file mode 100644 index 0000000..1a9428e --- /dev/null +++ b/docs/browser-automation/douyin-captcha-trigger-attempts.md @@ -0,0 +1,38 @@ +# 经验:触发抖音拖动验证码的尝试记录(截至 2025-XX 未成功) + +> 场景:为采集验证码样本,需要主动触发「拖动重叠」验证码。 +> 本文档记录已尝试且**无效**的方法,避免重复试错。 + +## 环境 + +- Chrome 148,已登录账号(cookie 正常,avatar/登录态正常) +- 验证码 SDK(rc-verifycenter / rmc-nocaptcha)已在页面预加载但未触发 + +## 已尝试且未触发验证码的操作 + +| # | 操作 | 结果 | +| --- | --- | --- | +| 1 | 用户主页连续 reload ×4(间隔 ~5s) | 无验证码 | +| 2 | 搜索页连续换关键词导航 ×4(cat/dog/street photography/travel) | 无验证码 | +| 3 | 打开视频 modal + 视频详情页 | 无验证码 | +| 4 | `creator.douyin.com` 创作者首页 / 内容上传页 | 无验证码(首次访问 creator 域曾被弹回 www 主站) | +| 5 | 视频页评论框输入「你好」+ Ctrl+Enter 提交 | **评论直接发布成功**,无验证码 | + +## 观察 + +- 验证码 iframe(rmc-nocaptcha)始终预加载但 `display:none`,未弹出。 +- 请求 URL 中已带 `verifyFp` / `fp` 参数,风控指纹已建立,但行为分未到触发阈值。 +- 单纯的页面导航 + 一次评论不构成风控触发条件。 + +## 下一步待尝试(按性价比排序) + +1. **高频点赞/取消点赞**(行为风控最常见触发器) +2. **高频关注/取关** +3. 短时间连续发多条评论 +4. 快速滚动视频 feed + 快速翻页 +5. 私信/敏感账号设置操作 +6. 无 cookie 的干净环境访问(风控分数从零开始,更容易触发) + +## 通用检测代码 + +见 [douyin-captcha-detection.md](douyin-captcha-detection.md)。 diff --git a/docs/browser-automation/douyin-comment-input.md b/docs/browser-automation/douyin-comment-input.md new file mode 100644 index 0000000..d5b0ac2 --- /dev/null +++ b/docs/browser-automation/douyin-comment-input.md @@ -0,0 +1,46 @@ +# 经验:抖音视频页评论框输入(DraftEditor 的坑) + +> 场景:通过 CDP 在抖音视频页评论框输入文字并提交。 + +## 坑 + +1. **容器里有假 INPUT**:`.comment-input-inner-container` 内有一个 `INPUT` 元素, + focus 它无效(`document.activeElement` 仍是 BODY),insertText 也进不去。 + 真正的编辑器是 Draft.js:`div[contenteditable="true"].notranslate.public-DraftEditor-content`。 +2. **输入框可能在视口外**:直接取 rect 可能 y 为负或超视口,坐标点击会点空 + (activeElement 变 BODY)。 +3. **没有可见的「发布」按钮**,提交用 Ctrl+Enter。 + +## 正确步骤 + +```python +# 1. 滚动到可见 +js("document.querySelector('.comment-input-inner-container').scrollIntoView({block:'center'})") + +# 2. 取新坐标并点击 +box = js(""" +(() => { const r = document.querySelector('.comment-input-inner-container').getBoundingClientRect(); + return JSON.stringify({x: Math.round(r.x+r.width/2), y: Math.round(r.y+r.height/2)}); })() +""") +pos = json.loads(box) +click_at_xy(pos["x"], pos["y"]) + +# 3. 确认焦点在 DraftEditor(div.notranslate.public-DraftEditor-content)后插入文字 +cdp("Input.insertText", text="评论内容") + +# 4. Ctrl+Enter 提交 +cdp("Input.dispatchKeyEvent", type="keyDown", modifiers=2, key="Enter", + code="Enter", windowsVirtualKeyCode=13, nativeVirtualKeyCode=13) +cdp("Input.dispatchKeyEvent", type="keyUp", modifiers=2, key="Enter", + code="Enter", windowsVirtualKeyCode=13, nativeVirtualKeyCode=13) +``` + +## 验证 + +- 焦点成功:`document.activeElement.className` 含 `notranslate public-DraftEditor-content`。 +- 输入成功:容器 `textContent` 变为输入内容(placeholder 消失)。 + +## 注意 + +发评论是**真实写操作**(会真的发出去),触发验证码失败时评论会直接发布成功—— +操作前确认账号允许发测试评论,或事后手动删除。 diff --git a/docs/browser-automation/human-drag-path.md b/docs/browser-automation/human-drag-path.md new file mode 100644 index 0000000..6f94fdb --- /dev/null +++ b/docs/browser-automation/human-drag-path.md @@ -0,0 +1,74 @@ +# 经验:拟人拖动路径生成算法(反检测三要素) + +> 场景:验证码行为风控会检测拖动轨迹的「机器特征」。人手拖动的轨迹与 +> 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 条真人轨迹做分布拟合替换) diff --git a/docs/experiments.md b/docs/experiments.md index 1282f1a..b19acb3 100644 --- a/docs/experiments.md +++ b/docs/experiments.md @@ -83,3 +83,220 @@ (41ac:88×106 vs 88×106); 3. 全部候选可视化后人工目检:真目标应落在几何图形上而非纹理上; 4. 结果叠加轮廓回贴大图(`src/verify_result.py`),观察贴合精度。 + +## 线上闭环实验(2026-05-15,CDP 连线) + +搭了「hook 采题 → solve → CDP 拖动 → 读 verify」全自动闭环后,暴露出离线 +评估覆盖不到的三层问题: + +1. **CDP pressure 指纹**:不带 `force` 的鼠标事件 pressure=0(真鼠标恒 0.5), + 行为风控 5014 的高危成因。加 `force:0.5` 后错误码从 5014 变为 VerifyErr + (位置层),证明 pressure 是被采集的判别特征(详见 + browser-automation/cdp-drag-force-pressure.md)。 +2. **错误码分层**:5014(行为拒)→ VerifyErr(位置判了但错)→ 5009 + (频控,压住一切)→ NotFoundChallengeId(challenge 过期)。判定任何 + 改动的效果都必须在频控冷却后单次干净尝试,连环重试的 5014/5009 + 是无效信号。 +3. **线上题分布漂移**:URL 下载的线上题覆盖物是亮白半透明贴片(离线样本 + 是暗色洞),方法 L 分数从 1-3 恶化到 3.6-7.7,且出现 scale 偏移 + (0.85-1.075)与 AMBIGUOUS。翻转 dark_pen 的 bright 模式更差(7+), + 说明亮贴片信号弱,尚无可靠增强。 + +交叉验证手段新增:**tip_y 一致性检查**——服务端 `question.tip_y*2` 应等于 +solve.y(mark 画布顶 y),两者差得远说明 solve 跑飞,可直接否决该题。 + +其它工程教训: + +- hover 序列里 `buttons` 与 `button` 状态矛盾(buttons=0 但 button="left") + 会毒化 SDK 拖动注册,verify 根本不发出——按下前保持 button:"none"+buttons:0, + 拖动中 buttons:1,释放后恢复; +- 每轮点刷新不重建 iframe,iframe 内 XHR hook 持续有效,比 netcap 的 + Network 域抓包可靠得多; +- 拖动映射已实测校准:按钮 1:1 带动 mark(UI px),mark 初始相对大图 + (0, tip_y*2)(原图坐标),拖动距离 = solve.x × 340/552。 + +### 干净账号 CDP 拖动序列(2026-05-15 下午) + +换干净账号 + 随机凭证触发后连续 4 次实验(拖动时长依次 3s→5-10s): + +| # | 距上次 | score | solve x | SDK位移 | 结果 | +| --- | --- | --- | --- | --- | --- | +| 1 | 冷启动 | 2.450 | 263 | 202* | **VerifyErr** | +| 2 | +2min | 2.610 | 329 | 202.0/202.6 | **VerifyErr** | +| 3 | +6min | 2.731 | 261 | 160.0/160.8 | 5014 过快 | +| 4 | +6min | 2.368 | 188 | 115.0/115.8 | 5014 过快(拖动已 5-10s) | + +*第 1 次未量位移。关键读数: + +- SDK 实际位移与期望差 ≤0.8px —— CDP→SDK→DOM 映射无损; +- solve 位置经 IoU 亚像素精修确认 ±1px —— **坐标换算无误**; +- 第 1-2 拖 VerifyErr(位置判定执行)、第 3-4 拖 5014(行为分累积后 + 位置判定被跳过)—— 与老账号序列模式一致; +- 5-10s 慢拖不能消除 5014 → 行为分按账号+指纹累积,非单次拖动速度。 + +附带:真人对照(同环境)——老账号手拖 3 次全败(超时/过快/网络差), +换新账号手拖 1 次即过。**账号被标记后连真人都过不了**。 + +### flatness 贴片特征发现(2026-05-15 傍晚,线上定位瓶颈突破) + +live_145400 拖动失败后的归因链:SDK 位移完美 → IoU 亚像素验证 solve 位置 +±1px → 仍 VerifyErr。逐题深挖发现该题 chamfer 精修分 2.655 的最优候选是 +**雪枝纹理假峰**,IoU 实证真缺口在 (412,68)(refined 反而 8.349)—— +边界/纹理特征在亮贴片雪景题上彻底失灵,此前所有 VerifyErr 均由此贡献。 + +依次否证的特征:masked NCC(离线 0/10 命中)、内部纹理 zNCC(真缺口与 +假峰都 ≈0,贴片重绘了内部纹理)、亮度抬升 lift(真缺口 lift 为负)。 + +**有效特征:flatness = 贴片内灰度 std / 环形灰度 std**。白半透明贴片把 +盖住的背景"贴平",真缺口 0.04–0.28,假峰 0.49–0.67。向量化实现 +(filter2D 算窗口均值/方差)后每尺度 ~0.5s。 + +接入 solve_pair(tip_y 提供时优先 flatness,命中判 OK)+ 修复两处坐标系 +bug(tip_y 锚定 canvas=bbox−bbox_y0×s;band 中心同向)后回归: + +| 集合 | 修复前 | 修复后 | +| --- | --- | --- | +| 离线 10(无 tip_y,chamfer 路径) | 9/10 | 9/10(不变) | +| 线上 batch 8(tip_y) | 7 OK + 1 AMBIGUOUS | **8/8 OK(全 flatness 命中 6 道)** | +| live_145400(GT IoU 实证) | 偏 163px | **差 (5,4)px** | +| live_143018(此前跑飞题) | 偏 240px | flatness 命中 (327,187) | + +另修复:SCALES 网格下限 0.85→0.70(线上目标尺度可低至 0.775)、拖动时长 +5–10s(用户要求,真人观测 4–8s)、随机号触发换号重试(部分号段仅支持 +验证码登录,提交被拒后自动换号)。 + +### 真人 GT 校准与 solve 修复(2026-05-15 傍晚,决定性) + +用户配合做了 5 次手拖校准(轨迹录制器实时快照),拿到 3 个位置真值: + +| 题 | solve(修复前) | 真人 GT | 偏差 | 用户结果 | +| --- | --- | --- | --- | --- | +| live_165204 | chamfer 179 | 177 | +2 | **PASS** | +| live_172458 | flatness 433 (s=0.7) | 388 | **+45** | 网络差(位置对) | +| live_173321 | flatness 209 (s=0.825) | 391 | **-182** | 网络差(位置对) | + +两条铁律浮出水面: + +1. **flatness 小尺度匹配(s<0.8)全是假阳性**——吸到天空/贴片内部等大平坦区; + 真目标尺度集中在 0.9–1.075; +2. 之前的交叉验证会被**弱 chamfer 候选"掩护"**(假 flatness 恰好靠近一个 + 同样是假的 s=0.7 chamfer 候选,两者互相印证通过)。 + +修复(`FLAT_S_MIN=0.8` + 交叉验证只与 refined 前 2 强候选比)后: +**3/3 真人 GT 命中(dx=0/0/2)**,离线 9/10 保持。 + +### 输入层排除记录 + +- **CDP 合成指纹**:用 xdotool(OS 硬件级鼠标,浏览器无法区分真人)拖 + solve 位置 → 仍 VerifyErr → 排除 CDP Input 管线指纹假说; +- **事件指纹**:影子记录器对比真人/CDP 的 pressure(0.5)、movementX/Y(非零)、 + coalesced、间隔分布——JS 可见属性全部一致; +- **时序积压**:绝对时间轴调度修复(旧代码尾部有 1s 空洞 + 0 位移 move); +- **轨迹机械化**:`enrich_replay.py` 把 18 点重放加密为 60Hz 样条流 + (Catmull-Rom + 速度衰减微抖动)。 + +结论:**之前所有失败案例事后看都是位置错(flatness 假阳性),不存在独立的 +"输入指纹拒"**。位置修复后待验证:硬件拖动 + 正确位置能否 PASS(后台循环 +进行中,冷却是服务端 5014 强制的 15 分钟窗口)。 + +### 换号零等待 + 会话预热 + 时长修复(2026-05-16 上午) + +用户确认:触发限流时**清 cookie 即可解除**(`rotate_loop.py` reload 前先 +`Network.clearBrowserCookies`,再 `Page.navigate` 回 douyin——清 cookie 后 +session 失效会跳页,reload 会把页面带到空标签)。 + +三项修复后 20 分钟冷却 + 预热 + 干净单拖 → 仍 VerifyErr: + +1. **触发拒绝正则误报**:`/验证码登录/` 会匹配登录 tab 自身文字,导致每次 + 提交都被判"被拒"换号。改为 `/仅支持验证码|不存在|格式有误|频繁|繁忙|错误/`; +2. **up 前终点停顿丢失**:真人 PASS 轨迹 up 前 dt≈0.7s(终点对齐), + 旧代码固定 `sleep(0.15)`,拖动总时长 2.6s 被压成 1.9s。改为 + `sleep(max(pts[-1].dt, 0.15))`;跳过 0 位移步时也累加 `t_plan`(时间轴连续); +3. **会话预热**:真人 down 前有 307s 页面活动,我们只有 11s。新增 + `_warmup_session()`(触发验证码**之前**游走 45-75s——放在采题后会把 + challenge 等过期,NotFoundChallengeId 实测)。 + +### 会话轨迹硬数据(真人 vs xdotool) + +| 指标 | 真人 PASS | xdotool(修复后) | +| --- | --- | --- | +| 拖动 | 109px / 2.60s / 17 move | 位移精确 / 2.6s / 17 move | +| move 间隔 | 20/83/266 ms | 完全一致(同一轨迹重放) | +| down 前 | 70 事件 / 307s | 预热后 ≈30 事件 / 60s | +| up 后 | 11 事件,1ms | 4 事件,500ms | +| y 振幅 | 4px | 4px | + +### 悬而未决 + +- **VerifyErr 根因**:位置小偏差(视觉确证 live_191109 solve 正确, + live_135654 块内 diamond 略偏)与行为分耦合,现有真值无法拆分; +- 真人 GT 采集效率低(challenge 约 1 分钟过期 + 用户主观对齐误差可达 + 84px——live_190742 两次自拖差 84px),可信 GT 只有 live_165204 PASS; +- 偶发"拖动不跟手"(鼠标事件完整、SDK 位移 15-100px 戛然而止)无法复现规律。 + +--- + +## 尺度精修与 VerifyErr 收尾(2026-09-15 深夜) + +### 社区情报核查(VerifyErr 语义确认) + +多来源交叉(52pojie 滑块纯算帖、cnblogs 拉灯 s_v_web_id、yoyo1216 playwright、 +TikTok-Captcha-Solver、jishuzhan 轨迹原理): + +- **VerifyErr = 滑块缺口距离错误**(位置层);VerifyModelErr 才是轨迹被模型拒 +- 换算系数 340/552(≈0.616)为社区共识;部分实现带 ±5px UI 修正(方向互相矛盾, + 均无严格论证,source_check 两次判 missing-evidence) +- TikTok-Captcha-Solver:reply.x 按原图 552 系上报(modified_img_width=552), + y 每点恒等于 tip_y;CSDN 150612271 实测样本 reply x∈[236,428](modified_img_width=340 + 但 x 超 340)→ x 上报的确实是另一(原图)尺度 +- jishuzhan 轨迹原理:滑块起始 x∈[20,84.05]、y∈[281,325];进页面鼠标轨迹与 + 滑动轨迹是两组;AI 生成的"四边进入+起始范围"不合规轨迹会被拒 + +### 插桩:SDK 加密前明文(JSON.stringify hook) + +hook JSON.stringify,捕获含 `"mode"`/`relative_time` 的长串。抓到的是 SDK **日志 +上报**(h5_result / h5_show_picture),非 captchaBody;确认字段:duration(展示→ +可交互时长,不是拖动时长)、dragType: "btn"、is_decision、canvas_hash、stage。 + +### 指针事件流级对比(真人 vs xdotool,iframe 内 probe) + +| 特征 | 真人 | xdotool 60Hz | +| --- | --- | --- | +| coalescedEvents.length | 1 为主(663/682),少量 2 | 1 | +| pointerType / pressure | mouse / 0.5 | mouse / 0.5 | +| move 间隔 | 中位 34ms(≈30Hz),含 0ms 同帧双事件 | 16.7ms | +| 坐标小数 | 无(全整数) | 无 | +| y 振幅 | ±9px | ±4px | + +输入层无决定性差异;coalesced/pressure/pointerType/时间戳全部排除。 + +### 「拖动不跟手」指标作废 + +post_pos 在 mouseup 后 0.5-2s 读取,**VerifyErr 后 SDK 立即重置滑块**—— +读到的 0.0/22.9px 是重置动画中间态。__dragTrace 显示鼠标事件流在全部案例中 +完整(53-57 move,位移与期望一致)。此前的"SDK 位移截断"是误读。 + +### 尺度精修(src/method_l_shape.py,本轮核心修复) + +SCALES 网格步长 0.025,真尺度落在步间时轮廓对齐可偏 5-15px(VerifyErr 量级)。 +对入选 OK 候选在 s±0.0375(步长 0.0125)重扫 + ±6px 窗口局部最优 + rotation_scan, +取 refined 最低: + +- 离线回归 9/10 保持;精修值出现在网格外(s=0.988/1.038/1.012)证明生效 +- GT live_165204:179 → **176**(真人 177,Δ −2 → −1) +- **机器 PASS #2**:live_160548,x=255,**s=1.0375**(精修值),157.1px 18 步重放, + SDK 155/157.1 跟手,toast「验证成功,正在为您登录」 +- VerifyErr×2(live_155342/161204):solve 分数不差(3.3/2.8)但**视觉混合不像** + —— 是候选选错(s=0.7 网格下边界假峰等),不是差几 px + +测试脚手架教训:离线验证必须传 4 通道 mark(IMREAD_UNCHANGED);丢 alpha 会 +退化成整方块边界 → score=nan + 左边缘假候选(nan 参与 min(key=refined) 比较行为未定义)。 + +### 结论与下一步 + +- VerifyErr 主要由**候选选择错误**贡献;尺度精修解决其中"真尺度落在步间"的部分, + 并立即产生一次机器 PASS; +- 剩余 VerifyErr 的两题 solve 视觉都不像 → 提升方向是**多候选质量评估/换题** + (视觉不像宁可 refresh),而非继续调拖动; +- 单号 PASS 后 60s 再战立即 VerifyErr:同一账号短间隔第二次挑战行为分不足, + 需要更长冷却或换号。 diff --git a/docs/retrospective.md b/docs/retrospective.md new file mode 100644 index 0000000..0fc2bac --- /dev/null +++ b/docs/retrospective.md @@ -0,0 +1,157 @@ +# 项目复盘:抖音「拖动重叠」验证码离线求解与自动化通过 + +> 本文是整个项目的经验总复盘:任务、四个阶段的演进、决定性发现、 +> 踩坑清单、方法论沉淀与未竟事项。细节以各专题文档为准 +>(索引见 [README.md](README.md))。 + +## 1. 任务与最终状态 + +**任务**:给定验证码大图(552×344)与 mark 小图(110×110 RGBA), +离线求出 mark 应拖动重叠的目标区域偏移;进一步在浏览器里自动完成 +「触发 → 采题 → 求解 → 拖动 → 通过」闭环。 + +**最终状态**: + +| 层面 | 状态 | +| --- | --- | +| 离线求解(captchas/ 17 组样本) | ✅ 方向感知倒角法 10/10 精确命中,`src/solve.py` 交付 | +| 线上求解(URL 采题) | ✅ tip_y 锚定后 8 题 7 中(1 题差 1px 出容差) | +| 拖动位置换算 | ✅ 实测校准(按钮 1:1 带 mark,`x × 340/552`) | +| 拟人轨迹生成 | ✅ 三要素路径(非直线/非匀速/过冲回拉),`try/human_drag.py` | +| 行为风控(5014) | ✅ 定位关键指纹(CDP pressure=0)并修复(force=0.5) | +| 端到端一次通过 | ⏸ 被本机 IP 深度频控(5009)阻塞,需换环境冷启动验证 | + +## 2. 四个阶段的演进 + +### 阶段一:离线求解方法调研(A → L) + +从 RGB 模板匹配(A/A2)出发,历经 SIFT(B)、旋转 NCC(C)、倒角(D/E)、 +轮廓匹配(F)、各类分割(G–K),共 12 条路线全部失败或受限后, +才确认两条**决定性事实**(详见 [findings](../try/findings.md)、[experiments](experiments.md)): + +1. **mark 的 RGB 是"捐赠补丁"**——内部是场景纹理,与洞内内容无像素关系 + (掩码 NCC 全图 ≤0.57),一切 RGB/灰度模板匹配原理上不可行; +2. **唯一可靠信号是 alpha 轮廓 + 尺度 + 旋转**——洞是叠加在照片上的实心 + 暗色覆盖物,形状=mark 的 alpha 轮廓,尺度≈1.0、旋转≈0;干扰项是同形的 + 缩放/旋转实例。 + +最终方案 L:方向感知倒角(9 法向桶 × 多尺度)+ 洞内部特征(边缘密度、 +内-环亮度差)+ 局部旋转扫描,17 组样本 10/10 精确命中。 + +**教训**:12 条失败路线里没有一条是"实现 bug",全是**信号假设错误**。 +早期就该做"掩码 NCC 上限"这类决定性实验先证伪 RGB 路线,而不是逐个换实现。 + +### 阶段二:浏览器触发与样本采集 + +- 抖音页面**预加载**验证码 iframe(display:none),「iframe 存在 ≠ 触发」, + 判定要看 `offsetWidth > 0`; +- wasm/GPU 渲染让 `` 与截图法失效,但**图片 URL 会正常发 HTTP 请求** + → 网络层抓 `captcha/get` 响应 + 下载 `url1/url2` 即得与离线同规格的样本对; +- 最可靠的触发法:密码登录弹窗(错误密码也必弹验证码); +- **tip_y 服务端真值**:`question.tip_y × 2 = 缺口顶 y`(mark 画布顶坐标系)。 + +### 阶段三:拖动闭环与行为风控(HOOK 路线) + +闭环管线(`try/auto_solve_drag.py`):点刷新 → 采 get → solve → +拟人路径 → CDP 拖动 → 读 verify,get→verify 全程 <8s(challenge 有效期约 60–90s)。 + +拟人轨迹三要素(`try/human_drag.py`):贝塞尔弓形骨架+高斯抖动(非直线)、 +三段速度结构(非匀速)、过冲后回拉瞄准。但最初 CDP 拖动仍全部 5014。 + +SDK 逆向(webmssdk/bdms/captcha.js 反混淆)确认:mousemove 入列规则、 +X-Bogus 行为位(kMoveFast=16 等)、`isTrusted` 采集、captchaBody 在 XHR.send +前已 wasm 加密。**CDP 事件确实进入了 SDK 缓冲且 isTrusted=true**——问题不在 +事件送达,在事件属性。 + +### 阶段四:决定性突破与 solve 增强 + +1. **pressure 指纹**:CDP 缺省产生的 MouseEvent `pressure=0`,W3C 规范里 + 真鼠标恒 0.5。三个鼠标事件全加 `force:0.5` 后,错误码从 5014(行为拒) + 稳定变为 VerifyErr(位置判定被执行)——行为闸门通过。 +2. **错误码语义分层**(多次连线实验归纳): + `5014 行为拒` → `VerifyErr 位置判了但错` → `5009 频控(压住一切)` → + `NotFoundChallengeId challenge 过期`。**任何改动的效果判定都必须在频控 + 冷却后做单次干净尝试**,连环重试的 5014/5009 是无效信号。 +3. **拖动映射实测**:按钮 1:1 带动 mark 预览;mark 初始相对大图 + `(0, tip_y×2)`(每题垂直自动对齐,拖动只控 x);拖动距离 = `solve.x × 340/552`。 +4. **线上分布漂移与 tip_y 锚定**:线上 URL 题的覆盖物是**亮白半透明贴片** + (离线样本是暗色洞),方法 L 分数从 1–3 恶化到 3.6–7.7。实验发现亮度项 + 在亮贴片题上是反作用,而服务端免费下发的 `tip_y` 是硬真值——把它做成 + y 锚(±8px)在候选中选精修分最低者:离线 10/10 不回归,线上 8 题 7 中, + 3 个原来的错误/AMBIGUOUS 全部修正。已落地 `solve(big, mark, tip_y=...)`。 + +## 3. 踩坑清单(最有复用价值) + +**图像算法**: + +- mark RGB 与洞内容无关,别在 RGB 匹配上浪费时间——先用上限实验证伪信号; +- `TM_CCORR_NORMED` 带 mask 在边界产生 inf,要手写 filter2D 掩码 NCC; +- 倒角会被密纹理击败,必须加方向约束 + 洞内部特征; +- `np.arange` 浮点累积误差参与区间比较前先 `round(s,3)`。 + +**CDP / 浏览器自动化**: + +- `Input.dispatchMouseEvent` 缺省 `pressure=0` 是硬指纹,拖动类风控必补 `force:0.5`; +- `button:"left"` 与 `buttons:0` 同时出现(矛盾状态)会毒化 SDK 拖动注册, + verify 根本不发出——无按键时用 `button:"none"`; +- 按下前不要发"带着 left 键的 hover",按下前后 `buttons` 状态要严格一致; +- 验证码「点刷新」不重建 iframe → iframe 内注入的 XHR hook 持续有效, + 比 netcap 的 Network 域 attach(时机不稳)可靠得多; +- 验证通过后 iframe 自毁,判断通过与否最硬的信号是 `/json/list` 里 rmc iframe 消失。 + +**风控对抗**: + +- 5009 频控阈值苛刻(几十次尝试/小时后窗口 >20 分钟),实验要"省着打", + 低质量题(solve 分差)宁可跳过也不出手; +- 错误码会互相掩盖:频控期看到 5014 不代表行为判定就是这个结果。 + +## 4. 方法论沉淀 + +1. **先证伪信号,再写实现**:RGB 路线若有早期的"掩码 NCC 上限"实验, + 方法 A–K 的大半工作量可以省掉; +2. **无真值时用交叉验证建锚**:SIFT 可用样本、bbox 与 alpha 尺寸一致性、 + 人工目检候选可视化;线上则直接用服务端 tip_y 当真值; +3. **服务端下发的一切字段都是潜在真值**(tip_y 是免费的 y 答案); +4. **错误响应是免费的判层探针**:5014/VerifyErr/5009 的分层让"行为关 + 过没过、位置关过没过"可独立观测; +5. **离线评估 ≠ 线上分布**:覆盖物样式一变(暗→亮),离线 10/10 的方法 + 也会跑飞,线上必须保留否决器(tip_y 一致性检查)。 + +## 5. 未竟事项 + +1. **端到端一次通过未闭环**:行为关(force=0.5)与 solve(tip_y 锚定) + 都已各自验证,但本机 IP 已进深度频控,"冷启动单次拖动通过"需换环境 + (新 IP / 无痕 profile)跑 `try/solo_attempt.py` 验证; +2. **AMBIGUOUS 题处理**:solve 置信度低的题目前只能跳过,可积累样本 + 校准"可信分数"阈值或引入第二方法仲裁; +3. **captchaBody 明文结构**:wasm 加密未破解,若 pressure 修复后仍被 + 行为层拒绝,需回退到 hook SDK 内部轨迹采集(wasm 前的 JS 层)注入轨迹。 + +## 6. 交付物与文档索引 + +| 交付物 | 位置 | +| --- | --- | +| 求解 API(含 tip_y 锚定) | `src/solve.py` | +| 核心算法(方法 L) | `src/method_l_shape.py` | +| 结果验证工具 | `src/verify_result.py` | +| 拟人路径生成 | `try/human_drag.py` | +| 自动闭环 / 单次尝试 | `try/auto_solve_drag.py` / `try/solo_attempt.py` | +| 网络层采集 | `try/captcha_net_capture.py` | + +### 线上闭环最终状态(2026-05-16) + +- **位置层**:flatness 方法经真人 GT 实证系统性偏差后禁用(`FLAT_DISABLED`), + tip_y 锚定 chamfer 为唯一选点路径(3 个可信 GT 全中);离线 9/10 保持; +- **输入层**:CDP 合成事件、事件属性指纹、xdotool OS 硬件级鼠标、真人轨迹 + 重放(含 0.7s 终点停顿修复)全部排除——不是根因; +- **触发层**:清 cookie 即解限流(无需等待)、错误正则去"验证码登录"误报、 + 清 cookie 后必须 Page.navigate 回站; +- **VerifyErr 收敛(2026-09-15 深夜)**:尺度精修上线后**首次机器 PASS** + (live_160548,s=1.0375 精修值,code=200「验证成功,正在为您登录」)。 + 社区资料确认 VerifyErr 语义 = 缺口距离错;剩余 VerifyErr 案例视觉确证为 + 候选整体选错(非小偏差)→ 后续方向是多候选质量评估 / 换题,而非拖动调参。 + 「拖动不跟手」指标作废(post_pos 读取晚于 SDK 重置滑块)。 + +专题文档:[solution.md](solution.md)(算法与 API)、 +[experiments.md](experiments.md)(方法演进)、 +[browser-automation/](browser-automation/)(触发、采集、拖动、CDP 经验)。 diff --git a/docs/solution.md b/docs/solution.md index 001f6dc..414448b 100644 --- a/docs/solution.md +++ b/docs/solution.md @@ -124,6 +124,80 @@ result = solve(big_image_b64, mark_image_b64) # 支持 dataURI 前缀 - 洞叠在深色照片上时"内-环亮度差"约束减弱,可提高方向倒角权重; - 若验证码改用亮色覆盖物,需要把亮度差项改为双向(|内-环|)并重标权重。 +## 线上增强:tip_y 锚定与 flatness 贴片检测(2026-05-15) + +线上实测发现题目分布漂移:覆盖物从离线样本的暗色洞变为**亮白半透明贴片**, +方法 L 分数从 1–3 恶化到 3.6–7.7,且出现假峰(chamfer 精修分 2.6 的雪枝纹理 +压过真缺口 8.3)—— 边界/纹理特征在亮贴片雪景题上完全失灵。 + +两阶段解决: + +### 1. 坐标系修正(bug 修复) + +服务端 `question.tip_y×2` 是**画布坐标系**(mark 全图左上)缺口顶 y 真值, +而求解器内部候选 `e.y` 是 alpha-bbox 左上 y,两者相差 `bbox_y0 × scale` +(实测 ≈9px)。不换算会把真候选推出 ±8px 锚窗、错误候选反而入选。 +换算关系(由离线 GT 实证):**canvas = bbox − bbox_y0×s**。 + +### 2. flatness 贴片检测(线上新特征,决定性) + +亮白半透明贴片的物理特征:**把盖住的背景“贴平”** —— 贴片区域内纹理方差 +远低于周围。定义 flatness = 掩码内灰度 std / 环形外灰度 std: + +- 线上真缺口 flatness 实测 **0.04–0.28**(live_145400 GT 位置 0.056); +- 同图假峰(雪枝纹理)0.49–0.67,区分度巨大; +- 内部纹理 zNCC、亮度抬升等其它特征在此类题上全部失效(实测)。 + +求解流程(tip_y 提供时):各尺度在 y 条带内用 filter2D 向量化扫描 flatness, +取画布 y 落在锚窗(±8px)内的最低值位置;flatness ≤ 0.30 判 OK(method += "flatness")。无匹配或未提供 tip_y → 回退 chamfer 路径(离线逻辑不变)。 + +**验证结果**: + +- 线上 batch 8/8 全 OK(此前 3 道 AMBIGUOUS 全修复),dy ≤ 8 全部满足; +- live_145400(chamfer 假峰题)flatness 命中 (407,64),与 IoU 亚像素实证 + GT (412,68) 差 (5,4)px; +- 离线 10 题无 tip_y 走原逻辑,9/10 保持(4db94793 为历史已知边界)。 + +`solve(big, mark, tip_y=...)` 返回新增 `method` 字段;score 量纲随 method +变化(flatness 为 0–1 比值,chamfer 为 px 分)。 + +### 3. flatness 路径最终降级为禁用(2026-05-15 晚,真人 GT 实证) + +flatness 在线批量指标全绿,但**位置真值校准暴露系统性偏差**。用真人手拖 +(轨迹录制器采样 down→up 位移)拿到 4 个真值: + +| 题 | flatness | chamfer(tip_y 锚定) | 真人 GT | 判定 | +| --- | --- | --- | --- | --- | +| live_165204 | — | 179 | 177 | chamfer ✓(真人 PASS) | +| live_172458 | 433 (s=0.70) | 388 | 388 | flatness +45px ✗ | +| live_173321 | 209 (s=0.825) | 391 | 391 | flatness −182px ✗ | +| live_180227 | 266 (s=0.95) | 257 | (用户拖偏,不采信) | — | + +结论:**chamfer(tip_y 锚定 + refined 排序)3/3 命中(dx=0/0/2), +flatness 每次都大幅偏移**。平坦区特征在雪景题上会吸到贴片内部/ +天空等大平坦区,且可与同样为假的弱 chamfer 候选互相“掩护” +(交叉验证被穿透,live_173321 实测)。 + +处理:`FLAT_DISABLED = True` 禁用 flatness 选点(`flatness_scan` +函数保留供参考);主路径 = tip_y 锚定 chamfer。采题侧把 +“flatness/chamfer 共识”作为加分项但不作硬依赖。 + +同时期的输入层排除(详见 experiments.md):CDP 合成指纹、事件指纹、 +时序积压均被 xdotool 硬件输入 + 60Hz 样条加密重放排除—— +**此前所有失败案例事后看都是位置错,不存在独立的“输入指纹拒”**。 + +### 4. 尺度精修 + 首次机器 PASS(2026-09-15 深夜) + +SCALES 网格步长 0.025,真尺度落在步间时轮廓对齐可偏 5-15px —— 正是 VerifyErr +(社区资料确认其语义 = 缺口距离错,非轨迹问题)的量级。修法:对入选 OK 候选在 +s±0.0375(步长 0.0125)重扫 + ±6px 窗口局部最优,取 rotation_scan refined 最低者。 + +- GT live_165204:179 → 176(真人 177,Δ −1);离线回归 9/10 保持 +- **机器 PASS**:live_160548 x=255 **s=1.0375**(精修值,网格外),拖 157.1px → code=200 +- 剩余 VerifyErr 案例视觉确证为候选整体选错(如 s=0.7 网格下边界假峰), + 方向:多候选质量评估 / 不像就 refresh 换题 + ## 复现 ```bash diff --git a/pyrightconfig.json b/pyrightconfig.json deleted file mode 100644 index df535fa..0000000 --- a/pyrightconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "venvPath": ".", - "venv": ".venv", - "extraPaths": [".venv/lib/python3.13/site-packages", "src", "try"], - "pythonPath": ".venv/bin/python" -} diff --git a/src/method_l_shape.py b/src/method_l_shape.py index f17a6d1..c350f5a 100644 --- a/src/method_l_shape.py +++ b/src/method_l_shape.py @@ -25,15 +25,68 @@ OUT = ROOT / "src" / "out" / "L" OUT.mkdir(parents=True, exist_ok=True) NB = 9 # 法向方向桶数(每桶 20 度) -SCALES = np.arange(0.85, 1.151, 0.025) # 目标尺度约 1.0(洞与 mark 同尺寸) +SCALES = np.arange(0.70, 1.151, 0.025) # 线上实测目标尺度可低至 0.775 W_EDGE, W_DARK = 20.0, 0.5 # 内部边缘密度 / 亮度差惩罚权重 -TOP_K = 5 +TOP_K = 8 MAX_DTP = 10.0 # 倒角距离截断 ROT_STEP = 10.0 # 旋转扫描步长(度) SHIFT = 3 # 旋转扫描平移半径(px) ROT_TOL = 12.0 # 目标允许的旋转角 S_LOW, S_HIGH = 0.96, 1.05 # 目标尺度门限(444d/4db9/41ac 均实测 s=1.00) TIE_TOL = 0.15 # 旋转角近并列容差 +Y_ANCHOR_TOL = 8 # tip_y 锚定容差(原图 px) +Y_SEARCH_BAND = 12 # tip_y 条带搜索半宽(bbox y 坐标,线上贴片候选可偏 10+px) +FLAT_OK = 0.30 # flatness 阈值:低于此值认为找到贴片(线上白贴片实测 0.04-0.2) +FLAT_XCHECK_PX = 30.0 # flatness 与 chamfer 交叉验证距离(px);真人实测假阳性可偏 45px +FLAT_S_MIN = 0.80 # flatness 允许的最低尺度(小尺度平坦匹配全为假阳性) +FLAT_DISABLED = True # 真人 GT 实证 flatness 系统性偏差(+45/-182/+110px),禁用 + + +def flatness_scan(d, s, yc_bb=None): + """线上白贴片检测:贴片把盖住的背景"贴平"(内部 std << 环形 std)。 + 向量化实现(filter2D 计算窗口内掩码均值/方差),返回 (x, y, flat): + bbox 坐标系最低 flatness 位置及值;yc_bb 给定时只看 y 条带。""" + amc = d["am"] + inner, ring = d["inner"], d["ring"] + h, w = round(amc.shape[0] * s), round(amc.shape[1] * s) + H, W = d["shape"] + if h >= H or w >= W or h < 8 or w < 8: + return None + try: + bi = cv2.resize(inner.astype(np.float32), (w, h), interpolation=cv2.INTER_AREA) + br = cv2.resize(ring.astype(np.float32), (w, h), interpolation=cv2.INTER_AREA) + n_i, n_r = float(bi.sum()), float(br.sum()) + if n_i < 50 or n_r < 50: + return None + gf = d["grayf"] + sum_i = crop_full(cv2.filter2D(gf, -1, bi, borderType=cv2.BORDER_CONSTANT), w, h, H, W) + sum_i2 = crop_full(cv2.filter2D(gf * gf, -1, bi, borderType=cv2.BORDER_CONSTANT), w, h, H, W) + sum_r = crop_full(cv2.filter2D(gf, -1, br, borderType=cv2.BORDER_CONSTANT), w, h, H, W) + sum_r2 = crop_full(cv2.filter2D(gf * gf, -1, br, borderType=cv2.BORDER_CONSTANT), w, h, H, W) + except cv2.error: + return None + var_i = np.maximum(sum_i2 / n_i - (sum_i / n_i) ** 2, 0.0) + var_r = np.maximum(sum_r2 / n_r - (sum_r / n_r) ** 2, 0.0) + std_i = np.sqrt(var_i) + std_r = np.sqrt(var_r) + with np.errstate(divide="ignore", invalid="ignore"): + flat = np.where(std_r > 1e-6, std_i / np.maximum(std_r, 1e-6), np.inf) + flat[~np.isfinite(flat)] = np.inf + if yc_bb is not None: + lo, hi = max(0, yc_bb - Y_SEARCH_BAND), min(flat.shape[0], yc_bb + Y_SEARCH_BAND + 1) + if lo >= hi: + return None + band = np.full(flat.shape, np.inf, np.float32) + band[lo:hi] = flat[lo:hi] + flat = band + try: + y0, x0 = np.unravel_index(int(np.argmin(flat)), flat.shape) + f = float(flat[y0, x0]) + if not np.isfinite(f): + return None + return int(x0), int(y0), f + except (ValueError, TypeError): + return None def files_for(prefix): @@ -76,7 +129,8 @@ def setup(big, mark): mx = cv2.Sobel(am.astype(np.float32), cv2.CV_32F, 1, 0, ksize=3) my = cv2.Sobel(am.astype(np.float32), cv2.CV_32F, 0, 1, ksize=3) mang = np.degrees(np.arctan2(my, mx)) % 180.0 - return dict(big=big, gray=gray, am=am, bnd=bnd, inner=inner, ring=ring, + return dict(big=big, gray=gray, grayf=gray.astype(np.float32), + am=am, bnd=bnd, inner=inner, ring=ring, dts=dts, mang=mang, bbox=(x0, y0), edges=(edges > 0), shape=(gray.shape[0], gray.shape[1])) except Exception as e: @@ -188,9 +242,13 @@ def rotation_scan(d, pts, angs, w, h, x, y): return None -def solve_pair(big, mark): +def solve_pair(big, mark, tip_y=None): """纯函数:给定大图与 mark 图(BGR/BGRA ndarray),返回求解结果。 + tip_y:服务端 question.tip_y(可选)。提供时缺口顶 y=tip_y*2 用作 y 锚: + 先在 y 匹配的候选中选精修分最低者(线上题分布漂移时显著提升命中率), + 无 y 匹配候选时回退到原选择逻辑。 + 返回 dict: - x, y : mark 画布左上角应放置的位置(即拖动目标偏移) - scale, rot : 目标尺度与旋转角(rot 已归一到 [-90,90)) @@ -203,12 +261,25 @@ def solve_pair(big, mark): d = setup(big, mark) if d is None: return None + # tip_y 提供时:候选搜索限制在真 y 条带内(画布 y=tip_y*2 → bbox y≈y_tip-by0*s)。 + # 线上亮贴片信号弱,全图粗筛的候选常偏出真 y 十几 px,只靠事后挑选不够。 + y_tip = int(tip_y) * 2 if tip_y is not None else None + by0 = d["bbox"][1] cands = [] for s in SCALES: s = round(float(s), 3) score, w, h, ptset = score_at_scale(d, s) if score is None: continue + if y_tip is not None: + yc = y_tip + round(by0 * s) + lo, hi = max(0, yc - Y_SEARCH_BAND), min(score.shape[0], yc + Y_SEARCH_BAND + 1) + if lo >= hi: + continue + score = score.copy() + mask = np.full(score.shape, np.inf, np.float32) + mask[lo:hi] = score[lo:hi] + score = mask for v, x, y in nms_take(score, 3, int(0.45 * max(w, h))): cands.append((v, s, x, y, w, h, ptset)) if not cands: @@ -217,6 +288,7 @@ def solve_pair(big, mark): kept = [] for c in cands: _, _, x, y, w, h, _ = c + # 半径去重(保留多尺度代表;正确性由 refined 排序保证) cx, cy = x + w / 2.0, y + h / 2.0 if all(math.hypot(cx - (q[2] + q[4] / 2.0), cy - (q[3] + q[5] / 2.0)) > 0.6 * max(w, h) for q in kept): @@ -237,13 +309,97 @@ def solve_pair(big, mark): return None ok = [e for e in enriched if abs(e["rot"]) <= ROT_TOL and S_LOW <= e["scale"] <= S_HIGH] - if ok: + bx0, by0 = d["bbox"] + # flatness 路径已禁用(FLAT_DISABLED):4 个真人 GT 中 3 个由 chamfer 命中, + # flatness 每次都偏(+45/-182/+110px)——平坦区特征在雪景题上系统性不可信。 + # 保留 flatness_scan 函数供参考,但不再参与选点。 + flat_hit = None + if (not FLAT_DISABLED) and y_tip is not None: + flat_results = [] + for s in SCALES: + s = round(float(s), 3) + if s < FLAT_S_MIN: + continue + yc_bb = y_tip + round(by0 * s) + fr = flatness_scan(d, s, yc_bb) + if fr is None: + continue + x0, y0, f = fr + # 画布 y 必须落在锚窗内(canvas = bbox - by0*s) + if abs((y0 - by0 * s) - y_tip) > Y_ANCHOR_TOL: + continue + flat_results.append((f, s, x0, y0)) + if flat_results: + flat_results.sort() + # 交叉验证:只与强 chamfer 候选(refined 前 2 名)比,且距离受限。 + # 弱候选(如 s=0.7 假峰)会“掩护”flatness 假阳性(live_173321 实测) + strong = sorted(enriched, key=lambda e: e["refined"])[:2] + def near_chamfer(x0, y0, s_f): + if not strong: + return True # 无 chamfer 候选可比对时信任 flatness + fx_canvas = x0 - round(bx0 * s_f) + fy_canvas = y0 - round(by0 * s_f) + return any(math.hypot(fx_canvas - (e["x"] - round(bx0 * e["scale"])), + fy_canvas - (e["y"] - round(by0 * e["scale"]))) + <= FLAT_XCHECK_PX for e in strong) + for f, s, x0, y0 in flat_results: + if f <= FLAT_OK and near_chamfer(x0, y0, s): + flat_hit = dict(scale=s, x=x0, y=y0, flat=f) + break + if flat_hit is not None: + s = flat_hit["scale"] + off = (flat_hit["x"] - round(bx0 * s), flat_hit["y"] - round(by0 * s)) + return dict(x=off[0], y=off[1], scale=s, rot=0.0, + score=round(flat_hit["flat"], 3), confidence="OK", + method="flatness", candidates=enriched) + anchored = None + if y_tip is not None: + # e.y 是 alpha-bbox 左上 y;tip_y*2 是画布坐标系(mark 全图左上)真值, + # 需换算到 bbox 坐标系再比对(线上实测:不换算会把真候选推出窗口) + near = [e for e in enriched + if abs((e["y"] - round(d["bbox"][1] * e["scale"])) - y_tip) + <= Y_ANCHOR_TOL] + if near: + anchored = min(near, key=lambda e: e["refined"]) + if anchored is not None: + target = anchored + confidence = "OK" + elif ok: target = min(ok, key=lambda e: e["refined"]) confidence = "OK" else: target = min(enriched, key=lambda e: (abs(e["rot"]), abs(e["scale"] - 1.0))) confidence = "AMBIGUOUS" - bx0, by0 = d["bbox"] + # 尺度精修:SCALES 步长 0.025,若真尺度落在步间,轮廓对齐会有 5-15px 的 + # x 偏差(VerifyErr 量级)。在入选候选 ±0.04 范围内以 0.0125 步长重扫, + # 取 refined 最低的 (s, dx, dy)。仅对 OK 候选做,AMBIGUOUS 本身不可信。 + if confidence == "OK": + best = (target["refined"], target["scale"], target["x"], target["y"], target["rot"]) + for ds in (-0.0375, -0.025, -0.0125, 0.0125, 0.025, 0.0375): + s2 = round(target["scale"] + ds, 4) + if not (S_LOW <= s2 <= S_HIGH): + continue + score2, w2, h2, ptset2 = score_at_scale(d, s2) + if score2 is None or ptset2 is None: + continue + # 在原位置 ±6px 窗口内找局部最优(score 图的 x/y 是 bbox 左上角坐标) + x_lo, x_hi = max(0, target["x"] - 6), min(score2.shape[1], target["x"] + 7) + y_lo, y_hi = max(0, target["y"] - 6), min(score2.shape[0], target["y"] + 7) + win = score2[y_lo:y_hi, x_lo:x_hi] + if win.size == 0: + continue + iy, ix = np.unravel_index(np.argmin(win), win.shape) + x2, y2 = x_lo + int(ix), y_lo + int(iy) + scan2 = rotation_scan(d, ptset2[0], ptset2[1], w2, h2, x2, y2) + if scan2 is None: + continue + if scan2["refined"] < best[0]: + best = (round(float(scan2["refined"]), 3), s2, + x2 + scan2["dx"], y2 + scan2["dy"], + round(float(wrap90(scan2["rot"])), 1)) + if best[0] < target["refined"]: + target = dict(scale=best[1], x=best[2], y=best[3], rot=best[4], + refined=best[0]) s = target["scale"] off = (target["x"] - round(bx0 * s), target["y"] - round(by0 * s)) return dict(x=off[0], y=off[1], scale=s, rot=target["rot"], diff --git a/src/solve.py b/src/solve.py index 71bc639..913a7d6 100644 --- a/src/solve.py +++ b/src/solve.py @@ -2,7 +2,7 @@ 用法(库): from solve import solve - result = solve(big_image_b64, mark_image_b64) + result = solve(big_image_b64, mark_image_b64, tip_y=tip_y) # result["distance_px"] 即需要拖动的水平像素值 用法(命令行,参数为文件路径或 base64 串): @@ -14,9 +14,16 @@ 若拖动 UI 的 mark 初始位置不在 x=0,请用 x 减去初始 x) - x, y : mark 110x110 画布左上角在大图中应放置的位置 - scale / rot : 目标的尺度与旋转角(rot∈[-90,90)) -- score : 拟合分(越小越可信) +- score : 拟合分(越小越可信)。注意量纲随 method 变化: + method=flatness 时为贴片平坦度比(0-1,<0.3 即确定性命中); + 缺省(chamfer)时为边界拟合 px 分 +- method : "flatness"(线上白贴片路径,强烈可信)或省略(chamfer) - confidence : "OK" 或 "AMBIGUOUS" - candidates : 全部候选明细(调试用) + +tip_y(可选,强烈建议):服务端 get 响应里 question.tip_y × 2 = 缺口顶 y +(原图坐标)。传入后求解器优先在 y 匹配(±8px)的候选中选最优, +线上题分布漂移时可显著提升命中率;不传则回退到纯图像选择逻辑。 """ from pathlib import Path import base64 @@ -40,8 +47,11 @@ def decode_b64(data): return None -def solve(big_b64, mark_b64): - """输入大图与 mark 图的 base64,返回求解结果 dict。""" +def solve(big_b64, mark_b64, tip_y=None): + """输入大图与 mark 图的 base64,返回求解结果 dict。 + + tip_y:服务端 question.tip_y(可选,强烈建议传入)——用作缺口顶 y 锚定。 + """ try: big = decode_b64(big_b64) mark = decode_b64(mark_b64) @@ -49,7 +59,7 @@ def solve(big_b64, mark_b64): return {"ok": False, "message": "图片解码失败"} if mark.ndim == 2 or (mark.ndim == 3 and mark.shape[2] < 4): return {"ok": False, "message": "mark 图缺少 alpha 通道"} - result = solve_pair(big, mark) + result = solve_pair(big, mark, tip_y=tip_y) if result is None: return {"ok": False, "message": "未找到目标区域"} result["ok"] = True diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..90387ec --- /dev/null +++ b/start.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +pi --skill ~/.skills/reverse-skill diff --git a/try/auto_solve_drag.py b/try/auto_solve_drag.py new file mode 100644 index 0000000..c429591 --- /dev/null +++ b/try/auto_solve_drag.py @@ -0,0 +1,221 @@ +"""一条龙自动过验证码:CDP websocket 直连,全程 <45s。 + +流程:轮询最新 net_*_get.json(由 captcha_net_capture.py 落盘) + → 等大图/mark 落盘 → live_solve(tip_y 约束) → 拟人路径 → CDP 鼠标事件拖动 + +前置: + 1. Chrome 带 --remote-debugging-port=9222 + 2. 验证码已弹出(登录页触发法) + 3. try/captcha_net_capture.py 在后台跑(抓 get 响应与图片字节) + +用法: + .venv/bin/python try/auto_solve_drag.py [--max-runs 3] +每轮:点刷新(模拟坐标)→ 等 get → solve → 拖 → 读 verify 结果(从落盘 JSON)。 +""" +import asyncio +import glob +import json +import os +import sys +import time +import urllib.request +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parent)) +sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src")) +sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "try")) + +import cv2 # noqa: E402 +import websockets # noqa: E402 + +import importlib.util # noqa: E402 + +from human_drag import gen_human_path # noqa: E402 + + +def _load_local(name: str): + """从本目录加载模块(try/ 名与 Python 关键字冲突,无法静态导入)。""" + spec = importlib.util.spec_from_file_location( + name, Path(__file__).resolve().parent / f"{name}.py") + if spec is None or spec.loader is None: + raise ImportError(f"无法加载模块 {name}") + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + +live_solve = _load_local("live_solve").live_solve + +CDP_HTTP = "http://127.0.0.1:9222" +CAPTURES = Path(__file__).resolve().parent / "captures" +# 验证码 UI 常量(380x384 iframe) +UI_IFRAME = (770, 305) # iframe 左上角视口坐标(如变了用 --iframe-x/y 覆盖) +UI_SLIDER_BTN = (22 + 32, 287 + 20) # 滑块按钮中心(iframe 内坐标) +UI_REFRESH = (30, 355) # 刷新按钮(iframe 内坐标) +SCALE = 340 / 552 # UI 显示 / 原图 + +next_msg_id = [1000] + + +async def cdp(ws, method, params=None, session_id=None): + next_msg_id[0] += 1 + mid = next_msg_id[0] + msg = {"id": mid, "method": method} + if params: + msg["params"] = params + if session_id: + msg["sessionId"] = session_id + await ws.send(json.dumps(msg)) + # 等到对应 id 的响应(跳过事件) + while True: + try: + raw = await ws.recv() + m = json.loads(raw) + except (json.JSONDecodeError, websockets.ConnectionClosed) as e: + raise RuntimeError(f"CDP 消息处理失败: {e}") from e + if m.get("id") == mid: + if "error" in m: + raise RuntimeError(f"{method}: {m['error']}") + return m.get("result", {}) + + +def latest_pair(before_ts): + """找比 before_ts 新的 get.json 与对应图片对,返回 (ts, big, mark, tip_y) 或 None。""" + for gj in sorted(glob.glob(str(CAPTURES / "net_*_get.json")), reverse=True): + ts = os.path.basename(gj).split("_")[1] + if ts <= before_ts: + continue + big = mark = None + for f in glob.glob(f"{CAPTURES}/net_{ts}_*"): + if f.endswith("get.json"): + continue + im = cv2.imread(f, cv2.IMREAD_UNCHANGED) + if im is None: + continue + if im.shape[:2] == (344, 552): + big = f + elif im.shape[:2] == (110, 110): + mark = f + if big and mark: + try: + with open(gj) as fh: + tip = json.load(fh)["data"]["question"]["tip_y"] + except (OSError, KeyError, ValueError): + continue + return ts, big, mark, tip + return None + + +async def drag(ws, session_id, dist_ui, seed): + try: + start_x = float(UI_IFRAME[0] + UI_SLIDER_BTN[0]) + start_y = float(UI_IFRAME[1] + UI_SLIDER_BTN[1]) + except (TypeError, ValueError): + start_x, start_y = 824.0, 612.0 + pts = gen_human_path(dist_ui, duration=2600, seed=seed) + mid_idx = len(pts) * 7 // 10 + cx, cy = start_x, start_y + # force=0.5:CDP 鼠标事件缺省 pressure=0,真鼠标恒 0.5(W3C UI Events), + # 不补齐会被 SDK 行为风控判 5014(见 docs/browser-automation/cdp-drag-force-pressure.md) + await cdp(ws, "Input.dispatchMouseEvent", + {"type": "mousePressed", "x": start_x, "y": start_y, + "button": "left", "buttons": 1, "clickCount": 1, "force": 0.5}, session_id) + await asyncio.sleep(0.3) + for i, (dx, dy, dt) in enumerate(pts): + cx += dx + cy += dy + await asyncio.sleep(dt / 1000.0) + await cdp(ws, "Input.dispatchMouseEvent", + {"type": "mouseMoved", "x": round(cx, 1), "y": round(cy, 1), + "button": "left", "buttons": 1, "force": 0.5}, session_id) + if i == mid_idx: + await asyncio.sleep(0.6) + await asyncio.sleep(0.3) + await cdp(ws, "Input.dispatchMouseEvent", + {"type": "mouseReleased", "x": round(cx, 1), "y": round(cy, 1), + "button": "left", "buttons": 1, "clickCount": 1, "force": 0.5}, session_id) + + +def verify_result(after_time): + """读 verify 落盘 JSON(由 captcha_verify_watch.py / captcha_net_capture.py 写)。""" + cands = sorted(glob.glob(str(CAPTURES / "net_*_verify.json")), reverse=True) + if cands: + try: + mtime = os.path.getmtime(cands[0]) + except OSError: + return None + if mtime > after_time: + try: + with open(cands[0]) as fh: + return json.load(fh) + except (OSError, ValueError): + return None + return None + + +async def main(max_runs: int): + try: + with urllib.request.urlopen(f"{CDP_HTTP}/json/version", timeout=5) as r: + ver = json.load(r) + with urllib.request.urlopen(f"{CDP_HTTP}/json/list", timeout=5) as r: + targets = json.load(r) + except (OSError, ValueError) as e: + print(f"无法连接 CDP {CDP_HTTP}: {e}", file=sys.stderr) + return + async with websockets.connect(ver["webSocketDebuggerUrl"], max_size=64 * 1024 * 1024) as ws: + # attach 主页面 + try: + page = next(t for t in targets if t["type"] == "page" and "douyin.com" in t.get("url", "")) + except StopIteration: + print("未找到 douyin.com 页面", file=sys.stderr) + return + sid = (await cdp(ws, "Target.attachToTarget", + {"targetId": page["id"], "flatten": True}))["sessionId"] + + last_ts = "" + ok = fail = 0 + for run in range(max_runs): + print(f"===== run {run + 1}/{max_runs} =====", flush=True) + # 点刷新(用 CDP 鼠标事件,坐标 = iframe + 刷新按钮) + rx = UI_IFRAME[0] + UI_REFRESH[0] + ry = UI_IFRAME[1] + UI_REFRESH[1] + for typ in ("mousePressed", "mouseReleased"): + await cdp(ws, "Input.dispatchMouseEvent", + {"type": typ, "x": rx, "y": ry, "button": "left", "buttons": 1, + "clickCount": 1}, sid) + t0 = time.time() + # 轮询新样本(最多 12s) + got = None + while time.time() - t0 < 12 and not got: + await asyncio.sleep(0.5) + got = latest_pair(last_ts) + if not got: + print("超时未拿到新题", flush=True) + continue + ts, big_f, mark_f, tip_y = got + last_ts = ts + result = live_solve(big_f, mark_f, tip_y) + if not result: + print("solve 失败", flush=True) + continue + print(f"[{ts}] tip_y={tip_y} x={result['x']} score={result['score']} " + f"(+{time.time() - t0:.1f}s)", flush=True) + await drag(ws, sid, result["x"] * SCALE, seed=result["x"]) + print(f"拖动完成 (+{time.time() - t0:.1f}s)", flush=True) + await asyncio.sleep(4) + vr = verify_result(time.time() - 12) + print("verify:", vr, flush=True) + msg = (vr or {}).get("message", "") + if "通过" in msg: + ok += 1 + break # 通过即止 + fail += 1 + print(f"完成:通过 {ok} / 失败 {fail}", flush=True) + + +if __name__ == "__main__": + import argparse + ap = argparse.ArgumentParser() + ap.add_argument("--max-runs", type=int, default=3) + args = ap.parse_args() + asyncio.run(main(args.max_runs)) diff --git a/try/captcha_net_capture.py b/try/captcha_net_capture.py new file mode 100644 index 0000000..8f8fab6 --- /dev/null +++ b/try/captcha_net_capture.py @@ -0,0 +1,187 @@ +"""网络层验证码图片采集器(CDP websocket 常驻监听)。 + +原理:浏览器级别的 Target.setAutoAttach 自动 attach 所有新 target +(含验证码 iframe),Network 域监听全部请求响应,凡 mime 为 image/* +或 URL 含 captcha/verify 的响应体直接落盘——不经过 DOM/wasm 渲染层, +字节与服务器下发的完全一致。 + +用法(验证码触发前启动,后台常驻): + .venv/bin/python try/captcha_net_capture.py # 默认监听 10 分钟 + .venv/bin/python try/captcha_net_capture.py --minutes 30 + +输出: try/captures/net_<时间戳>_<序号>.(按 Content-Type 扩展名) + + try/captures/net_<时间戳>_get.json(captcha/get 响应原文) +""" +import argparse +import base64 +import json +import sys +import time +import urllib.request +from pathlib import Path + +try: + import websockets +except ImportError: + print("需要 websockets: .venv/bin/pip install websockets", file=sys.stderr) + sys.exit(1) + +CDP_HTTP = "http://127.0.0.1:9222" +OUTDIR = Path(__file__).resolve().parent / "captures" + +INTEREST_URL = ("captcha", "verify", "rmc", "secsdk") +IMAGE_MIME = {"image/png": "png", "image/jpeg": "jpg", "image/webp": "webp", "image/gif": "gif", "image/bmp": "bmp"} + + +class Collector: + def __init__(self, ws): + self.ws = ws + self.msg_id = 1 + self.sessions = {} # sessionId -> None + self.pending = {} # msg_id -> (url, mime) 等待 getResponseBody + self.finished = {} # requestId -> (url, mime) 待取响应体 + self.n_saved = 0 + + async def send(self, method, params=None, session_id=None): + mid = self.msg_id + self.msg_id += 1 + msg = {"id": mid, "method": method} + if params: + msg["params"] = params + if session_id: + msg["sessionId"] = session_id + await self.ws.send(json.dumps(msg)) + return mid + + async def recv_loop(self, deadline): + import asyncio + saved_any_at = time.time() + while time.time() < deadline: + try: + raw = await asyncio.wait_for(self.ws.recv(), timeout=1.0) + except asyncio.TimeoutError: + # 超时窗口内把已完成请求的响应体取回 + await self.drain_bodies() + continue + except websockets.ConnectionClosed: + print("[conn closed]", flush=True) + break + try: + m = json.loads(raw) + except json.JSONDecodeError: + continue + method = m.get("method", "") + + if method == "Target.attachedToTarget": + # 新 target(页面/iframe)出现,对其启用 Network + sid = m["params"]["sessionId"] + ti = m["params"]["targetInfo"] + self.sessions[sid] = ti.get("url", "") + print(f"[attach] {ti.get('type')} {ti.get('url', '')[:80]}", flush=True) + await self.send("Network.enable", session_id=sid) + + elif method == "Network.requestWillBeSent": + u = m["params"]["request"]["url"] + if any(k in u for k in INTEREST_URL): + print(f"[req ] {m['params']['request']['method']} {u[:110]}", flush=True) + + elif method == "Network.responseReceived": + p = m["params"] + u = p["response"]["url"] + mime = (p["response"].get("mimeType") or "").split(";")[0].strip() + interesting = mime in IMAGE_MIME or any(k in u for k in INTEREST_URL) + if interesting: + self.finished[p["requestId"]] = (u, mime) + print(f"[resp] {p['response']['status']} {mime or '?'} {u[:100]}", flush=True) + + elif method == "Network.loadingFinished": + rid = m["params"]["requestId"] + if rid in self.finished: + # 立即拉响应体(需带 sessionId) + info = self.finished.pop(rid) + sid = m.get("sessionId") + if sid: + mid = await self.send("Network.getResponseBody", {"requestId": rid}, session_id=sid) + self.pending[mid] = info + + elif "id" in m and m["id"] in self.pending and "result" in m: + await self.save_body(m, self.pending.pop(m["id"])) + + await self.drain_bodies() + + _body_seq = 100000 + + async def next_body_id(self): + Collector._body_seq += 1 + return Collector._body_seq + + async def drain_bodies(self): + """把已完成请求的响应体真正拉回(发 getResponseBody,响应由 recv_loop 处理)。""" + for rid in list(self.finished.keys()): + info = self.finished.pop(rid) + # 找到该 request 所在 session 的 sessionId(任意已 attach session 均可试) + for sid in self.sessions: + mid = await self.send("Network.getResponseBody", {"requestId": rid}, session_id=sid) + self.pending[mid] = info + break + + async def save_body(self, msg, info): + url, mime = info + result = msg.get("result", {}) + body = result.get("body", "") + if not body: + return + OUTDIR.mkdir(parents=True, exist_ok=True) + ts = time.strftime("%H%M%S") + if result.get("base64Encoded"): + # 二进制:按 mime 保存图片 + ext = IMAGE_MIME.get(mime, "bin") + self.n_saved += 1 + path = OUTDIR / f"net_{ts}_{self.n_saved}.{ext}" + path.write_bytes(base64.b64decode(body)) + print(f"[save] {path.name} ({len(body)} b64, {mime}) <- {url[:80]}", flush=True) + else: + # 文本:captcha/get + captcha/verify 的 JSON 响应全存 + if "captcha/get" in url or "captcha/verify" in url or (body.startswith("{") and ("question" in body or "captcha" in body)): + self.n_saved += 1 + tag = "get" if "captcha/get" in url else "verify" + path = OUTDIR / f"net_{ts}_{tag}.json" + path.write_text(body, encoding="utf-8") + print(f"[save] {path.name} ({len(body)} chars) <- {url[:80]}", flush=True) + print(f" head: {body[:200]}", flush=True) + + +async def main(minutes: float): + import asyncio + try: + ver = json.load(urllib.request.urlopen(f"{CDP_HTTP}/json/version", timeout=5)) + except (OSError, ValueError) as e: + print(f"无法连接 CDP {CDP_HTTP}(Chrome 需带 --remote-debugging-port=9222 启动): {e}", file=sys.stderr) + sys.exit(1) + ws_url = ver["webSocketDebuggerUrl"] + deadline = time.time() + minutes * 60 + async with websockets.connect(ws_url, max_size=64 * 1024 * 1024) as ws: + col = Collector(ws) + # 浏览器级 autoAttach:所有新 target(含未来弹出的验证码 iframe)自动 attach + await col.send("Target.setAutoAttach", { + "autoAttach": True, "waitForDebuggerOnStart": False, "flatten": True, + }) + # 补充 attach 已存在的 target(验证码 iframe 可能已经弹出) + try: + targets = json.load(urllib.request.urlopen(f"{CDP_HTTP}/json/list", timeout=5)) + except (OSError, ValueError): + targets = [] + for t in targets: + if t.get("type") in ("page", "iframe", "webview") and t.get("id"): + await col.send("Target.attachToTarget", {"targetId": t["id"], "flatten": True}) + print(f"[listen] auto-attach + 已存在 target attach({len(targets)}),监听 {minutes} 分钟,Ctrl+C 退出", flush=True) + await col.recv_loop(deadline) + print(f"[done] 共保存 {col.n_saved} 个文件到 {OUTDIR}", flush=True) + + +if __name__ == "__main__": + ap = argparse.ArgumentParser() + ap.add_argument("--minutes", type=float, default=10) + args = ap.parse_args() + import asyncio + asyncio.run(main(args.minutes)) diff --git a/try/captcha_verify_watch.py b/try/captcha_verify_watch.py new file mode 100644 index 0000000..f77ebe3 --- /dev/null +++ b/try/captcha_verify_watch.py @@ -0,0 +1,99 @@ +# 监听 captcha/verify 请求+响应全文(含 postData),落盘 /tmp/verify_captures/ +# 用途:对比真人 vs 自动化拖动的 verify 参数差异 +import asyncio, json, time, urllib.request, os, sys +import websockets + +CDP_HTTP = "http://127.0.0.1:9222" +OUT = "/tmp/verify_captures" + + +def _cdp_json(path: str): + """拉取 CDP HTTP 接口的 JSON;失败返回 None。""" + try: + with urllib.request.urlopen(f"{CDP_HTTP}{path}", timeout=5) as r: + return json.load(r) + except (OSError, ValueError): + return None + + +async def main(minutes: float = 10.0) -> None: + ver = _cdp_json("/json/version") + if not ver or "webSocketDebuggerUrl" not in ver: + print("无法连接 CDP 9222(Chrome 需带 --remote-debugging-port=9222)", file=sys.stderr) + return + try: + os.makedirs(OUT, exist_ok=True) + except OSError as e: + print(f"无法创建输出目录 {OUT}: {e}", file=sys.stderr) + return + + async with websockets.connect(ver["webSocketDebuggerUrl"], max_size=64 * 1024 * 1024) as ws: + msg_id = 10 + + async def send(method, params=None, sid=None): + nonlocal msg_id + msg_id += 1 + m = {"id": msg_id, "method": method, "params": params or {}} + if sid: + m["sessionId"] = sid + await ws.send(json.dumps(m)) + return msg_id + + await send("Target.setAutoAttach", {"autoAttach": True, "waitForDebuggerOnStart": False, "flatten": True}) + for t in (_cdp_json("/json/list") or []): + if t.get("type") in ("page", "iframe"): + await send("Target.attachToTarget", {"targetId": t["id"], "flatten": True}) + + pend = {} + deadline = time.time() + minutes * 60 + print("watching verify (full)...", flush=True) + while time.time() < deadline: + try: + raw = await asyncio.wait_for(ws.recv(), timeout=1) + m = json.loads(raw) + except asyncio.TimeoutError: + continue + except json.JSONDecodeError: + continue + if m.get("method") == "Target.attachedToTarget": + await send("Network.enable", sid=m["params"]["sessionId"]) + meth = m.get("method", "") + if meth == "Network.requestWillBeSent" and "captcha/verify" in m["params"]["request"]["url"]: + ts = time.strftime("%H%M%S") + rec = {"ts": ts, "url": m["params"]["request"]["url"][:300], + "method": m["params"]["request"]["method"], + "post": m["params"]["request"].get("postData", "")} + rid = m["params"]["requestId"] + body_id = await send("Network.getResponseBody", {"requestId": rid}, sid=m.get("sessionId")) + rec["req_id"] = rid + rec["url_full"] = m["params"]["request"]["url"] + pend[body_id] = rec + # 同时存下请求体全文(含 captchaBody 轨迹密文) + path_req = f"{OUT}/verify_{ts}_req.json" + try: + with open(path_req, "w") as f: + json.dump(rec, f, ensure_ascii=False, indent=1) + except OSError as e: + print(f"落盘失败 {path_req}: {e}", file=sys.stderr) + print(f"[{ts}] VERIFY-REQ post_len={len(rec['post'])}", flush=True) + elif "id" in m and m["id"] in pend and "result" in m: + rec = pend.pop(m["id"]) + rec["resp"] = m["result"].get("body", "") + path = f"{OUT}/verify_{rec['ts']}.json" + try: + with open(path, "w") as f: + json.dump(rec, f, ensure_ascii=False, indent=1) + except OSError as e: + print(f"落盘失败 {path}: {e}", file=sys.stderr) + print(f"[{rec['ts']}] VERIFY-RESP: {rec['resp'][:150]}", flush=True) + + +if __name__ == "__main__": + try: + minutes = float(sys.argv[1]) if len(sys.argv) > 1 else 10.0 + except ValueError: + minutes = 10.0 + try: + asyncio.run(main(minutes)) + except KeyboardInterrupt: + pass diff --git a/try/captures/net_093135_get.json b/try/captures/net_093135_get.json new file mode 100644 index 0000000..acfb908 --- /dev/null +++ b/try/captures/net_093135_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":62,"host":"","id":"aff62a3a5e38b990b2e2794a2bc6212f92fc183a","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/026610a526b14d61a73995c1287acb1e~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/bfef530e9f754ccebfaaa28a0ad9571d~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/026610a526b14d61a73995c1287acb1e~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/026610a526b14d61a73995c1287acb1e~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/bfef530e9f754ccebfaaa28a0ad9571d~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/bfef530e9f754ccebfaaa28a0ad9571d~tplv-188rlo5p4y-1.png"],"tip_y":58,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_093136_2.jpg b/try/captures/net_093136_2.jpg new file mode 100644 index 0000000..d17f321 Binary files /dev/null and b/try/captures/net_093136_2.jpg differ diff --git a/try/captures/net_093244_verify.json b/try/captures/net_093244_verify.json new file mode 100644 index 0000000..cac68eb --- /dev/null +++ b/try/captures/net_093244_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"NotFoundChallengeId"},"message":"验证超时,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_093245_6.jpg b/try/captures/net_093245_6.jpg new file mode 100644 index 0000000..02be1a4 Binary files /dev/null and b/try/captures/net_093245_6.jpg differ diff --git a/try/captures/net_093245_get.json b/try/captures/net_093245_get.json new file mode 100644 index 0000000..6dd7b6b --- /dev/null +++ b/try/captures/net_093245_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":24,"host":"","id":"6c343a96a4aa52d00810032f5a96bb9b0353dbd9","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/71acd0f4ec1942979aa17911c0b73a1f~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a1bb791042b847f4beaca70a005e6ebc~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/71acd0f4ec1942979aa17911c0b73a1f~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/71acd0f4ec1942979aa17911c0b73a1f~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a1bb791042b847f4beaca70a005e6ebc~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a1bb791042b847f4beaca70a005e6ebc~tplv-188rlo5p4y-1.png"],"tip_y":42,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_093323_get.json b/try/captures/net_093323_get.json new file mode 100644 index 0000000..546c95c --- /dev/null +++ b/try/captures/net_093323_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":1,"host":"","id":"e4d75836bc889874ef1617f8c37e567987ca17a3","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1b73a92ee9844cceac0331f73a73ad4f~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/44c0201ac4b6483990082473bdfbb62b~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1b73a92ee9844cceac0331f73a73ad4f~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1b73a92ee9844cceac0331f73a73ad4f~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/44c0201ac4b6483990082473bdfbb62b~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/44c0201ac4b6483990082473bdfbb62b~tplv-188rlo5p4y-1.png"],"tip_y":32,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_093324_10.jpg b/try/captures/net_093324_10.jpg new file mode 100644 index 0000000..8ac64ab Binary files /dev/null and b/try/captures/net_093324_10.jpg differ diff --git a/try/captures/net_093416_verify.json b/try/captures/net_093416_verify.json new file mode 100644 index 0000000..b7d27f8 --- /dev/null +++ b/try/captures/net_093416_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"检测到您的网络环境较差,请更换网络或者稍后再试[5014]"} \ No newline at end of file diff --git a/try/captures/net_093447_13.jpg b/try/captures/net_093447_13.jpg new file mode 100644 index 0000000..cf0ab5e Binary files /dev/null and b/try/captures/net_093447_13.jpg differ diff --git a/try/captures/net_093447_get.json b/try/captures/net_093447_get.json new file mode 100644 index 0000000..e53dc5b --- /dev/null +++ b/try/captures/net_093447_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":67,"host":"","id":"c1580262dc147875302303acf2fa494ce441be37","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/9abb14fa9b4844e5a35d04dcaaca3abc~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/23eae7b1ecfc42d5ae9453a0ff337e0a~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/9abb14fa9b4844e5a35d04dcaaca3abc~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/9abb14fa9b4844e5a35d04dcaaca3abc~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/23eae7b1ecfc42d5ae9453a0ff337e0a~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/23eae7b1ecfc42d5ae9453a0ff337e0a~tplv-188rlo5p4y-1.png"],"tip_y":43,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_095916_verify.json b/try/captures/net_095916_verify.json new file mode 100644 index 0000000..69441b7 --- /dev/null +++ b/try/captures/net_095916_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"滑动滑块进行验证","error_code":1105,"verify_center_decision_conf":"{\"code\":\"10000\",\"from\":\"shark_admin\",\"type\":\"verify\",\"version\":\"1\",\"region\":\"cn\",\"subtype\":\"slide\",\"ui_type\":\"\",\"detail\":\"keE*21mp9fplTSxKY8S*q18DkqYpVkP45MlpB4X2XX85*BzBekWaTs*Vfq5oNyZg8F-piK4mQvu8lA4znwtcf8U8FgBSYgHoDCXNA8xly5CDnZR8WuRThqSQjUUlHnsQks3SWYBhUEaRUJ-l8uL*Zn6Ixmj*1ILU6526l0sLF3PlTa6w-sM9EBmy-LWclUMLjknhk9THXgM1C4Nc5eEVykE0pZWXivQYj68SpjhtTP41bVwGb9Y5yCWj1NLul2tkXrCQVpFKX6Rj6cYNZsZR3abCbF83s0-JN11KF*7*NTTxAOJ1dpnj8-XqWqb-QkB2qGVbGVsR1HuBtqiIvS5U9v*7Vv1wYULIBE-9KrIjRnHpyPLDncl3Z9zQYf6jndBN\",\"verify_event\":\"tt_user_pwd_login\",\"fp\":\"verify_mtwarf05_T2cF4uRW_4ewx_4A4K_9lxP_FRjbBMt9WYRC\",\"verify_ticket\":\"VTIDEFCZB7MQAWNFHTFJ7RJMGWHUSHBH2PNJ8Z_lf\",\"server_sdk_env\":\"{\\\"idc\\\":\\\"lf\\\",\\\"region\\\":\\\"CN\\\",\\\"server_type\\\":\\\"passport\\\"}\",\"log_id\":\"202609141000077765FE8E5A3D2F25CEDB\",\"is_assist_mobile\":false,\"is_complex_sms\":false,\"identity_action\":\"\",\"identity_scene\":\"\",\"verify_scene\":\"passport\",\"login_status\":0,\"aid\":0,\"replay_data\":{\"x-tt-passport-replay-params\":\"{}\"}}","verify_ticket":"VTIDEFCZB7MQAWNFHTFJ7RJMGWHUSHBH2PNJ8Z_lf"},"message":"error"} \ No newline at end of file diff --git a/try/captures/net_095921_verify.json b/try/captures/net_095921_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_095921_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_095926_verify.json b/try/captures/net_095926_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_095926_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_095931_verify.json b/try/captures/net_095931_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_095931_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_095936_verify.json b/try/captures/net_095936_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_095936_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_095941_verify.json b/try/captures/net_095941_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_095941_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_095947_verify.json b/try/captures/net_095947_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_095947_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_095952_verify.json b/try/captures/net_095952_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_095952_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_095957_verify.json b/try/captures/net_095957_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_095957_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100002_verify.json b/try/captures/net_100002_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100002_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100007_verify.json b/try/captures/net_100007_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100007_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100012_verify.json b/try/captures/net_100012_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100012_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100018_verify.json b/try/captures/net_100018_verify.json new file mode 100644 index 0000000..4e38388 --- /dev/null +++ b/try/captures/net_100018_verify.json @@ -0,0 +1 @@ +{"data":{"app_name":"抖音","captcha":"","desc_url":"","description":"","error_code":0,"expire_time":1789351330,"frontier_params":{"access_key":"d8b2e550d05b7afcfea970017e05bc44","frontier_device":"7657740123052901934","method":1,"product_id":971,"service_id":1024},"is_frontier":true,"qrcode":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIAAQMAAADOtka5AAAABlBMVEX///8AAABVwtN+AAAC2klEQVR42uycPZLqSgyFRTkgZAksZZZmL81LYQmEDij0ymqpf57bd0hu1bX5TjQew0ekknSkbkEIIYQQQgihf10/mjUP+hC52d8vkYs+RJ8yxlPWGwAAAD1APF4NcNGnqOpkL+6af8Re/O8bAACcDXBfI2S66izpz/Xfg86XFFqTPQVZXwAAAPgdMKTMIyKjfy6/AADgqwAid385epWWajYAAAB8BshlnmWmKPNMmSwf1YkAABwZ0Lb/FjOLZ6a7rlVaZKbP/AMAAL4WUGtYX95UF3uKlidF40cCAODAgFSlZfvY09FajFngPGVccvsvV52Gjq8MAACAyEwegjGkWTwwRRLgx4c0ct1LbQAAnADwbjobB4wWTA9zAhb7kXdyAqZ+zwQAAICSmZaci7JlFiabamp51swEAMBZAbHwIlWXv/grI3v2eie/bVulAQAAoIpGH/JX0/+o/2TthWLfzJ8EAIAzAupZTPQ56jGT1spaX/nVNdQAAACQQ7DyD6pqLn8rJakrAADnBViXXz5n31rMZfaWR7VeCwAAAMAeIJ93Kf5BisZqrUy1nArY7ZkAADg4INnH7ZDfuvy5WbFUz15jPxoBAADg1VwMNqOam8rEM405bV6TTLbulAcAgMMDUvsfmzBRpUUvVHb3Pcp0x0sDAABARGPWLU5YSvHSfj09AADA8QHteZfqIEwc3R8bL63TMwEAAKCd/ouXeXni+S5udNE0bFIbAADnAKQ8c2tWLDefK+1/9yAMAAAANqfKYsg/xfTmWfy2WAuYAQA4JWBz8Z6pvRMmD2kW74UAAAAgO1VabI/VE8/KZCvRuOOlAQBwCsDmfqRmYDlVARcrMgAAAPgzYMg3v47NhcizX5BRpSwAAL4BUN0JU5aU4+h+bxMGAAAAm5v70ucq9+zZGAu7uzgAAJwA0LT/1SwmDoX5nTC+Vtbd0QQAAABCCCGEEEII/RX9FwAA//8dSDEKVp+WDwAAAABJRU5ErkJggg==","qrcode_index_url":"https://api.amemv.com/ucenter_web/app/aweme/scan_login/index/douyin_scan_code_login/cn/app/index.html?_pia_=1\u0026hide_nav_bar=1\u0026is_new_login=1\u0026loader_name=forest\u0026next_url=https%3A%2F%2Fapi.amemv.com%2Fpassport%2Fmobile%2Fscan_qrcode%2F\u0026qr_source_aid=6383\u0026scene=\u0026source=\u0026token=69b8d3dcdf195aecdf6520bcd9eba481_hl\u0026verify_reason=\u0026verify_scene=\u0026verify_ticket=\u0026web_app_from=rcode","status":"expired","token":"69b8d3dcdf195aecdf6520bcd9eba481_hl","web_name":"抖音"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100144_verify.json b/try/captures/net_100144_verify.json new file mode 100644 index 0000000..7c6fa90 --- /dev/null +++ b/try/captures/net_100144_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"该账号无法使用密码登录,建议切换其他方式登录。","error_code":1467},"message":"error"} \ No newline at end of file diff --git a/try/captures/net_100316_verify.json b/try/captures/net_100316_verify.json new file mode 100644 index 0000000..05509b5 --- /dev/null +++ b/try/captures/net_100316_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"滑动滑块进行验证","error_code":1105,"verify_center_decision_conf":"{\"code\":\"10000\",\"from\":\"shark_admin\",\"type\":\"verify\",\"version\":\"1\",\"region\":\"cn\",\"subtype\":\"slide\",\"ui_type\":\"\",\"detail\":\"toTgLwS9uO13EtqVaJDHJ-qstyOnPPfOfcAHf6eBuN61SkpAmMqhpVtEa4SO8vz2mm598XJTGCmrvwgvRDn5T1C4Qeq1jFNzKm9q3MRjTkie0B7CcvBvHs8hOY0M3RccOvINVYOPNO2rzyRCcdwiknFgNiPSpzdLEkAUEfdD9r4cRoJQrJDvGeAWm6gIjfm*rs1DSXydXHy1oZyeSn1XsgzCzMSufW9ab8P8KKObQqr2mbsB4DhQafbWRGLMWfwIRHDnvQoTrBSFYVWwLFtaxoGcK*be5haJjgIq5XFQ-jEpM2JfNnj99nuEigLQ7nCt5utlGBCU18jRYOBs1Wy8J2eDta7OplM5SMctGky4sLPzZ9DJ86Z1oHqGrMRUbDJl\",\"verify_event\":\"tt_user_pwd_login\",\"fp\":\"verify_mtwarf05_T2cF4uRW_4ewx_4A4K_9lxP_FRjbBMt9WYRC\",\"verify_ticket\":\"VTIDEFWMPR3Z4QNF6R6Y78Z447YKN7YSR4N9RA_hl\",\"server_sdk_env\":\"{\\\"idc\\\":\\\"hl\\\",\\\"region\\\":\\\"CN\\\",\\\"server_type\\\":\\\"passport\\\"}\",\"log_id\":\"20260914100408EEF5625A1F8DCD833250\",\"is_assist_mobile\":false,\"is_complex_sms\":false,\"identity_action\":\"\",\"identity_scene\":\"\",\"verify_scene\":\"passport\",\"login_status\":0,\"aid\":0,\"replay_data\":{\"x-tt-passport-replay-params\":\"{}\"}}","verify_ticket":"VTIDEFWMPR3Z4QNF6R6Y78Z447YKN7YSR4N9RA_hl"},"message":"error"} \ No newline at end of file diff --git a/try/captures/net_100321_verify.json b/try/captures/net_100321_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100321_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100327_verify.json b/try/captures/net_100327_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100327_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100332_verify.json b/try/captures/net_100332_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100332_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100337_verify.json b/try/captures/net_100337_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100337_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100342_verify.json b/try/captures/net_100342_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100342_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100348_verify.json b/try/captures/net_100348_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100348_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100350_verify.json b/try/captures/net_100350_verify.json new file mode 100644 index 0000000..7c6fa90 --- /dev/null +++ b/try/captures/net_100350_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"该账号无法使用密码登录,建议切换其他方式登录。","error_code":1467},"message":"error"} \ No newline at end of file diff --git a/try/captures/net_100353_verify.json b/try/captures/net_100353_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100353_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100358_verify.json b/try/captures/net_100358_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100358_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100403_verify.json b/try/captures/net_100403_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100403_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100409_verify.json b/try/captures/net_100409_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100409_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100414_verify.json b/try/captures/net_100414_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100414_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100419_verify.json b/try/captures/net_100419_verify.json new file mode 100644 index 0000000..2b6804b --- /dev/null +++ b/try/captures/net_100419_verify.json @@ -0,0 +1 @@ +{"data":{"app_name":"抖音","captcha":"","desc_url":"","description":"","error_code":0,"expire_time":1789351571,"frontier_params":{"access_key":"d8b2e550d05b7afcfea970017e05bc44","frontier_device":"7657740123052901934","method":1,"product_id":971,"service_id":1024},"is_frontier":true,"qrcode":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIAAQMAAADOtka5AAAABlBMVEX///8AAABVwtN+AAAC2klEQVR42uzcMXYiMQyAYfEoKPcIcxSONhwtR8kRKKeYN9pnW5I14IQUWyyTXxUJw0flZ1mSEYIgCIIgCIIgiP89rhrxITKp3st/5/qXiN5lXupzp/7cBgAAMAL8z4t+nPXTXupaPvIp8kdvYsD98RMAAEcDprJCbg2oz130dlbdrbIKlNcrAADATwAtO5MuIufdzmQyAMBvAexfAUya9ykAAIBXQKR5ItPWgHltZyFL83zLepUnAgC8M5CSMd+AGlBWWQE8fftB/QAA4DcDOSzNEymApJ1JrbDwKgAA3hh4qKXVNbPUuvIpKmtRcL54MQAAAOAJEHtzXuS6Rv05mjT1LKSrnYUUAOC4QF1MOUtTtU3Ks7T+JS19EwAAgCHgB5nF0rwKzF4yq8B1bfW2789MAABvD9Qmf6sZp2RMvZZ2yXWB4VgZAABAHHlS/Vk192JcrmNlNhawAQAcEajTY+XIU5/0XsxsH4kRS19lt/PTmQkAAKB3/8uiWyyb2z3XuPLGFgtzND4AAPD+gJx2Q8plL0rpW8/ZtvYlz91/AACAHL4a5RQzmrXN2QoLaZkOViMAwJEA6WtGJJ1srHtjJYL8DAAAwOj43+vPfUbT71TaILPPKwMAHBVoR56YHjv1fo11Mq1haUee26iuDAAAEE0an9H8tIwvzStHZya9BAA4IuDP1UkY3eJS2L5hWY//ad4MAABgPK88SvPSM73jqes33X8AgLcGbGeKVeKn/Dq7b/PKPQbjAwAAAONbZapx32XyQ4798lLkfwAABwSujz+DpL18HGMB2q8hP2dpAAAATzcsbf2ld9tq9N3r61tlAACHANLvI01bTML41f25FwOM2wAAAF4CcSs5Df/vC9PnYccTAOBwgDcse8E5NyxrlgYAAPAVMEjzZjvy2F607i6YCQDAIYHdD++lZMwvhaXZ/VZv+wAAABgBBEEQBEEQBEEQ/z7+BgAA//+F7UMbrdeyuwAAAABJRU5ErkJggg==","qrcode_index_url":"https://api.amemv.com/ucenter_web/app/aweme/scan_login/index/douyin_scan_code_login/cn/app/index.html?_pia_=1\u0026hide_nav_bar=1\u0026is_new_login=1\u0026loader_name=forest\u0026next_url=https%3A%2F%2Fapi.amemv.com%2Fpassport%2Fmobile%2Fscan_qrcode%2F\u0026qr_source_aid=6383\u0026scene=\u0026source=\u0026token=af6118efba5520f3502c3865bce72067_hl\u0026verify_reason=\u0026verify_scene=\u0026verify_ticket=\u0026web_app_from=rcode","status":"expired","token":"af6118efba5520f3502c3865bce72067_hl","web_name":"抖音"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100532_verify.json b/try/captures/net_100532_verify.json new file mode 100644 index 0000000..50abfda --- /dev/null +++ b/try/captures/net_100532_verify.json @@ -0,0 +1 @@ +{"data":{"app_name":"抖音","captcha":"","copywriting":"{\"desc\":\"为保障账号安全,请使用[color=red]「抖音 APP」[/]扫码验证,以确保为本人操作\",\"page_title\":\"身份验证\",\"title\":\"请使用已登录账号的设备扫码\"}","desc_url":"","description":"","error_code":0,"expire_time":1789351644,"frontier_params":{"access_key":"d8b2e550d05b7afcfea970017e05bc44","frontier_device":"7657740123052901934","method":1,"product_id":971,"service_id":1024},"is_frontier":true,"qrcode":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIAAQMAAADOtka5AAAABlBMVEX///8AAABVwtN+AAACzklEQVR42uzcMbLqOgyAYWVSUJ4lZClnabA0lsISKCky0RtblmyI4XFnbnExvyrA4es8smU5QhAEQRAEQRAE8a/Hr0acRWSyj6c8cBH5yV/XGEixAQAA9AD/ekjAstnHxE0FuOXhSa+P/wAAGA1Y8vQ56HlOH64JOEk7fc4FsHkFAADwBuDz71ieqwMAAN8F5Eg/zzlPaclT65/MRgCA7wVimTen7cyPpszkli3zymz833UiAMAnA8323xOQZ6YlAZGZ3qgfAAB8M9DGXAdzZspxzH+6vFWkBgD4YMBXae0u/5b+5YAV2aIYsAIAAPSBPFKsVZat1A9yAlpUr3K8pQF77NDLTAAAgwDSq6VZkrJVmj/jy7d9AAAAeGaKg814zjNTHkjTVEstrXf6DwAwApCjbv+b8/7ClRJBaQs4zQAAAE+BRaOsFgebXjTItTQ/pAEAGBn4bZ5T64Qpi7HJvh1ryjLgLAAAAK+AuvsRiUOaKKA50CnGAQAMA3hfpd536+flmw/oFsu37uk/AACAlDLBqRambdLlaVruxKxlmh46bWUAAKMAU3kuD9ohjebF2BRTy3sv+4VpAACA3opvsudkVu1evXzZVgYA8PFA2uU3xzKWjvwijO2FthjoBQAAgG15Hnr8/bqyattW9qr5HwBgAGCLOlkkoNpWFr37dkNG7novAQAAdrfK4pD/UgG/YRk9ms8K0wAAIwHNWYxvec61kVnq9r97EQYAAGB/q6yWzEK29V/eGXnKAgAYELh/8V5zEcYyk/Ura72GrJ1OGAAAgN17MNrC9BZFNr+u/MY7YQAAPhlo34/0OJnylqc5sum0WAIAAPSBWPFt0WMTZzm3u3dlAACMDGi8KtxaZK71xXveViYCAADwrK5cDzb3sl1XlrrMAwAYFHh88V7MmWYyaRxYyvyqfgAA8M0AQRAEQRAEQRDE34//AgAA//9AniUeTGmGdQAAAABJRU5ErkJggg==","qrcode_index_url":"https://api.amemv.com/ucenter_web/app/aweme/scan_login/index/douyin_scan_code_login/cn/app/index.html?_pia_=1\u0026hide_nav_bar=1\u0026is_new_login=1\u0026loader_name=forest\u0026next_url=https%3A%2F%2Fapi.amemv.com%2Fpassport%2Fmobile%2Fscan_qrcode%2F\u0026qr_source_aid=6383\u0026scene=\u0026source=\u0026token=45e8748c0b5d25dd34a9c3993de34407_lf\u0026verify_reason=\u0026verify_scene=\u0026verify_ticket=\u0026web_app_from=rcode","token":"45e8748c0b5d25dd34a9c3993de34407_lf","web_name":"抖音"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100537_verify.json b/try/captures/net_100537_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100537_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100542_verify.json b/try/captures/net_100542_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100542_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100547_verify.json b/try/captures/net_100547_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100547_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100552_verify.json b/try/captures/net_100552_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100552_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100558_verify.json b/try/captures/net_100558_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100558_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100603_verify.json b/try/captures/net_100603_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100603_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100608_verify.json b/try/captures/net_100608_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100608_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100613_verify.json b/try/captures/net_100613_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100613_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100619_verify.json b/try/captures/net_100619_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100619_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100624_verify.json b/try/captures/net_100624_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100624_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100629_verify.json b/try/captures/net_100629_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_100629_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_100634_verify.json b/try/captures/net_100634_verify.json new file mode 100644 index 0000000..72e91b1 --- /dev/null +++ b/try/captures/net_100634_verify.json @@ -0,0 +1 @@ +{"data":{"app_name":"抖音","captcha":"","desc_url":"","description":"","error_code":0,"expire_time":1789351706,"frontier_params":{"access_key":"d8b2e550d05b7afcfea970017e05bc44","frontier_device":"7657740123052901934","method":1,"product_id":971,"service_id":1024},"is_frontier":true,"qrcode":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIAAQMAAADOtka5AAAABlBMVEX///8AAABVwtN+AAACy0lEQVR42uzdPbKjMAzAcWUoKHOEHCVHC0fLUThCSopMvBPLkgU4H8UWD/JXtQT4beWxJcs8IQiCIAiCIAiC+OtxTh7XLo3Pn/yH0f55FznU5x4AAAAtwC77DDyfkz4N+adT8v9kPKTb8g0AgL0Bp+cIGfp0XY6yUeSYrU4BHVcAAAAfgU5nHhG5lOf8BgDATwEip4ccCyAHHUxl+QYAAPAZ8GWeqDVPcsqU9dU6EQBgy8A8/c9jZioz0yk9V2k1F/qmfgAA8LNAjLzMs0GXR2MBvi1SAwBsGNBV2k0uOh3luvJUVmmZu0ye/kufhq5RVwYAADDgmeTocxVweZJz4aRvb9IAAOwB0Ds55Un3kvJMNf3P8jm/lSsBwyrlAQAAmEd5Lvmgs2rCkK/CVigAwD6B/FYpH4vORZr9hKuzTUfNVRoAAECIvMm/moB0/Wf9Zke7EgCAPQL2XNykmXIxINwIdeV7s5YGAABQqmc6AYW25Lu3BeiVTlI9AMB+ASuZSW0r88Fkbfy2YHs9GgEAAGrKY/UD3YupO57lTExpK3uTMwEAbBvwlKevvWQ6mFJssUyh4CwAAABtIJTM9JUwM+naLvlWqLQq2wAAuwAOaRTthAlZvp+wPMZjyK92/wEAABbLvLsehNHReK1tAZ+b/wEAtg/EVZpt8ofTxlJ6L61E8D7lAQD4acBmpjoaV0W2EEO32jIFANgHcA6ZTe3d1zMx4+yETE7/mwdhAAAAVqfKxtrjfz34GTObpNrDGQBgH8D8tHEqKY+3BYR+5VsZZQAAAG1g9uU+n4A6L0z7fk3oBQAA2Cew+vCe7f6PoZF50SIDAADwDrBNmnB0fzZlhU/6AQD8AhCOIde6gOVCL3o0AQAAFl/ue8xraX7e0obpx0//AQBsFmj8DYrJK8nlTP/8w0kCAADwsl+ZIAiCIAiCIAjif8a/AAAA//8kfGJ+GmIouAAAAABJRU5ErkJggg==","qrcode_index_url":"https://api.amemv.com/ucenter_web/app/aweme/scan_login/index/douyin_scan_code_login/cn/app/index.html?_pia_=1\u0026hide_nav_bar=1\u0026is_new_login=1\u0026loader_name=forest\u0026next_url=https%3A%2F%2Fapi.amemv.com%2Fpassport%2Fmobile%2Fscan_qrcode%2F\u0026qr_source_aid=6383\u0026scene=\u0026source=\u0026token=621de9524be86e20eb2f8b7fdf1c3416_lf\u0026verify_reason=\u0026verify_scene=\u0026verify_ticket=\u0026web_app_from=rcode","status":"expired","token":"621de9524be86e20eb2f8b7fdf1c3416_lf","web_name":"抖音"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_165541_get.json b/try/captures/net_165541_get.json new file mode 100644 index 0000000..be4729d --- /dev/null +++ b/try/captures/net_165541_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":66,"host":"","id":"74139ac7f8d7f6720414ef8a5b8c6e38c4af2020","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/279e20b118fa47e0a6eaa35061ddd023~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1a76d9f7cab941f5b4a48768f07b5d55~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/279e20b118fa47e0a6eaa35061ddd023~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/279e20b118fa47e0a6eaa35061ddd023~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1a76d9f7cab941f5b4a48768f07b5d55~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1a76d9f7cab941f5b4a48768f07b5d55~tplv-188rlo5p4y-1.png"],"tip_y":73,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_165900_get.json b/try/captures/net_165900_get.json new file mode 100644 index 0000000..cb843ea --- /dev/null +++ b/try/captures/net_165900_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":51,"host":"","id":"db00e213fd73eaebeecbe373a8468185070cd5de","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/11303a0e5f184d39b3474e9122bdc50a~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5fba792e01bd41558ed784863088f391~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/11303a0e5f184d39b3474e9122bdc50a~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/11303a0e5f184d39b3474e9122bdc50a~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5fba792e01bd41558ed784863088f391~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5fba792e01bd41558ed784863088f391~tplv-188rlo5p4y-1.png"],"tip_y":27,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_165904_get.json b/try/captures/net_165904_get.json new file mode 100644 index 0000000..79d5337 --- /dev/null +++ b/try/captures/net_165904_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":33,"host":"","id":"819f7fba7a896323f7dc47a4d9ad4e7a39908325","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0f9db01697d94430ae3935bcfe907605~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/be6cd78ab66a4352ab9c0c751a55a063~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0f9db01697d94430ae3935bcfe907605~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0f9db01697d94430ae3935bcfe907605~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/be6cd78ab66a4352ab9c0c751a55a063~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/be6cd78ab66a4352ab9c0c751a55a063~tplv-188rlo5p4y-1.png"],"tip_y":81,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_170108_14.jpg b/try/captures/net_170108_14.jpg new file mode 100644 index 0000000..fefd9e4 Binary files /dev/null and b/try/captures/net_170108_14.jpg differ diff --git a/try/captures/net_170108_get.json b/try/captures/net_170108_get.json new file mode 100644 index 0000000..eca5b68 --- /dev/null +++ b/try/captures/net_170108_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":87,"host":"","id":"bc7278d7fb26b2b6d7fc5e2f2299527e8b42a3e3","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/89c6fe5731014ce1976eeaa9077cc5cf~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/2aad9aec93a04b398e15040c67ef5f44~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/89c6fe5731014ce1976eeaa9077cc5cf~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/89c6fe5731014ce1976eeaa9077cc5cf~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/2aad9aec93a04b398e15040c67ef5f44~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/2aad9aec93a04b398e15040c67ef5f44~tplv-188rlo5p4y-1.png"],"tip_y":72,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_170158_18.jpg b/try/captures/net_170158_18.jpg new file mode 100644 index 0000000..3af9872 Binary files /dev/null and b/try/captures/net_170158_18.jpg differ diff --git a/try/captures/net_170158_get.json b/try/captures/net_170158_get.json new file mode 100644 index 0000000..ae214da --- /dev/null +++ b/try/captures/net_170158_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":72,"host":"","id":"764bbfa73dabb10a014955924919850efb730a55","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c6da8c3fd81343e5bb5dbe9292a55871~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/8c16a01f1c804b7b85a159f1a5b64751~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c6da8c3fd81343e5bb5dbe9292a55871~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c6da8c3fd81343e5bb5dbe9292a55871~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/8c16a01f1c804b7b85a159f1a5b64751~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/8c16a01f1c804b7b85a159f1a5b64751~tplv-188rlo5p4y-1.png"],"tip_y":77,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_170305_get.json b/try/captures/net_170305_get.json new file mode 100644 index 0000000..5df3883 --- /dev/null +++ b/try/captures/net_170305_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":97,"host":"","id":"180bf869c8de5ee7acd4c33e27227509838f387c","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c1c130d1a027459ea342f2ecc921cbff~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4714d31d39e84b5a9049276225342466~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c1c130d1a027459ea342f2ecc921cbff~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c1c130d1a027459ea342f2ecc921cbff~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4714d31d39e84b5a9049276225342466~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4714d31d39e84b5a9049276225342466~tplv-188rlo5p4y-1.png"],"tip_y":53,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_170444_get.json b/try/captures/net_170444_get.json new file mode 100644 index 0000000..d28af39 --- /dev/null +++ b/try/captures/net_170444_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":34,"host":"","id":"05f12892083f7f8f5e684da816f0b4bf153bcc07","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/53aa158f8c524a5a8d54a1e067572162~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/16b3142c91d24a509f3036e4573c3f7b~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/53aa158f8c524a5a8d54a1e067572162~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/53aa158f8c524a5a8d54a1e067572162~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/16b3142c91d24a509f3036e4573c3f7b~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/16b3142c91d24a509f3036e4573c3f7b~tplv-188rlo5p4y-1.png"],"tip_y":25,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_170646_get.json b/try/captures/net_170646_get.json new file mode 100644 index 0000000..e97c54d --- /dev/null +++ b/try/captures/net_170646_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":82,"host":"","id":"43f0e7b1443a0229040dd05a66d39d8bca769d3c","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/85b313fec0e3447987a63f6bc77f0849~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b654eb5f6a23450989d3787702998fec~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/85b313fec0e3447987a63f6bc77f0849~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/85b313fec0e3447987a63f6bc77f0849~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b654eb5f6a23450989d3787702998fec~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b654eb5f6a23450989d3787702998fec~tplv-188rlo5p4y-1.png"],"tip_y":87,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_171109_get.json b/try/captures/net_171109_get.json new file mode 100644 index 0000000..eff5a79 --- /dev/null +++ b/try/captures/net_171109_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":93,"host":"","id":"1fa66e4ec5a93013dbdce6e195d6c012d3450258","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/261106ff8d9049459d9db6b1b2700017~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c0387784042b4ffbbbcc580f7aa83e58~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/261106ff8d9049459d9db6b1b2700017~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/261106ff8d9049459d9db6b1b2700017~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c0387784042b4ffbbbcc580f7aa83e58~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c0387784042b4ffbbbcc580f7aa83e58~tplv-188rlo5p4y-1.png"],"tip_y":81,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_171237_get.json b/try/captures/net_171237_get.json new file mode 100644 index 0000000..a2b4494 --- /dev/null +++ b/try/captures/net_171237_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":24,"host":"","id":"33d637c34fa70ba243f6d9f501f3f60388e178b6","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/04415ef849754456a6c839e0e32dea7d~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/69d0386562774aa3960fe5d94c7ca5ce~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/04415ef849754456a6c839e0e32dea7d~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/04415ef849754456a6c839e0e32dea7d~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/69d0386562774aa3960fe5d94c7ca5ce~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/69d0386562774aa3960fe5d94c7ca5ce~tplv-188rlo5p4y-1.png"],"tip_y":68,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_171342_get.json b/try/captures/net_171342_get.json new file mode 100644 index 0000000..92b0506 --- /dev/null +++ b/try/captures/net_171342_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":43,"host":"","id":"c8df3af78dfa67f5e70e2d0c9a4bcd341542b1d0","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/d8296d67851942cf9eebf86f0f5a96d3~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/faab120f393f484c9d3c62cf1ee1e397~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/d8296d67851942cf9eebf86f0f5a96d3~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/d8296d67851942cf9eebf86f0f5a96d3~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/faab120f393f484c9d3c62cf1ee1e397~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/faab120f393f484c9d3c62cf1ee1e397~tplv-188rlo5p4y-1.png"],"tip_y":53,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_171412_get.json b/try/captures/net_171412_get.json new file mode 100644 index 0000000..bb81c32 --- /dev/null +++ b/try/captures/net_171412_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":61,"host":"","id":"a7e0a4151261a079c38930cc0c85f7753adf1330","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/d403cb0a2d9242bd8618fb6e83f41bac~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/64b8b3fb28774538ab3a18b716a105f3~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/d403cb0a2d9242bd8618fb6e83f41bac~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/d403cb0a2d9242bd8618fb6e83f41bac~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/64b8b3fb28774538ab3a18b716a105f3~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/64b8b3fb28774538ab3a18b716a105f3~tplv-188rlo5p4y-1.png"],"tip_y":69,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_171413_11.jpg b/try/captures/net_171413_11.jpg new file mode 100644 index 0000000..f332a4f Binary files /dev/null and b/try/captures/net_171413_11.jpg differ diff --git a/try/captures/net_171511_get.json b/try/captures/net_171511_get.json new file mode 100644 index 0000000..0b784a1 --- /dev/null +++ b/try/captures/net_171511_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":38,"host":"","id":"223f9fba55722c63e929d676e0c676995e8e74d4","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4d05142b42754e688d47146a5bb0ed32~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/655c8a556b1840c8b5e3c16b3128546c~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4d05142b42754e688d47146a5bb0ed32~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4d05142b42754e688d47146a5bb0ed32~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/655c8a556b1840c8b5e3c16b3128546c~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/655c8a556b1840c8b5e3c16b3128546c~tplv-188rlo5p4y-1.png"],"tip_y":38,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_174630_get.json b/try/captures/net_174630_get.json new file mode 100644 index 0000000..d2eba62 --- /dev/null +++ b/try/captures/net_174630_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":53,"host":"","id":"45543c41428c82fbc6594ba9206314b2f7a83b2d","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0701d5d1399a47cda548015f66df919f~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7db3817546ff440698965686485b692d~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0701d5d1399a47cda548015f66df919f~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0701d5d1399a47cda548015f66df919f~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7db3817546ff440698965686485b692d~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7db3817546ff440698965686485b692d~tplv-188rlo5p4y-1.png"],"tip_y":30,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_174742_5.jpg b/try/captures/net_174742_5.jpg new file mode 100644 index 0000000..2ff5302 Binary files /dev/null and b/try/captures/net_174742_5.jpg differ diff --git a/try/captures/net_174742_get.json b/try/captures/net_174742_get.json new file mode 100644 index 0000000..870a9ae --- /dev/null +++ b/try/captures/net_174742_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":89,"host":"","id":"42c3d7d05017f067aecfe8de26fab665079511b3","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7043266546954442a176664ff6f7ce6e~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/52ade76e082c4fc38d70e2e28d5d9b10~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7043266546954442a176664ff6f7ce6e~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7043266546954442a176664ff6f7ce6e~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/52ade76e082c4fc38d70e2e28d5d9b10~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/52ade76e082c4fc38d70e2e28d5d9b10~tplv-188rlo5p4y-1.png"],"tip_y":72,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_175019_get.json b/try/captures/net_175019_get.json new file mode 100644 index 0000000..884ad49 --- /dev/null +++ b/try/captures/net_175019_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":81,"host":"","id":"676989a43195854977ad08a017644f06160fb315","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/81230bfc863a4f5fa08a232d265bed49~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3e3ef6a071684f1ea1d5ef2314b073c4~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/81230bfc863a4f5fa08a232d265bed49~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/81230bfc863a4f5fa08a232d265bed49~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3e3ef6a071684f1ea1d5ef2314b073c4~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3e3ef6a071684f1ea1d5ef2314b073c4~tplv-188rlo5p4y-1.png"],"tip_y":95,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_175109_verify.json b/try/captures/net_175109_verify.json new file mode 100644 index 0000000..8279f82 --- /dev/null +++ b/try/captures/net_175109_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"VerifyErr"},"message":"验证失败,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_175110_get.json b/try/captures/net_175110_get.json new file mode 100644 index 0000000..d82710d --- /dev/null +++ b/try/captures/net_175110_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":97,"host":"","id":"915a5f24aa81d3737f9ade5f4c9aca8d289cf66d","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/01661cd33b1d42efb0e6215105287e0f~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/bfc1eeb90aba4864b586d0dab93bffd3~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/01661cd33b1d42efb0e6215105287e0f~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/01661cd33b1d42efb0e6215105287e0f~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/bfc1eeb90aba4864b586d0dab93bffd3~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/bfc1eeb90aba4864b586d0dab93bffd3~tplv-188rlo5p4y-1.png"],"tip_y":24,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_175111_6.jpg b/try/captures/net_175111_6.jpg new file mode 100644 index 0000000..973192a Binary files /dev/null and b/try/captures/net_175111_6.jpg differ diff --git a/try/captures/net_175334_verify.json b/try/captures/net_175334_verify.json new file mode 100644 index 0000000..cac68eb --- /dev/null +++ b/try/captures/net_175334_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"NotFoundChallengeId"},"message":"验证超时,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_175335_get.json b/try/captures/net_175335_get.json new file mode 100644 index 0000000..f2777b3 --- /dev/null +++ b/try/captures/net_175335_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":82,"host":"","id":"bb6bc15b283564a831af01c3eabe475a284e10a9","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3937d1d2756c4d5b9903c874e9f41a9c~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5ecd057426154fe9a6372fd4b840d79a~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3937d1d2756c4d5b9903c874e9f41a9c~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3937d1d2756c4d5b9903c874e9f41a9c~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5ecd057426154fe9a6372fd4b840d79a~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5ecd057426154fe9a6372fd4b840d79a~tplv-188rlo5p4y-1.png"],"tip_y":54,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_180857_get.json b/try/captures/net_180857_get.json new file mode 100644 index 0000000..b82c311 --- /dev/null +++ b/try/captures/net_180857_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":75,"host":"","id":"2617e98d2b4615811177130ea09802793c9cb605","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0ebaaae97e4147e28704d6de684c7d58~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/dee09afee0fd44389a2fd887a375d4a7~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0ebaaae97e4147e28704d6de684c7d58~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0ebaaae97e4147e28704d6de684c7d58~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/dee09afee0fd44389a2fd887a375d4a7~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/dee09afee0fd44389a2fd887a375d4a7~tplv-188rlo5p4y-1.png"],"tip_y":78,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_180955_verify.json b/try/captures/net_180955_verify.json new file mode 100644 index 0000000..dc8311c --- /dev/null +++ b/try/captures/net_180955_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"操作过快,请慢一点[5014]"} \ No newline at end of file diff --git a/try/captures/net_181100_get.json b/try/captures/net_181100_get.json new file mode 100644 index 0000000..0790051 --- /dev/null +++ b/try/captures/net_181100_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":35,"host":"","id":"c2da214c228620bcf05c6a08c504026beb7c79f1","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0273de214ae24c1cb2da2ebf90c4adfb~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a1d806dddf5e4e0ebf3898227a4dd3ba~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0273de214ae24c1cb2da2ebf90c4adfb~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0273de214ae24c1cb2da2ebf90c4adfb~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a1d806dddf5e4e0ebf3898227a4dd3ba~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a1d806dddf5e4e0ebf3898227a4dd3ba~tplv-188rlo5p4y-1.png"],"tip_y":75,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_181413_verify.json b/try/captures/net_181413_verify.json new file mode 100644 index 0000000..cac68eb --- /dev/null +++ b/try/captures/net_181413_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"NotFoundChallengeId"},"message":"验证超时,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_181414_11.jpg b/try/captures/net_181414_11.jpg new file mode 100644 index 0000000..1076c74 Binary files /dev/null and b/try/captures/net_181414_11.jpg differ diff --git a/try/captures/net_181414_get.json b/try/captures/net_181414_get.json new file mode 100644 index 0000000..4a83384 --- /dev/null +++ b/try/captures/net_181414_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":24,"host":"","id":"f241e01462746893b2a4bbc76aa31e76934ffb98","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3cbbab20c2e146b0aca6145a0ecdc4af~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a89de64b1d624618af217c94a46dfa06~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3cbbab20c2e146b0aca6145a0ecdc4af~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3cbbab20c2e146b0aca6145a0ecdc4af~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a89de64b1d624618af217c94a46dfa06~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a89de64b1d624618af217c94a46dfa06~tplv-188rlo5p4y-1.png"],"tip_y":30,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_181418_verify.json b/try/captures/net_181418_verify.json new file mode 100644 index 0000000..04a629d --- /dev/null +++ b/try/captures/net_181418_verify.json @@ -0,0 +1 @@ +{"code":200,"data":null,"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_181420_verify.json b/try/captures/net_181420_verify.json new file mode 100644 index 0000000..2f2e75a --- /dev/null +++ b/try/captures/net_181420_verify.json @@ -0,0 +1 @@ +{"data":{"alert_text":"账号或密码错误,请重试。","captcha":"","desc_url":"","description":"账号或密码错误,请重试。","error_code":1009},"message":"error"} \ No newline at end of file diff --git a/try/captures/net_181431_verify.json b/try/captures/net_181431_verify.json new file mode 100644 index 0000000..bfa3bae --- /dev/null +++ b/try/captures/net_181431_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"滑动滑块进行验证","error_code":1105,"verify_center_decision_conf":"{\"code\":\"10000\",\"from\":\"shark_admin\",\"type\":\"verify\",\"version\":\"1\",\"region\":\"cn\",\"subtype\":\"slide\",\"ui_type\":\"\",\"detail\":\"XCCxxJ78Uvchj9qXrcrjDNIIsELbQidfcNkB550Wgkxe-w5fGBiiV-4jNqE5eSOQf6Ye7GZU63*ElhUMB*1MK2obS2I4x36av0mg7LnG6ahdEpKFb2WparazaPusLW5sxUECjK4PopzFUHDkuzp4dF6fM1tIW*g28hjPTmvuOhgX5N5YFty9DudxmLecYg1wzUEMRh13-UwqF6iuoTgOVp0ic5eUMbmNleuPgnjAs8HwdBgthi2y39zAD4PxrVW4HfDRU6bUOGB7ut3CVxeojIHDVfzr-9ekzP6fcP8s75ohInezPWl6v7NW8S0TljBr4mBDyBEstTcTK4yMSY5mOThTdQFGtwd5KubaBGur3qILyCof1-o9kwm012tEbF6N\",\"verify_event\":\"tt_user_pwd_login\",\"fp\":\"verify_mtwarf05_T2cF4uRW_4ewx_4A4K_9lxP_FRjbBMt9WYRC\",\"verify_ticket\":\"VTIDEFBA8SANFNN4X7XHPVEUUY3AUMHUH7CYZK_lf\",\"server_sdk_env\":\"{\\\"idc\\\":\\\"lf\\\",\\\"region\\\":\\\"CN\\\",\\\"server_type\\\":\\\"passport\\\"}\",\"log_id\":\"20260911181519D4B2FAFC3591DBB180DB\",\"is_assist_mobile\":false,\"is_complex_sms\":false,\"identity_action\":\"\",\"identity_scene\":\"\",\"verify_scene\":\"passport\",\"login_status\":0,\"aid\":0,\"replay_data\":{\"x-tt-passport-replay-params\":\"{}\"}}","verify_ticket":"VTIDEFBA8SANFNN4X7XHPVEUUY3AUMHUH7CYZK_lf"},"message":"error"} \ No newline at end of file diff --git a/try/captures/net_181436_verify.json b/try/captures/net_181436_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181436_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181442_verify.json b/try/captures/net_181442_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181442_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181447_verify.json b/try/captures/net_181447_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181447_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181452_verify.json b/try/captures/net_181452_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181452_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181457_verify.json b/try/captures/net_181457_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181457_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181503_verify.json b/try/captures/net_181503_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181503_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181508_verify.json b/try/captures/net_181508_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181508_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181513_verify.json b/try/captures/net_181513_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181513_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181519_verify.json b/try/captures/net_181519_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181519_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181524_verify.json b/try/captures/net_181524_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181524_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181529_verify.json b/try/captures/net_181529_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_181529_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_181535_verify.json b/try/captures/net_181535_verify.json new file mode 100644 index 0000000..ebb4903 --- /dev/null +++ b/try/captures/net_181535_verify.json @@ -0,0 +1 @@ +{"data":{"app_name":"抖音","captcha":"","desc_url":"","description":"","error_code":0,"expire_time":1789121843,"frontier_params":{"access_key":"d8b2e550d05b7afcfea970017e05bc44","frontier_device":"7657740123052901934","method":1,"product_id":971,"service_id":1024},"is_frontier":true,"qrcode":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIAAQMAAADOtka5AAAABlBMVEX///8AAABVwtN+AAACxklEQVR42uzcPbLyOgyAYTEUKVkCS2FpYWksJUugTJGJ7tiSfxKcA82d+TCvmgMn4ek8khU5QhAEQRAEQRAE8a/HTXM8ROSkT5Eh/0su8c8SLuRYAQAAWkD6OjigasDjpJMEYI6Xo7z9BQBAb8A13H8f9HHWKdwXvjVXma0rAACADwDVcN8soyegFxkA4EeAmItk0Ps5ZCZVS1lWpQEAALwDcpl39u1MBPKWZxbx1fi2TgQA+GagKsZSApplXGyVyaVkpg/6BwAAvwzUETNT+vjwT2P80fRRkxoA4IuBVKVt+8qWmaZdk81bzAAAAC1AJCQgs/yiZaZ4QZ8yzvFC6Vi/ZiYAgB6Am7fMqrDMpKlKk2xlGQAA4AAI1VxcdNe1Xo3iTzzDBfVe2uHTfwCA7wcsAcUK7LrKRfOWJ17wFkHVZAMAAGgBVr+liZl60ak9srmXhzQAAP0DsllMQxmqjFueJPuTTAEAAGgAacuTdzYx7psmmy4Z0MM9EwDAlwNyKu3jc9n++4Uyyb/m7HVbAQAAjgBPQGViZlzCPmdKo8uLLUxbjQAA3QJVlWbdM/URy8m/pVXW7CsDAABUvbTcmE6Hx0a1eeV6LKD+BgDQIaCemcr2P2956r3QWlYZAADAIbAbpUn3XbUeKzse/gcA6AJYS5/MLTv6kg7C3NMJmYsXc63UBgAAUJd5KQHlZzEv9d9wNPAMANAJsD3wZUf3H5sTMmn7/+dBGACAnwZ2p8qqxnSS53zcrN2MAwDoA9i9BqlUaZaZbF5ZyzHkVi8NAADg9T0YZXjGemnP+rjyUWcbAKATYPt+pO1iEh8L0DJvJgAAAO8B9YmZfHT/Uv/Em2wrAED/wLR7W0VpoJ3yWNnfqxEA4JeBXOZJ/qib/kH1KBQAoF+g8eK99Krw/ey+bN5CBgAAQBAEQRAEQRAE8T/HfwEAAP//dilsCCH1Q54AAAAASUVORK5CYII=","qrcode_index_url":"https://api.amemv.com/ucenter_web/app/aweme/scan_login/index/douyin_scan_code_login/cn/app/index.html?_pia_=1\u0026hide_nav_bar=1\u0026is_new_login=1\u0026loader_name=forest\u0026next_url=https%3A%2F%2Fapi.amemv.com%2Fpassport%2Fmobile%2Fscan_qrcode%2F\u0026qr_source_aid=6383\u0026scene=\u0026source=\u0026token=4ce1c27464933da899841b2209779b3b_lf\u0026verify_reason=\u0026verify_scene=\u0026verify_ticket=\u0026web_app_from=rcode","status":"expired","token":"4ce1c27464933da899841b2209779b3b_lf","web_name":"抖音"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_182914_verify.json b/try/captures/net_182914_verify.json new file mode 100644 index 0000000..c7dcdc2 --- /dev/null +++ b/try/captures/net_182914_verify.json @@ -0,0 +1 @@ +{"data":{"captcha":"","desc_url":"","description":"","error_code":0,"extra":"","scan_app_id":0,"status":"new"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_182919_verify.json b/try/captures/net_182919_verify.json new file mode 100644 index 0000000..1028878 --- /dev/null +++ b/try/captures/net_182919_verify.json @@ -0,0 +1 @@ +{"data":{"app_name":"抖音","captcha":"","desc_url":"","description":"","error_code":0,"expire_time":1789122667,"frontier_params":{"access_key":"d8b2e550d05b7afcfea970017e05bc44","frontier_device":"7657740123052901934","method":1,"product_id":971,"service_id":1024},"is_frontier":true,"qrcode":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIAAQMAAADOtka5AAAABlBMVEX///8AAABVwtN+AAACzklEQVR42uzcMZLqMAyAYe9QpOQIHGWPRo7GUTgCJUUmehNLsuWsgS1esZhf1bJJvs5jWVKSCIIgCIIgCIIg/np8S4lLSieRW5K7Xcu/zvrrq963AgAA9AD/OcnlINeUjvmmZZPzrzkZcNs/AQAwGnDanpgzINvySZPMB7l8xVWWAZMBAABeA9f81L1ctZ0pXwAA+Bwg/+MoYTHpliXLLxcTAMCHAyXNS2rFC5rm2Wp8mScCALwzEI7/vgHd03nRVbYBYct6VT8AAPhkIIbdt/vvtD10/VWRGgDgjYFdLS0DnqVdmy3rZtYFAACgC9SV5n9Krhh40jfrkSdfEACAcYHclyydmWRZWjpsyZhmabV3qelbAgAA6AGhTPCdjzPHLc0r9+mFRRfmk+4/AMDbAz7iMjdZmnb/pTn+hxEZAACALpBzu/O9DM/oavRlWrYsPwv9XI0AACMAXleea1+ytCiljliewohMAgAA6AFrU5jelQm0zbmleWsd3lwBAEYE8s5kC2qxSZhaWSvF5HwW0iwNAACgD1hYmmczmudQLrhb/cC3LACAMYFwsvERy1Ay0yytnIWmJ8U4AAAAW2m1sradbNoiW3gRBgBgYEDXjK8hLx/rBfGGpR155v5YGQAAQPet5LwafV65dGaO0m3SAACMAtjOFA45loy5rK8h+1hAb0YTAAAg7Ey2MGv3P95TO56yPNraAADeHbCBl9Dkt1qaZ2lTqKs96v4DAADs3irTI0+9zw45h/JWwFkAAAYF2g/vhc9YSD3y6JZ1M+DBKA0AwMcDzXcwfjRpxN4KCDM2sgIADAqE7yOVSUp/WyzZx8ZKlpaef2AJAAAgNDZ3w/9tYfrwfDUCAIwC+MkmfB8pNCy7Rx4AAIBOmnday3cwYpq3NC+YJQCAIYHmw3val5zKwEs7u6/1tgsAAEAPIAiCIAiCIAiC+P/xLwAA///lj0+yH8ecTwAAAABJRU5ErkJggg==","qrcode_index_url":"https://api.amemv.com/ucenter_web/app/aweme/scan_login/index/douyin_scan_code_login/cn/app/index.html?_pia_=1\u0026hide_nav_bar=1\u0026is_new_login=1\u0026loader_name=forest\u0026next_url=https%3A%2F%2Fapi.amemv.com%2Fpassport%2Fmobile%2Fscan_qrcode%2F\u0026qr_source_aid=6383\u0026scene=\u0026source=\u0026token=dda9c224f2456720880df3358e152bae_lq\u0026verify_reason=\u0026verify_scene=\u0026verify_ticket=\u0026web_app_from=rcode","status":"expired","token":"dda9c224f2456720880df3358e152bae_lq","web_name":"抖音"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_182937_get.json b/try/captures/net_182937_get.json new file mode 100644 index 0000000..58d41f8 --- /dev/null +++ b/try/captures/net_182937_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":85,"host":"","id":"a079801174e14fe280f5b52cbfc879cc24da2c05","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/8c2d606ab68f49edb2d6805e0ab77a42~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/21c7186069ca47e78370a1ef99876c9a~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/8c2d606ab68f49edb2d6805e0ab77a42~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/8c2d606ab68f49edb2d6805e0ab77a42~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/21c7186069ca47e78370a1ef99876c9a~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/21c7186069ca47e78370a1ef99876c9a~tplv-188rlo5p4y-1.png"],"tip_y":30,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_183039_verify.json b/try/captures/net_183039_verify.json new file mode 100644 index 0000000..cac68eb --- /dev/null +++ b/try/captures/net_183039_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"NotFoundChallengeId"},"message":"验证超时,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_183040_get.json b/try/captures/net_183040_get.json new file mode 100644 index 0000000..731f216 --- /dev/null +++ b/try/captures/net_183040_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":25,"host":"","id":"619d39ad07d9bd07fbc6358fcc2065b7e29a48b0","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4d5742044baf49a99424e8a1beef5b3a~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5526885562f04b8cbfa83273b57be142~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4d5742044baf49a99424e8a1beef5b3a~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4d5742044baf49a99424e8a1beef5b3a~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5526885562f04b8cbfa83273b57be142~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5526885562f04b8cbfa83273b57be142~tplv-188rlo5p4y-1.png"],"tip_y":31,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_183229_verify.json b/try/captures/net_183229_verify.json new file mode 100644 index 0000000..cac68eb --- /dev/null +++ b/try/captures/net_183229_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"NotFoundChallengeId"},"message":"验证超时,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_183231_15.jpg b/try/captures/net_183231_15.jpg new file mode 100644 index 0000000..456b85f Binary files /dev/null and b/try/captures/net_183231_15.jpg differ diff --git a/try/captures/net_183231_get.json b/try/captures/net_183231_get.json new file mode 100644 index 0000000..920e61f --- /dev/null +++ b/try/captures/net_183231_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":51,"host":"","id":"b3e593aa50658eff7b1a7bde727f1f99953209e7","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/be0ccf364472497686e294a9ced0b15f~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/530dca6fc7224bbab8a8d52845515d37~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/be0ccf364472497686e294a9ced0b15f~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/be0ccf364472497686e294a9ced0b15f~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/530dca6fc7224bbab8a8d52845515d37~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/530dca6fc7224bbab8a8d52845515d37~tplv-188rlo5p4y-1.png"],"tip_y":80,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_183931_2.jpg b/try/captures/net_183931_2.jpg new file mode 100644 index 0000000..4043703 Binary files /dev/null and b/try/captures/net_183931_2.jpg differ diff --git a/try/captures/net_183931_get.json b/try/captures/net_183931_get.json new file mode 100644 index 0000000..415f8ce --- /dev/null +++ b/try/captures/net_183931_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":35,"host":"","id":"4da0a187dbf37192c8bb7d7cf166e8f582157270","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/8fb8cb8dc366493da05416f1b2967cc8~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/f8c7a2fcfc634547a57f0978da83b3c1~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/8fb8cb8dc366493da05416f1b2967cc8~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/8fb8cb8dc366493da05416f1b2967cc8~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/f8c7a2fcfc634547a57f0978da83b3c1~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/f8c7a2fcfc634547a57f0978da83b3c1~tplv-188rlo5p4y-1.png"],"tip_y":44,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_183938_verify.json b/try/captures/net_183938_verify.json new file mode 100644 index 0000000..dc8311c --- /dev/null +++ b/try/captures/net_183938_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"操作过快,请慢一点[5014]"} \ No newline at end of file diff --git a/try/captures/net_183942_get.json b/try/captures/net_183942_get.json new file mode 100644 index 0000000..82e2d26 --- /dev/null +++ b/try/captures/net_183942_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":26,"host":"","id":"500294fc3cef296ba5a13b5e9dc800cd48b8f6ee","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/054aea18996a490a95d44605b447e31f~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5924cddf42974177a5db24f56592db6f~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/054aea18996a490a95d44605b447e31f~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/054aea18996a490a95d44605b447e31f~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5924cddf42974177a5db24f56592db6f~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5924cddf42974177a5db24f56592db6f~tplv-188rlo5p4y-1.png"],"tip_y":27,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_183943_7.jpg b/try/captures/net_183943_7.jpg new file mode 100644 index 0000000..7b54d5a Binary files /dev/null and b/try/captures/net_183943_7.jpg differ diff --git a/try/captures/net_183954_9.jpg b/try/captures/net_183954_9.jpg new file mode 100644 index 0000000..7598f25 Binary files /dev/null and b/try/captures/net_183954_9.jpg differ diff --git a/try/captures/net_183954_get.json b/try/captures/net_183954_get.json new file mode 100644 index 0000000..83a5242 --- /dev/null +++ b/try/captures/net_183954_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":60,"host":"","id":"e5359f2cc2d7580ba8e3e88bfad2233fe7d87621","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7a7cc0ea4d8d43839732ce6e92f782fa~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/adee869a4afe420f99b857710ee574a8~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7a7cc0ea4d8d43839732ce6e92f782fa~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7a7cc0ea4d8d43839732ce6e92f782fa~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/adee869a4afe420f99b857710ee574a8~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/adee869a4afe420f99b857710ee574a8~tplv-188rlo5p4y-1.png"],"tip_y":90,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184002_verify.json b/try/captures/net_184002_verify.json new file mode 100644 index 0000000..dc8311c --- /dev/null +++ b/try/captures/net_184002_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"操作过快,请慢一点[5014]"} \ No newline at end of file diff --git a/try/captures/net_184209_get.json b/try/captures/net_184209_get.json new file mode 100644 index 0000000..2fad949 --- /dev/null +++ b/try/captures/net_184209_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":64,"host":"","id":"2d74d02cdba872c58f3bbade0360290ef4c50f2e","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6b32bb445f734f7394bf06474f32a33f~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1e5e3281990848cfb5fddc80467435c5~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6b32bb445f734f7394bf06474f32a33f~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6b32bb445f734f7394bf06474f32a33f~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1e5e3281990848cfb5fddc80467435c5~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1e5e3281990848cfb5fddc80467435c5~tplv-188rlo5p4y-1.png"],"tip_y":95,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184210_14.jpg b/try/captures/net_184210_14.jpg new file mode 100644 index 0000000..f49d367 Binary files /dev/null and b/try/captures/net_184210_14.jpg differ diff --git a/try/captures/net_184217_verify.json b/try/captures/net_184217_verify.json new file mode 100644 index 0000000..8279f82 --- /dev/null +++ b/try/captures/net_184217_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"VerifyErr"},"message":"验证失败,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_184218_get.json b/try/captures/net_184218_get.json new file mode 100644 index 0000000..95d8c5d --- /dev/null +++ b/try/captures/net_184218_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":80,"host":"","id":"32fb2fdc68c63f4a404ebce049206d02c66eca5f","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/62b53419c11a43b4b48c1c42ca72fc55~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6182025c8ad74d208aab72e654739c9d~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/62b53419c11a43b4b48c1c42ca72fc55~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/62b53419c11a43b4b48c1c42ca72fc55~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6182025c8ad74d208aab72e654739c9d~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6182025c8ad74d208aab72e654739c9d~tplv-188rlo5p4y-1.png"],"tip_y":66,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184219_19.jpg b/try/captures/net_184219_19.jpg new file mode 100644 index 0000000..b9de7bc Binary files /dev/null and b/try/captures/net_184219_19.jpg differ diff --git a/try/captures/net_184221_22.jpg b/try/captures/net_184221_22.jpg new file mode 100644 index 0000000..475847b Binary files /dev/null and b/try/captures/net_184221_22.jpg differ diff --git a/try/captures/net_184221_get.json b/try/captures/net_184221_get.json new file mode 100644 index 0000000..7c2e2cf --- /dev/null +++ b/try/captures/net_184221_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":8,"host":"","id":"f760eedd3a154d2da4c33bd4878f953e1fccbff9","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1a617bd7230e41c1b3c8f6491af8b0ba~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/d9d64cc1773a44fba8c0df572873af44~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1a617bd7230e41c1b3c8f6491af8b0ba~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1a617bd7230e41c1b3c8f6491af8b0ba~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/d9d64cc1773a44fba8c0df572873af44~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/d9d64cc1773a44fba8c0df572873af44~tplv-188rlo5p4y-1.png"],"tip_y":89,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184228_verify.json b/try/captures/net_184228_verify.json new file mode 100644 index 0000000..dc8311c --- /dev/null +++ b/try/captures/net_184228_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"操作过快,请慢一点[5014]"} \ No newline at end of file diff --git a/try/captures/net_184354_26.jpg b/try/captures/net_184354_26.jpg new file mode 100644 index 0000000..b8e57c0 Binary files /dev/null and b/try/captures/net_184354_26.jpg differ diff --git a/try/captures/net_184354_get.json b/try/captures/net_184354_get.json new file mode 100644 index 0000000..a81022a --- /dev/null +++ b/try/captures/net_184354_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":7,"host":"","id":"bccd9ff911a2119c6261c5e98fbff151bd1137e3","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0ba31beba68940fc942980c7f47a0838~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3af9e237d05e467e98698cb4de5d00d8~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0ba31beba68940fc942980c7f47a0838~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0ba31beba68940fc942980c7f47a0838~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3af9e237d05e467e98698cb4de5d00d8~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/3af9e237d05e467e98698cb4de5d00d8~tplv-188rlo5p4y-1.png"],"tip_y":60,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184402_verify.json b/try/captures/net_184402_verify.json new file mode 100644 index 0000000..dc8311c --- /dev/null +++ b/try/captures/net_184402_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"操作过快,请慢一点[5014]"} \ No newline at end of file diff --git a/try/captures/net_184406_29.jpg b/try/captures/net_184406_29.jpg new file mode 100644 index 0000000..1b27c15 Binary files /dev/null and b/try/captures/net_184406_29.jpg differ diff --git a/try/captures/net_184406_get.json b/try/captures/net_184406_get.json new file mode 100644 index 0000000..3e0aa02 --- /dev/null +++ b/try/captures/net_184406_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":25,"host":"","id":"6c545567d7f9dc570043db42d45dd621344e5927","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5894623d79814e6c83b735f7360c6ba7~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/22cf77b8b2d242b8a3b5d33614099a6b~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5894623d79814e6c83b735f7360c6ba7~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/5894623d79814e6c83b735f7360c6ba7~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/22cf77b8b2d242b8a3b5d33614099a6b~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/22cf77b8b2d242b8a3b5d33614099a6b~tplv-188rlo5p4y-1.png"],"tip_y":79,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184413_verify.json b/try/captures/net_184413_verify.json new file mode 100644 index 0000000..8279f82 --- /dev/null +++ b/try/captures/net_184413_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"VerifyErr"},"message":"验证失败,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_184414_get.json b/try/captures/net_184414_get.json new file mode 100644 index 0000000..b6598a4 --- /dev/null +++ b/try/captures/net_184414_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":12,"host":"","id":"9c065d174b72909d8df1beb97c12c2440be0bcc5","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/f0588db7a82d46e6aa2b6f3e5f22e0c1~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/621f25cf46524c56ba6832c0030e255a~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/f0588db7a82d46e6aa2b6f3e5f22e0c1~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/f0588db7a82d46e6aa2b6f3e5f22e0c1~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/621f25cf46524c56ba6832c0030e255a~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/621f25cf46524c56ba6832c0030e255a~tplv-188rlo5p4y-1.png"],"tip_y":68,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184415_34.jpg b/try/captures/net_184415_34.jpg new file mode 100644 index 0000000..b011be3 Binary files /dev/null and b/try/captures/net_184415_34.jpg differ diff --git a/try/captures/net_184853_2.jpg b/try/captures/net_184853_2.jpg new file mode 100644 index 0000000..99b6d49 Binary files /dev/null and b/try/captures/net_184853_2.jpg differ diff --git a/try/captures/net_184853_get.json b/try/captures/net_184853_get.json new file mode 100644 index 0000000..3ba1569 --- /dev/null +++ b/try/captures/net_184853_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":60,"host":"","id":"0292cde0f1cc02b4fcfbafbb26ffaf050ef44917","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7d2080a3d9dc4615aa2c63231454823b~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4236cba0af104a1dbfbc7b7fefe7cab6~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7d2080a3d9dc4615aa2c63231454823b~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/7d2080a3d9dc4615aa2c63231454823b~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4236cba0af104a1dbfbc7b7fefe7cab6~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/4236cba0af104a1dbfbc7b7fefe7cab6~tplv-188rlo5p4y-1.png"],"tip_y":94,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184900_verify.json b/try/captures/net_184900_verify.json new file mode 100644 index 0000000..8279f82 --- /dev/null +++ b/try/captures/net_184900_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"VerifyErr"},"message":"验证失败,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_184902_6.jpg b/try/captures/net_184902_6.jpg new file mode 100644 index 0000000..ac0f5fa Binary files /dev/null and b/try/captures/net_184902_6.jpg differ diff --git a/try/captures/net_184902_get.json b/try/captures/net_184902_get.json new file mode 100644 index 0000000..dc48e99 --- /dev/null +++ b/try/captures/net_184902_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":85,"host":"","id":"8a418fa57756d69cc4e512d279a6ce9b44f674b1","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/62543677568b4bc9badfde5a2dcf690a~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/efa14e3f54504057ab21ec68e3868e67~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/62543677568b4bc9badfde5a2dcf690a~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/62543677568b4bc9badfde5a2dcf690a~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/efa14e3f54504057ab21ec68e3868e67~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/efa14e3f54504057ab21ec68e3868e67~tplv-188rlo5p4y-1.png"],"tip_y":93,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184904_9.jpg b/try/captures/net_184904_9.jpg new file mode 100644 index 0000000..7e3f6b3 Binary files /dev/null and b/try/captures/net_184904_9.jpg differ diff --git a/try/captures/net_184904_get.json b/try/captures/net_184904_get.json new file mode 100644 index 0000000..c812c1b --- /dev/null +++ b/try/captures/net_184904_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":38,"host":"","id":"02c51e3e150706b66296f3aa1d4e3ae91dca1f55","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/682c58e51ea54161a512657e96d9fb1e~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/86a8188dfde44072b096a2e09fbc0a39~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/682c58e51ea54161a512657e96d9fb1e~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/682c58e51ea54161a512657e96d9fb1e~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/86a8188dfde44072b096a2e09fbc0a39~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/86a8188dfde44072b096a2e09fbc0a39~tplv-188rlo5p4y-1.png"],"tip_y":94,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_184912_verify.json b/try/captures/net_184912_verify.json new file mode 100644 index 0000000..dc8311c --- /dev/null +++ b/try/captures/net_184912_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"操作过快,请慢一点[5014]"} \ No newline at end of file diff --git a/try/captures/net_191926_verify.json b/try/captures/net_191926_verify.json new file mode 100644 index 0000000..35c285a --- /dev/null +++ b/try/captures/net_191926_verify.json @@ -0,0 +1 @@ +{"data":{"app_name":"抖音","captcha":"","desc_url":"","description":"","error_code":0,"expire_time":1789125675,"frontier_params":{"access_key":"d8b2e550d05b7afcfea970017e05bc44","frontier_device":"7657740123052901934","method":1,"product_id":971,"service_id":1024},"is_frontier":true,"qrcode":"iVBORw0KGgoAAAANSUhEUgAAAgAAAAIAAQMAAADOtka5AAAABlBMVEX///8AAABVwtN+AAACyUlEQVR42uzcP5K7OgzAcWVSpOQIHIWjwdE4yh4hJQWD3mBL/kMgSfGK33q/qpYNfDqPbUm2EARBEARBEARB/OsxaIo5/KNTedg/fkSfMqrqKnLL720AAABngD8+AlC8twPSqS7h55s+j18AALQG9PvL00Pn+/6JyP501/lWjbId0DCuAAAAvgBCiITpaDMrygAAfwtIc9F9H0G9xikrrtIAAAA+AWmZZ6MxAnFn49zPV+tEAIDfDBTbf5+AFhnXOMqkyzPTF/kDAIC/DJThW55lX+bN9s/RUwlfBADALwZ8lRZ3+f2Wvppv9lWdZFsBAADeAGk1pxpnprjM6/encZHBijRWvdkAAJoGclkmTlJx+9/pFF7rNS3frgYTAABA+FH8vZiY9vfCMB1WA/RqNAIANABonI7GvP0vBlN8Gvyrh053AACAC6BazYUtT8wf+Dw15SINAEDLQJqA8qxTLMai7Ku0CMwCAABwAgzWlmx/VoVNT7LpmoCTXBoAQBuA3HYgvbfZuLKGF/sqjDJvXT5U/wEAAIrGmLTP8YpnIU9i+YOYmF4BABoFJNcltarFxIJlZy0y3m82ns9MAAAAZf5A8nmX6eXo5bsTlgAAjQDiKTO1TsqlOggTqze2fJvO2soAAADqimeZP7ATlmVb2dvjygAALQBit1W8HN3X3Lsftv/WeykAAACXQJpyDtX//RPv0bzKbAMANAMUBZjeOC1698UamdWvhwEAAFg+nirTKv/c58PL6bjZa2IaAKANoE6Z1W3JfkLG90L10UsAAICTXFq6B2PLAzPvhfy4cnnZJQBAg8DJ/UijlluetEqL1ZsNAADgM3Ds8e/Kskx58xIAQOOADya/HPx5bJG5vAcDAAAgL/N80OUJKOYPhjX9AADQLlBdvFcMn3RCJvfup+oNAACAXJywJAiCIAiCIAiC+D/jvwAAAP//+okGooThltIAAAAASUVORK5CYII=","qrcode_index_url":"https://api.amemv.com/ucenter_web/app/aweme/scan_login/index/douyin_scan_code_login/cn/app/index.html?_pia_=1\u0026hide_nav_bar=1\u0026is_new_login=1\u0026loader_name=forest\u0026next_url=https%3A%2F%2Fapi.amemv.com%2Fpassport%2Fmobile%2Fscan_qrcode%2F\u0026qr_source_aid=6383\u0026scene=\u0026source=\u0026token=c84c347c3fe6ca105043cdfd48ff8272_lf\u0026verify_reason=\u0026verify_scene=\u0026verify_ticket=\u0026web_app_from=rcode","status":"expired","token":"c84c347c3fe6ca105043cdfd48ff8272_lf","web_name":"抖音"},"message":"success"} \ No newline at end of file diff --git a/try/captures/net_192004_4.jpg b/try/captures/net_192004_4.jpg new file mode 100644 index 0000000..3899d90 Binary files /dev/null and b/try/captures/net_192004_4.jpg differ diff --git a/try/captures/net_192004_get.json b/try/captures/net_192004_get.json new file mode 100644 index 0000000..31a4486 --- /dev/null +++ b/try/captures/net_192004_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":36,"host":"","id":"578125ce90cb7a7fe45f24373699711fd57f309d","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/9260d2581a274c06afad462764c2db17~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6e035f1ae07f4cf2ae75e5bf2b8368fb~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/9260d2581a274c06afad462764c2db17~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/9260d2581a274c06afad462764c2db17~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6e035f1ae07f4cf2ae75e5bf2b8368fb~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6e035f1ae07f4cf2ae75e5bf2b8368fb~tplv-188rlo5p4y-1.png"],"tip_y":68,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_192054_verify.json b/try/captures/net_192054_verify.json new file mode 100644 index 0000000..dc8311c --- /dev/null +++ b/try/captures/net_192054_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"操作过快,请慢一点[5014]"} \ No newline at end of file diff --git a/try/captures/net_192226_8.jpg b/try/captures/net_192226_8.jpg new file mode 100644 index 0000000..f460099 Binary files /dev/null and b/try/captures/net_192226_8.jpg differ diff --git a/try/captures/net_192226_get.json b/try/captures/net_192226_get.json new file mode 100644 index 0000000..62612a3 --- /dev/null +++ b/try/captures/net_192226_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":58,"host":"","id":"670839105040431d429a4e7501d8a5c2ebb7f807","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b25a1a78bfd44028a244731a9722daa3~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c54fe3a55c0d492a843a34729367d61a~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b25a1a78bfd44028a244731a9722daa3~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b25a1a78bfd44028a244731a9722daa3~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c54fe3a55c0d492a843a34729367d61a~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/c54fe3a55c0d492a843a34729367d61a~tplv-188rlo5p4y-1.png"],"tip_y":27,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_192233_verify.json b/try/captures/net_192233_verify.json new file mode 100644 index 0000000..dc8311c --- /dev/null +++ b/try/captures/net_192233_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"操作过快,请慢一点[5014]"} \ No newline at end of file diff --git a/try/captures/net_192321_12.jpg b/try/captures/net_192321_12.jpg new file mode 100644 index 0000000..fcd38d5 Binary files /dev/null and b/try/captures/net_192321_12.jpg differ diff --git a/try/captures/net_192321_get.json b/try/captures/net_192321_get.json new file mode 100644 index 0000000..b93c1c3 --- /dev/null +++ b/try/captures/net_192321_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":54,"host":"","id":"af7a99b6e096294ea82bc42557cae217cd53b09d","mode":"slide","question":{"url1":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/fe58943f53854077a26d16fc23ed83ff~tplv-188rlo5p4y-2.jpeg","url2":"https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1ac7ea56bb764801bcbc9f736f9fed90~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/fe58943f53854077a26d16fc23ed83ff~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/fe58943f53854077a26d16fc23ed83ff~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1ac7ea56bb764801bcbc9f736f9fed90~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/1ac7ea56bb764801bcbc9f736f9fed90~tplv-188rlo5p4y-1.png"],"tip_y":87,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_192329_verify.json b/try/captures/net_192329_verify.json new file mode 100644 index 0000000..8279f82 --- /dev/null +++ b/try/captures/net_192329_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"VerifyErr"},"message":"验证失败,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_192330_16.jpg b/try/captures/net_192330_16.jpg new file mode 100644 index 0000000..f924243 Binary files /dev/null and b/try/captures/net_192330_16.jpg differ diff --git a/try/captures/net_192330_get.json b/try/captures/net_192330_get.json new file mode 100644 index 0000000..dc66d75 --- /dev/null +++ b/try/captures/net_192330_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":86,"host":"","id":"aebc6e446697819f152631daceda0c00177d3703","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a0b11aa9eb4444b290ba11006963091d~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6b6d81cbff1f4ac1917d74c6dd1201ab~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a0b11aa9eb4444b290ba11006963091d~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/a0b11aa9eb4444b290ba11006963091d~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6b6d81cbff1f4ac1917d74c6dd1201ab~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6b6d81cbff1f4ac1917d74c6dd1201ab~tplv-188rlo5p4y-1.png"],"tip_y":77,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_192443_get.json b/try/captures/net_192443_get.json new file mode 100644 index 0000000..039626e --- /dev/null +++ b/try/captures/net_192443_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":83,"host":"","id":"8129c653df2cb32715bf6046970db36ffb3992d1","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/ee6a280039f64b31976949ad16a33cce~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0884697c102941d9868d6235e73aa318~tplv-188rlo5p4y-1.png","backup_url1":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/ee6a280039f64b31976949ad16a33cce~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/ee6a280039f64b31976949ad16a33cce~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0884697c102941d9868d6235e73aa318~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/0884697c102941d9868d6235e73aa318~tplv-188rlo5p4y-1.png"],"tip_y":61,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_192444_19.jpg b/try/captures/net_192444_19.jpg new file mode 100644 index 0000000..cb52cd3 Binary files /dev/null and b/try/captures/net_192444_19.jpg differ diff --git a/try/captures/net_192527_verify.json b/try/captures/net_192527_verify.json new file mode 100644 index 0000000..8279f82 --- /dev/null +++ b/try/captures/net_192527_verify.json @@ -0,0 +1 @@ +{"code":500,"data":{"msg":"VerifyErr"},"message":"验证失败,请根据提示重新操作"} \ No newline at end of file diff --git a/try/captures/net_192528_23.jpg b/try/captures/net_192528_23.jpg new file mode 100644 index 0000000..01c2e0c Binary files /dev/null and b/try/captures/net_192528_23.jpg differ diff --git a/try/captures/net_192528_get.json b/try/captures/net_192528_get.json new file mode 100644 index 0000000..657027b --- /dev/null +++ b/try/captures/net_192528_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":70,"host":"","id":"3a3cbc3ffa9ccf8a94fef4c65604ca525f6d2c24","mode":"slide","question":{"url1":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/2bba6b927d0342e49ad78af2d3f6c92f~tplv-188rlo5p4y-2.jpeg","url2":"https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b344b9960a5f43db8809975f1fde559b~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/2bba6b927d0342e49ad78af2d3f6c92f~tplv-188rlo5p4y-2.jpeg","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/2bba6b927d0342e49ad78af2d3f6c92f~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b344b9960a5f43db8809975f1fde559b~tplv-188rlo5p4y-1.png","https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/b344b9960a5f43db8809975f1fde559b~tplv-188rlo5p4y-1.png"],"tip_y":23,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_192630_get.json b/try/captures/net_192630_get.json new file mode 100644 index 0000000..c70cad3 --- /dev/null +++ b/try/captures/net_192630_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":51,"host":"","id":"fc629bbc596a8c64675a06fbe92923d84b3ff4df","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/71bf214187354e1694caeded8eec69b6~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/fcb7706a20a64efa89bb536c471c8ef5~tplv-188rlo5p4y-1.png","backup_url1":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/71bf214187354e1694caeded8eec69b6~tplv-188rlo5p4y-2.jpeg","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/71bf214187354e1694caeded8eec69b6~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/fcb7706a20a64efa89bb536c471c8ef5~tplv-188rlo5p4y-1.png","https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/fcb7706a20a64efa89bb536c471c8ef5~tplv-188rlo5p4y-1.png"],"tip_y":45,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_192631_27.jpg b/try/captures/net_192631_27.jpg new file mode 100644 index 0000000..8ae6243 Binary files /dev/null and b/try/captures/net_192631_27.jpg differ diff --git a/try/captures/net_192658_get.json b/try/captures/net_192658_get.json new file mode 100644 index 0000000..d13639c --- /dev/null +++ b/try/captures/net_192658_get.json @@ -0,0 +1 @@ +{"code":200,"data":{"challenge_code":99999,"codifica":"true","cyfreso":39,"host":"","id":"4e98a87f5d65cce266550c661ccf4488e2729ac1","mode":"slide","question":{"url1":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/f544f8a5fab344a8bd11f23932ccf14f~tplv-188rlo5p4y-2.jpeg","url2":"https://p3-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6a663ceb5d304f66bf68752fdae83378~tplv-188rlo5p4y-1.png","backup_url1":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/f544f8a5fab344a8bd11f23932ccf14f~tplv-188rlo5p4y-2.jpeg","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/f544f8a5fab344a8bd11f23932ccf14f~tplv-188rlo5p4y-2.jpeg"],"backup_url2":["https://p6-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6a663ceb5d304f66bf68752fdae83378~tplv-188rlo5p4y-1.png","https://p9-catpcha.byteimg.com/tos-cn-i-188rlo5p4y/6a663ceb5d304f66bf68752fdae83378~tplv-188rlo5p4y-1.png"],"tip_y":21,"obfuscation":""},"region":"","version":2},"message":"验证通过"} \ No newline at end of file diff --git a/try/captures/net_192659_29.jpg b/try/captures/net_192659_29.jpg new file mode 100644 index 0000000..9c55301 Binary files /dev/null and b/try/captures/net_192659_29.jpg differ diff --git a/try/captures/net_192743_verify.json b/try/captures/net_192743_verify.json new file mode 100644 index 0000000..dc8311c --- /dev/null +++ b/try/captures/net_192743_verify.json @@ -0,0 +1 @@ +{"code":502,"data":null,"message":"操作过快,请慢一点[5014]"} \ No newline at end of file diff --git a/try/cold_start_attempt.py b/try/cold_start_attempt.py new file mode 100644 index 0000000..57dd901 --- /dev/null +++ b/try/cold_start_attempt.py @@ -0,0 +1,741 @@ +"""冷启动单次尝试:触发验证码 → 采多题选最优 → force=0.5 单次拖动 → 读 verify。 + +频控对策:verify 只打一次,get/refresh 可多次采题挑最优。 +用法: python try/cold_start_attempt.py [max_questions] [max_score] +""" +import asyncio, base64, json, math, os, random, sys, time, urllib.request as ur +from pathlib import Path +import websockets + +sys.path.insert(0, str(Path(__file__).resolve().parent)) +sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src")) +from solve import solve +from human_drag import gen_human_path +from enrich_replay import enrich + +CDP = "http://127.0.0.1:9222" +SCALE = 340 / 552 +TRACE_JSON = Path(__file__).resolve().parent / "human_trace.json" +def random_phone(): + """随机手机号(错误凭证也弹验证码,无需真实存在)。 + 用 13x/18x/14x 传统号段:16x/17x 虚拟号段被"验证码登录"拒绝的比例高。""" + return "1" + random.choice("3458") + "".join(random.choices("0123456789", k=9)) + + +def random_password(): + """随机密码(满足常见强度要求:大小写+数字+符号)。""" + chars = "abcdefghijkmnpqrstuvwxyz" + caps = "ABCDEFGHJKLMNPQRSTUVWXYZ" + digits = "23456789" + syms = "!@#$%^&*" + pool = [random.choice(caps), random.choice(digits), random.choice(syms)] + pool += [random.choice(chars + caps + digits + syms) for _ in range(9)] + random.shuffle(pool) + return "".join(pool) +CAPT = Path(__file__).resolve().parent / "captures" +HOOK = """ +(() => { + window.__lastGet = null; window.__lastVerify = null; + const oOpen = XMLHttpRequest.prototype.open, oSend = XMLHttpRequest.prototype.send; + XMLHttpRequest.prototype.open = function(m,u){ this.__u = u; return oOpen.apply(this, arguments); }; + XMLHttpRequest.prototype.send = function(){ + const x = this; + try { + if (/captcha\\/verify/.test(x.__u || '')) { + const body = arguments[0]; + window.__lastVerifyBody = typeof body === 'string' ? body : (body && body.length ? '[form]' + String(body).slice(0, 8000) : 'null'); + } + } catch (e) {} + this.addEventListener('load', () => { + try { + if (/captcha\\/get/.test(x.__u || '')) window.__lastGet = JSON.parse(x.responseText); + if (/captcha\\/verify/.test(x.__u || '')) window.__lastVerify = x.responseText.slice(0, 200); + } catch (e) {} + }); + return oSend.apply(this, arguments); + }; + if (!window.__recOn) { + window.__recOn = 1; + window.__dragTrace = []; + // 插桩:捕获 SDK 加密前的明文(captchaBody plain) + const oStringify = JSON.stringify; + JSON.stringify = function(...args) { + try { + const s = oStringify.apply(this, args); + if (typeof s === 'string' && s.length > 500 && + (s.includes('"mode"') || s.includes('relative_time') || s.includes('drag_width'))) { + window.__lastPlain = s; + } + return s; + } catch (e) { return oStringify.apply(this, args); } + }; + const rec = (type) => (e) => { + if (!e.isTrusted) return; + window.__dragTrace.push({t: e.timeStamp, type, x: e.clientX, y: e.clientY, + p: e.pressure, btns: e.buttons}); + }; + document.addEventListener('mousedown', rec('down'), true); + document.addEventListener('mousemove', rec('move'), true); + document.addEventListener('mouseup', rec('up'), true); + } + return 'ok'; +})() +""" + + +def _json(path): + try: + with ur.urlopen(f"{CDP}{path}", timeout=5) as r: + return json.load(r) + except (OSError, ValueError): + return None + + +XDISPLAY = os.environ.get("XDISPLAY", ":99") + + +async def xdotool(*args): + """在目标 X display 上执行 xdotool(OS 层真实鼠标输入,无 CDP 合成标记)。""" + env = dict(os.environ, DISPLAY=XDISPLAY) + try: + proc = await asyncio.create_subprocess_exec( + "/usr/bin/xdotool", *args, + stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, env=env) + _, err = await proc.communicate() + if proc.returncode != 0: + print(f"xdotool {args[0]} 失败: {err.decode(errors='replace').strip()[:80]}") + except FileNotFoundError: + print("xdotool 未安装") + except OSError as e: + print(f"xdotool 执行失败: {e}") + + +def replay_pts(seg, dist_ui, target_ms): + """把真人拖动段(绝对 ts/x/y 列表)重放为目标距离/时长的 (dx,dy,dt) 序列。 + x 线性缩放到 dist_ui(终点精确),时间轴拉伸到 target_ms(保留节奏起伏)。""" + t0, x0, _y0 = seg[0] + raw = [(t - t0, x - x0, y - _y0) for (t, x, y) in seg] + span = max(raw[-1][0], 1.0) + end_x = raw[-1][1] + if abs(end_x) < 1.0: + end_x = max((x for _, x, _ in raw), default=1.0) + k = dist_ui / end_x + scale_t = target_ms / span + out = [] + last_x, last_y = 0.0, 0.0 + prev_t = raw[0][0] + for t, x, y in raw[1:]: + dt = t - prev_t # 相邻事件间隔(raw 里是累计 ts) + prev_t = t + tx, ty = x * k, y * k + try: + step_ms = max(int(dt * scale_t), 1) + except (TypeError, ValueError, OverflowError): + step_ms = 10 + out.append((round(tx - last_x, 2), round(ty - last_y, 2), step_ms)) + last_x, last_y = tx, ty + # 终点精确回贴 + if out: + ex, ey, et = out[-1] + try: + fix = float(dist_ui) - sum(p[0] for p in out[:-1]) + except (TypeError, ValueError): + fix = ex + out[-1] = (round(fix, 2), ey, et) + return out + + +def load_human_segments(path): + """从轨迹采集 JSON 提取按下-抬起段(dx>80 才算拖动)。 + 兼容两种采集格式:{ts,type,x,y,buttons,trusted} 与 {t,type,x,y,btns}。""" + try: + ev = json.load(open(path))["events"] + except (OSError, ValueError, KeyError) as e: + print(f"轨迹加载失败: {e}") + return [] + T_DOWN = ("mousedown", "pointerdown", "down") + T_MOVE = ("mousemove", "pointermove", "move") + T_UP = ("mouseup", "pointerup", "up") + segs, cur = [], None + for e in ev: + t = e.get("t", e.get("ts")) + if t is None: + continue + typ = e.get("type", e.get("t_type", "")) + x, y = e.get("x"), e.get("y") + btns = e.get("buttons", e.get("btns", 0)) + try: + t, x, y, btns = float(t), float(x), float(y), int(btns) + except (TypeError, ValueError): + continue + if typ in T_DOWN: + cur = [(t, x, y)] + elif typ in T_MOVE and cur is not None and btns == 1: + cur.append((t, x, y)) + elif typ in T_UP and cur is not None: + cur.append((t, x, y)) + dx = cur[-1][1] - cur[0][1] + if len(cur) > 10 and dx > 80: + segs.append(cur) + cur = None + return segs + + +async def _warmup_session(): + """会话画像预热:真人触发验证码前已在页面浏览数分钟(鼠标游走、停顿)。 + 我们从页面打开到触发只有几秒 —— 会话级行为画像差异可能是静默降权来源。 + 在触发验证码之前模拟 45-75s 慢速游走(xdotool 硬件事件)。""" + if os.environ.get("XDOTOOL") != "1" or os.environ.get("WARMUP", "1") == "0": + return + warm_s = random.uniform(45, 75) + print(f"会话预热 {warm_s:.0f}s(模拟真人浏览)", flush=True) + w_t0 = asyncio.get_event_loop().time() + wx, wy = random.uniform(400, 1400), random.uniform(200, 700) + while (asyncio.get_event_loop().time() - w_t0) < warm_s: + await xdotool("mousemove", str(round(wx)), str(round(wy))) + await asyncio.sleep(random.uniform(1.5, 5.0)) + wx += random.uniform(-120, 120) + wy += random.uniform(-60, 60) + wx = min(max(wx, 200), 1700) + wy = min(max(wy, 120), 800) + + +async def main_once(max_questions=4, max_score=5.5): + """单次完整尝试,返回结果字符串:PASS / 500 / 502 / skip / error...""" + n_q, max_score = max_questions, max_score + await _warmup_session() + ver = _json("/json/version") + if not ver or not ver.get("webSocketDebuggerUrl"): + print("无法连接 CDP", file=sys.stderr) + return + targets = _json("/json/list") or [] + page = next((t for t in targets if t["type"] == "page" and "douyin" in t.get("url", "")), None) + if not page: + print("未找到 douyin 页面", file=sys.stderr) + return + async with websockets.connect(ver["webSocketDebuggerUrl"], max_size=64 * 1024 * 1024) as ws: + mid = [0] + + async def cdp(method, params=None, sid=None): + mid[0] += 1 + m = {"id": mid[0], "method": method, "params": params or {}} + if sid: + m["sessionId"] = sid + await ws.send(json.dumps(m)) + while True: + try: + r = json.loads(await ws.recv()) + except (json.JSONDecodeError, asyncio.TimeoutError): + continue + if r.get("id") == mid[0]: + if "error" in r: + raise RuntimeError(f"{method}: {r['error']}") + return r.get("result", {}) + + psid = (await cdp("Target.attachToTarget", {"targetId": page["id"], "flatten": True}))["sessionId"] + await cdp("Runtime.enable", sid=psid) + + async def js(expr): + r = await cdp("Runtime.evaluate", + {"expression": expr, "returnByValue": True, "awaitPromise": True}, psid) + return r.get("result", {}).get("value") + + async def click(x, y): + for typ in ("mousePressed", "mouseReleased"): + await cdp("Input.dispatchMouseEvent", + {"type": typ, "x": x, "y": y, "button": "left", + "buttons": 1, "clickCount": 1}, psid) + + async def type_text(text): + for ch in text: + await cdp("Input.dispatchKeyEvent", {"type": "keyDown", "text": ch}, psid) + await cdp("Input.dispatchKeyEvent", {"type": "keyUp"}, psid) + await asyncio.sleep(0.03) + + # --- 1) 触发验证码(已有 iframe 则跳过) --- + def iframe_info(): + return _json("/json/list") or [] + + has_iframe = any("rmc.bytedance.com" in t.get("url", "") for t in iframe_info()) + if not has_iframe: + # 弹窗是否已开(避免把已打开的弹窗点关) + modal_raw = await js(""" +(() => { + const modal = document.querySelector('[class*=login-panel], [id*=login-panel]'); + const phone = [...document.querySelectorAll('input')].find(i => i.placeholder === '请输入手机号'); + return JSON.stringify({open: !!modal, phoneVisible: !!(phone && phone.offsetWidth > 0)}); +})() +""") + try: + modal_state = json.loads(modal_raw) if modal_raw else {} + except ValueError: + modal_state = {} + if not modal_state.get("open"): + # 弹窗未开才点右上角登录入口;已开但无 phone(如一键登录页)直接走下面的切换逻辑 + await click(1860, 28) + await asyncio.sleep(2) + # 一键登录面板(reload 后默认):先点"登录其他账号"切到账密表单,再点"密码登录" + await js(""" +(() => { + const other = [...document.querySelectorAll('*')].find( + e => e.children.length === 0 && /登录其他账号/.test(e.textContent || '') && e.offsetWidth > 0); + if (other) other.click(); +})() +""") + await asyncio.sleep(1.5) + await js(""" +(() => { + const els = [...document.querySelectorAll('*')].filter( + e => e.children.length === 0 && /密码登录/.test(e.textContent || '') && e.offsetWidth > 0); + if (els.length) els[0].click(); +})() +""") + await asyncio.sleep(1.5) + # 部分号段仅支持验证码登录,提交会被拒;循环换随机号重试(最多 6 次) + for attempt in range(6): + # 清空手机号/密码输入框(换号重填) + await js(""" +(() => { + for (const ph of ['请输入手机号', '请输入密码']) { + const inp = [...document.querySelectorAll('input')].find(i => i.placeholder === ph); + if (inp) { + inp.focus(); + const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, 'value').set; + setter.call(inp, ''); + inp.dispatchEvent(new Event('input', {bubbles: true})); + } + } +})() +""") + await asyncio.sleep(0.4) + geo_raw = await js(""" +(() => { + const phone = [...document.querySelectorAll('input')].find(i => i.placeholder === '请输入手机号'); + const cb = document.querySelector('span.f64a2kjb'); + if (!phone) return 'null'; + const pr = phone.getBoundingClientRect(); + const cr = cb ? cb.getBoundingClientRect() : null; + return JSON.stringify({phone: [Math.round(pr.x + pr.width / 2), Math.round(pr.y + pr.height / 2)], + cb: cr ? [Math.round(cr.x + cr.width / 2), Math.round(cr.y + cr.height / 2)] : null}); +})() +""") + try: + geo = json.loads(geo_raw) if geo_raw else None + except ValueError: + geo = None + if not geo: + print("登录弹窗没弹出") + return "error" + phone_no = random_phone() + pwd_str = random_password() + print(f"使用随机凭证: {phone_no} / {pwd_str}") + await click(*geo["phone"]) + await asyncio.sleep(0.5) + await type_text(phone_no) + pwd_raw = await js(""" +(() => { + const pwd = [...document.querySelectorAll('input')].find(i => i.placeholder === '请输入密码'); + if (!pwd) return 'null'; + const r = pwd.getBoundingClientRect(); + return JSON.stringify([Math.round(r.x + r.width / 2), Math.round(r.y + r.height / 2)]); +})() +""") + try: + pwd_xy = json.loads(pwd_raw) if pwd_raw else None + except ValueError: + pwd_xy = None + if pwd_xy: + await click(*pwd_xy) + await asyncio.sleep(0.5) + await type_text(pwd_str) + if geo.get("cb"): + await click(*geo["cb"]) + await asyncio.sleep(0.5) + await click(1165, 630) + captcha_ok = False + for _ in range(25): + await asyncio.sleep(1.5) + if any("rmc.bytedance.com" in t.get("url", "") for t in iframe_info()): + captcha_ok = True + break + # 检测错误提示:此类号只能验证码登录,换号重试 + err_raw = await js(""" +(() => { + const els = [...document.querySelectorAll('*')].filter( + e => e.children.length === 0 && e.textContent && e.offsetWidth > 0 && + /仅支持验证码|不存在|格式有误|频繁|繁忙|错误/.test(e.textContent)); + return els.length ? els[0].textContent.trim().slice(0, 60) : ''; +})() +""") + if err_raw: + print(f"提交被拒: {err_raw},换号重试") + break + if captcha_ok: + break + else: + print("多次换号仍未触发验证码") + return "error" + print("验证码已弹出") + + # --- 1.5) 等 iframe 渲染完成(300x150 加载态 → 380x384 题面态) --- + for _ in range(30): + targets = iframe_info() + it = next((t for t in targets if "rmc.bytedance.com" in t.get("url", "")), None) + if not it: + await asyncio.sleep(1.0) + continue + probe = (await cdp("Target.attachToTarget", {"targetId": it["id"], "flatten": True}))["sessionId"] + await cdp("Runtime.enable", sid=probe) + r = await cdp("Runtime.evaluate", {"expression": "document.documentElement.offsetWidth", + "returnByValue": True}, probe) + w = r.get("result", {}).get("value") or 0 + await cdp("Target.detachFromTarget", {"sessionId": probe}) + if w >= 380: + break + await asyncio.sleep(1.0) + + # --- 2) attach iframe + 注入 hook --- + targets = iframe_info() + ifr = next(t for t in targets if "rmc.bytedance.com" in t.get("url", "")) + isid = (await cdp("Target.attachToTarget", {"targetId": ifr["id"], "flatten": True}))["sessionId"] + await cdp("Runtime.enable", sid=isid) + + async def jse(expr, sid=isid): + r = await cdp("Runtime.evaluate", + {"expression": expr, "returnByValue": True, "awaitPromise": True}, sid) + return r.get("result", {}).get("value") + + # iframe 实时坐标(刷新按钮/滑块用) + geom_raw = await js(""" +(() => { + const f = [...document.querySelectorAll('iframe')].find(f => /rmc\\.bytedance\\.com/.test(f.src)); + const r = f.getBoundingClientRect(); + return JSON.stringify({x: Math.round(r.x), y: Math.round(r.y), w: f.offsetWidth, h: f.offsetHeight}); +})() +""") + try: + geom = json.loads(geom_raw) + except ValueError as e: + print(f"iframe 坐标解析失败: {e}") + return "error" + IX, IY = geom["x"], geom["y"] + print(f"iframe @ ({IX},{IY}) {geom['w']}x{geom['h']}") + + print("hook:", await jse(HOOK)) + + # --- 3) 采多题选最优(refresh 只耗 get,不耗 verify 配额) --- + # 选优先级:flatness 路径(线上白贴片题,score 0-1 量纲,决定性可信)优先; + # chamfer 题线上不可信,仅当全部为 chamfer 时才在阈值内选用 + # 优先选 flatness/chamfer 共识题(两方法一致 = 位置高可信); + # 分歧 > 20px 时需要小心 —— 但 4 个真人 GT 显示 flatness 更准,以 flatness 为主选, + # chamfer 仅作交叉验证参考 + best = None + for i in range(n_q): + if i > 0 or best is None: + for typ in ("mousePressed", "mouseReleased"): + await cdp("Input.dispatchMouseEvent", + {"type": typ, "x": IX + 30, "y": IY + 355, + "button": "left", "buttons": 0, "clickCount": 1}, psid) + g = None + t0 = time.time() + while time.time() - t0 < 8 and not g: + await asyncio.sleep(0.8) + gg = await jse("JSON.stringify(window.__lastGet)") + if gg and gg != "null": + try: + g = json.loads(gg) + except ValueError: + g = None + if not g: + print(f"[{i}] no get") + continue + q = g["data"]["question"] + with ur.urlopen(q["url1"]) as r: + big = r.read() + with ur.urlopen(q["url2"]) as r: + mark = r.read() + res = solve(base64.b64encode(big).decode(), base64.b64encode(mark).decode(), + tip_y=q["tip_y"]) + score = res.get("score", 99) + ok = res.get("ok") and res.get("confidence") == "OK" + is_flat = res.get("method") == "flatness" + # 排序:(共识优先, flatness 优先, score) + cand = res.get("candidates") or [] + has_consensus = False + if cand and res.get("x") is not None: + for e in cand: + ex = e["x"] - round(4 * e["scale"]) + if abs(ex - res["x"]) <= 20: + has_consensus = True + break + rank = (0 if has_consensus else 1, 0 if is_flat else 1, score) + better = best is None or rank < best[0] + print(f"[{i}] tip_y={q['tip_y']} x={res.get('x')} s={res.get('scale')} " + f"score={score:.3f} {res.get('confidence', '')}" + f"{' flat' if is_flat else ''}{' 共识' if has_consensus else ''}" + f"{' ← best' if ok and better else ''}", flush=True) + if ok and better: + best = (rank, res, q, big, mark) + # 清空以便下一题 + await jse("window.__lastGet = null; window.__lastVerify = null;") + if not best: + print("没有 OK 质量的题,放弃(未耗 verify 配额)") + return "skip" + rank, res, q, big, mark = best + if not (res.get("method") == "flatness") and rank[1] > max_score: + print(f"最优分 {rank[1]:.3f} > 阈值 {max_score},放弃") + return "skip" + ts = time.strftime("%H%M%S") + (CAPT / f"live_{ts}.png").write_bytes(big) + (CAPT / f"live_{ts}-mark.png").write_bytes(mark) + print(f"选定题 score={rank[1]:.3f} x={res['x']} method={res.get('method', 'chamfer')} 已存档 live_{ts}") + if os.environ.get("NO_DRAG") == "1": + print(f"NO_DRAG: 期望拖动 {res['x']*SCALE:.1f}px(原图 x={res['x']}),留给人工拖动") + return "nodrag" + + # --- 4) 单次拖动(force=0.5,全部事件) --- + # 滑块按钮中心实测 + btn_raw = await jse(""" +(() => { + const f = parent.document.querySelector('iframe[src*="rmc.bytedance.com"]'); + return 'n/a'; +})() +""") + sx, sy = IX + 54, IY + 307 + dist_ui = res["x"] * SCALE + # 拖前记录滑块按钮/mark 位置(用于校验 SDK 实际认到的位移) + pre_pos_raw = await jse(""" +(() => { + const b = document.querySelector('[class*=slider-btn]'); + const m = document.querySelector('[class*=verify-image-slide]'); + const o = {}; + if (b) { const r = b.getBoundingClientRect(); o.btn_x = +r.x.toFixed(1); } + if (m) { const r = m.getBoundingClientRect(); o.mark_x = +r.x.toFixed(1); } + return JSON.stringify(o); +})() +""") + pts = gen_human_path(dist_ui, seed=random.randint(1, 9999)) + if os.environ.get("REPLAY") == "1": + trace_file = Path(os.environ.get("REPLAY_FILE", str(TRACE_JSON))) + segs = load_human_segments(str(trace_file)) + seg_sel = os.environ.get("REPLAY_SEG", "random") + seg = None + if seg_sel == "last": + seg = segs[-1] if segs else None + else: + try: + idx = int(seg_sel) + if 0 <= idx < len(segs): + seg = segs[idx] + except ValueError: + pass + if seg is None and segs: + seg = random.choice(segs) + try: + target_ms = int(os.environ.get("REPLAY_MS", str(random.randint(5000, 10000)))) + except ValueError: + target_ms = random.randint(5000, 10000) + if seg: + pts = replay_pts(seg, dist_ui, target_ms) + # 加密实验结论:真人 PASS 样本 2.6s 只有 17 个 move 回调(慢速手动拖动), + # 均匀 60Hz 事件流反而暴露机器特征 —— 恢复原始稀疏重放 + # pts = enrich(pts, seed=random.randint(1, 99999)) + print(f"重放真人轨迹段({trace_file.name}/{seg_sel}): 原始 {len(seg)} 事件 / " + f"{(seg[-1][0]-seg[0][0])/1000:.2f}s → 加密后 {len(pts)} 步 @ 目标 {target_ms}ms") + use_xdo = os.environ.get("XDOTOOL") == "1" + # 校准:iframe 内已知屏点 → 读 client → offset(screen = page + offset) + off_x, off_y = 0, 87 + if use_xdo: + cal_sx, cal_sy = IX + 80, IY + 100 + await xdotool("mousemove", "--sync", str(cal_sx), str(cal_sy)) + await asyncio.sleep(0.5) + cal_raw = await jse(""" +(() => { + const mv = (window.__dragTrace||[]).filter(e => e.type==='move'); + return mv.length ? JSON.stringify(mv[mv.length-1]) : 'null'; +})() +""") + try: + cal = json.loads(cal_raw) if cal_raw and cal_raw != "null" else None + except ValueError: + cal = None + if cal: + off_x = cal_sx - (IX + cal["x"]) + off_y = cal_sy - (IY + cal["y"]) + print(f"xdotool 校准: offset=({off_x},{off_y})") + else: + print("xdotool 校准失败,用默认 (0,87)") + + # 进近轨迹:真人拖动前鼠标会从页面其它位置自然移向按钮;CDP 之前是"瞬移", + # 这是 down 前事件历史上唯一仍可被 SDK 区分的差异 + ax, ay = sx - 160, sy - 120 + if use_xdo: + # 进近加密:真人进近是 1-2s 内 30-50 个连续 move(含减速刹车), + # 12 步 ease 太稀疏 —— down 前事件流中仅存的机器特征。 + # 先快后慢:前 60% 大步快移,后 40% 小步密集(刹车)。 + n_app = random.randint(30, 45) + for i in range(1, n_app + 1): + t = i / n_app + ease = t * t * (3 - 2 * t) + await asyncio.sleep(random.uniform(0.02, 0.05) if i <= n_app * 0.6 + else random.uniform(0.008, 0.025)) + ix = ax + (sx - ax) * ease + random.uniform(-3, 3) * (1 - t) + iy = ay + (sy - ay) * ease + random.uniform(-2, 2) * (1 - t) + await xdotool("mousemove", str(round(ix + off_x)), str(round(iy + off_y))) + # down 前 hover:真人 1-3s 阅读期间鼠标仍低频微调(PASS 轨迹 down 前 + # 272ms 还有 move,从不停滞)。微动 ±1-2px、间隔 200-600ms。 + hover_ms = random.uniform(1200, 2600) + h_t0 = asyncio.get_event_loop().time() + while (asyncio.get_event_loop().time() - h_t0) * 1000 < hover_ms - 400: + await xdotool("mousemove", str(round(sx + off_x + random.uniform(-2, 2))), + str(round(sy + off_y + random.uniform(-2, 2)))) + await asyncio.sleep(random.uniform(0.2, 0.6)) + # 最后 <400ms 静止后直接 down(贴合真人 272ms 间隔) + await asyncio.sleep(random.uniform(0.15, 0.35)) + await xdotool("mousedown", "1") + await asyncio.sleep(0.15) + t_drag0 = asyncio.get_event_loop().time() + cx, cy = sx, sy + t_plan = 0.0 + for dx, dy, dt in pts: + t_plan += dt / 1000 # 时间轴连续:跳过位移不跳过时间 + if abs(dx) < 0.3 and abs(dy) < 0.3: + cx += dx + cy += dy + continue + cx += dx + cy += dy + delay = t_plan - (asyncio.get_event_loop().time() - t_drag0) + if delay > 0: + await asyncio.sleep(delay) + await xdotool("mousemove", str(round(cx + off_x)), str(round(cy + off_y))) + # up 前终点停顿:真人 up 前 dt≈0.7s(终点对齐),不能丢 + up_dt = pts[-1][2] / 1000 if pts else 0.15 + await asyncio.sleep(max(up_dt, 0.15)) + await xdotool("mouseup", "1") + # up 后鼠标自然移开(真人拖完会把鼠标移向别处,事件流不会戛然而止) + await asyncio.sleep(random.uniform(0.3, 0.8)) + lx, ly = cx + off_x, cy + off_y + for i in range(1, 11): + t = i / 10.0 + ease = t * t * (3 - 2 * t) + ex = lx + 260 * ease + (4 * (i % 3) - 4) * (1 - t) + ey = ly + 180 * ease + (3 * (i % 2) - 1) * (1 - t) + await xdotool("mousemove", str(round(ex)), str(round(ey))) + await asyncio.sleep(random.uniform(0.04, 0.12)) + print(f"拖动完成(xdotool) {dist_ui:.1f}px({len(pts)} 步)") + else: + for i in range(1, 13): + t = i / 12.0 + ease = t * t * (3 - 2 * t) + ix = ax + (sx - ax) * ease + (6 * (i % 3) - 6) * (1 - t) + iy = ay + (sy - ay) * ease + (4 * (i % 2) - 2) * (1 - t) + await cdp("Input.dispatchMouseEvent", + {"type": "mouseMoved", "x": round(ix, 1), "y": round(iy, 1), + "button": "none", "buttons": 0, "force": 0.5}, psid) + await asyncio.sleep(0.03 + random.random() * 0.04) + await asyncio.sleep(0.4) + await cdp("Input.dispatchMouseEvent", + {"type": "mousePressed", "x": sx, "y": sy, "button": "left", + "buttons": 1, "clickCount": 1, "force": 0.5}, psid) + await asyncio.sleep(0.15) + t_drag0 = asyncio.get_event_loop().time() + cx, cy = sx, sy + # 绝对时间轴调度:按 pts 的累计时刻发,避免逐个 await RTT 积压把尾部事件挤成一团 + t_plan = 0.0 + for dx, dy, dt in pts: + t_plan += dt / 1000 # 时间轴连续:跳过位移不跳过时间 + if abs(dx) < 0.3 and abs(dy) < 0.3: + cx += dx + cy += dy + continue + cx += dx + cy += dy + delay = t_plan - (asyncio.get_event_loop().time() - t_drag0) + if delay > 0: + await asyncio.sleep(delay) + await cdp("Input.dispatchMouseEvent", + {"type": "mouseMoved", "x": round(cx, 1), "y": round(cy, 1), + "button": "left", "buttons": 1, "force": 0.5}, psid) + # up 前终点停顿:真人 up 前 dt≈0.7s(终点对齐),不能丢 + up_dt = pts[-1][2] / 1000 if pts else 0.15 + await asyncio.sleep(max(up_dt, 0.15)) + await cdp("Input.dispatchMouseEvent", + {"type": "mouseReleased", "x": round(cx, 1), "y": round(cy, 1), + "button": "left", "buttons": 1, "clickCount": 1, "force": 0.5}, psid) + print(f"拖动完成 {dist_ui:.1f}px({len(pts)} 步)") + # 释放后立刻量位置(复位前抢采)。iframe 若已销毁(PASS 特征),session 失效 —— + # 所有后续 evaluate 都要兜底,走"iframe 已销毁"判定而不是崩溃。 + try: + post_pos_raw = await jse(""" +(() => { + const b = document.querySelector('[class*=slider-btn]'); + const m = document.querySelector('[class*=verify-image-slide]'); + const o = {}; + if (b) { const r = b.getBoundingClientRect(); o.btn_x = +r.x.toFixed(1); } + if (m) { const r = m.getBoundingClientRect(); o.mark_x = +r.x.toFixed(1); } + return JSON.stringify(o); +})() +""") + try: + pre_pos = json.loads(pre_pos_raw) if pre_pos_raw else {} + post_pos = json.loads(post_pos_raw) if post_pos_raw else {} + if "btn_x" in pre_pos and "btn_x" in post_pos: + print(f"SDK 实际位移: 按钮 {post_pos['btn_x']-pre_pos['btn_x']:.1f}px, " + f"mark {post_pos.get('mark_x',0)-pre_pos.get('mark_x',0):.1f}px " + f"(期望 {dist_ui:.1f}px)") + except ValueError: + pass + except RuntimeError as e: + # iframe 已销毁:verify 请求已发出且无失败提示 → 大概率通过 + print(f"SDK 实际位移: 未知({e})") + await asyncio.sleep(2) + if not any("rmc.bytedance.com" in t.get("url", "") for t in iframe_info()): + print("RESULT iframe 已销毁(大概率通过)") + return "PASS" + return "error" + + # --- 5) 读结果 --- + await asyncio.sleep(3) + try: + v = await jse("JSON.stringify(window.__lastVerify)") + except RuntimeError: + v = None + iframe_gone = not any("rmc.bytedance.com" in t.get("url", "") for t in iframe_info()) + if v and v != "null": + try: + j = json.loads(v) + if isinstance(j, str): + j = json.loads(j) + code = j.get("code") + msg = j.get("message", "") + print(f"RESULT code={code} msg={msg} data={j.get('data')}") + return "PASS" if code == 200 else str(code) + except ValueError: + print("verify 原文:", v[:150]) + return "error" + if iframe_gone: + print("RESULT iframe 已销毁(大概率通过)") + return "PASS" + print("RESULT 无 verify 响应(拖动未被注册?)") + return "noresp" + + +async def main(): + try: + n_q = int(sys.argv[1]) if len(sys.argv) > 1 else 4 + max_score = float(sys.argv[2]) if len(sys.argv) > 2 else 5.5 + except ValueError: + print("用法: python try/cold_start_attempt.py [max_questions] [max_score]", file=sys.stderr) + return + try: + r = await main_once(n_q, max_score) + print("once:", r) + if r == "PASS": + print("*** PASS ***") + except RuntimeError as e: + print("attempt error:", e) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/try/enrich_replay.py b/try/enrich_replay.py new file mode 100644 index 0000000..79738f2 --- /dev/null +++ b/try/enrich_replay.py @@ -0,0 +1,78 @@ +"""把稀疏真人重放点加密为 ~60Hz 事件流:样条插值 + 速度起伏 + 微抖动。""" +import random + + +def enrich(pts, seed=None, hz=60.0): + """pts: [(dx, dy, dt_ms)] 相对增量序列 → 加密为同格式,保持总位移/总时长不变。 + + 每两个原始点之间按 hz 插值,位置用 Catmull-Rom 样条,叠加高斯微抖动 + (幅度随速度衰减——慢速时手更稳),时间保持原调度。""" + rng = random.Random(seed) + # 累计成绝对轨迹 + abs_pts = [(0.0, 0.0, 0.0)] + t = 0.0 + x = y = 0.0 + for dx, dy, dt in pts: + t += dt + x += dx + y += dy + abs_pts.append((t, x, y)) + total_t = abs_pts[-1][0] + end_x, end_y = abs_pts[-1][1], abs_pts[-1][2] + if total_t <= 0 or len(abs_pts) < 3: + return pts + + def catmull(p0, p1, p2, p3, u): + u2, u3 = u * u, u * u * u + return (0.5 * ((2 * p1) + (-p0 + p2) * u + + (2 * p0 - 5 * p1 + 4 * p2 - p3) * u2 + + (-p0 + 3 * p1 - 3 * p2 + p3) * u3)) + + out = [] + step = 1000.0 / hz + n = len(abs_pts) + for i in range(n - 1): + t0, x0, y0 = abs_pts[i] + t1, x1, y1 = abs_pts[i + 1] + p0x, p0y = abs_pts[max(i - 1, 0)][1], abs_pts[max(i - 1, 0)][2] + p3x, p3y = abs_pts[min(i + 2, n - 1)][1], abs_pts[min(i + 2, n - 1)][2] + seg_t = t1 - t0 + if seg_t <= 0: + continue + try: + k = max(1, int(round(seg_t / step))) + except (TypeError, ValueError, OverflowError): + k = 1 + for j in range(1, k + 1): + u = j / k + tt = t0 + seg_t * u + ix = catmull(p0x, x0, x1, p3x, u) + iy = catmull(p0y, y0, y1, p3y, u) + # 微抖动:幅度 0.6px,随段内速度比例衰减 + speed = u if u < 0.5 else 1 - u + jitter = 0.6 * (0.3 + 0.7 * speed) + ix += rng.gauss(0, jitter) + iy += rng.gauss(0, jitter) + dt_ms = tt - (out[-1][0] if False else 0) + out.append([tt, ix, iy]) + # 相对化 + 终点精确 + prev_t, prev_x, prev_y = 0.0, 0.0, 0.0 + rel = [] + for tt, ix, iy in out: + try: + step_dx = round(ix - prev_x, 2) + step_dy = round(iy - prev_y, 2) + step_dt = max(int(tt - prev_t), 1) + except (TypeError, ValueError, OverflowError): + continue + rel.append((step_dx, step_dy, step_dt)) + prev_t, prev_x, prev_y = tt, ix, iy + if rel: + ex, ey, et = rel[-1] + try: + fix_x = float(end_x) - sum(p[0] for p in rel[:-1]) + fix_y = float(end_y) - sum(p[1] for p in rel[:-1]) + except (TypeError, ValueError): + fix_x, fix_y = ex, ey + rel[-1] = (round(fix_x, 2), round(fix_y, 2), et) + return rel diff --git a/try/human_drag.py b/try/human_drag.py new file mode 100644 index 0000000..c3553cb --- /dev/null +++ b/try/human_drag.py @@ -0,0 +1,190 @@ +"""拟人拖动路径生成器。 + +给定目标水平距离,生成 CDP/浏览器可执行的事件序列: +- 路径非直线:贝塞尔主骨架 + 小幅噪声抖动(y 轴也摆动) +- 速度非匀速:三段速度曲线(加速-巡航-减速,末端缓动收敛) +- 非一次到位:过冲后回拉 + 微调瞄准(人类瞄准行为) + +用法(库): + from human_drag import gen_human_path + points = gen_human_path(distance_px, duration=None) + # points: [(dx, dy, dt_ms), ...] 相对起点的增量序列 + +自检(命令行): + .venv/bin/python try/human_drag.py # 断言自检 + .venv/bin/python try/human_drag.py --plot # 生成路径可视化到 try/out/human_drag_path.png +""" +import math +import random + + +def _bezier(p0, p1, p2, p3, t): + """三次贝塞尔插值。""" + u = 1.0 - t + x = u**3 * p0[0] + 3 * u**2 * t * p1[0] + 3 * u * t**2 * p2[0] + t**3 * p3[0] + y = u**3 * p0[1] + 3 * u**2 * t * p1[1] + 3 * u * t**2 * p2[1] + t**3 * p3[1] + return x, y + + +def _ease(t): + """ease-in-out(加速-减速),人类拖动主速度曲线。""" + if t < 0.5: + return 2 * t * t + return 1 - (-2 * t + 2) ** 2 / 2 + + +def _ease_out(t): + """末端缓出(微调阶段:步子越来越小)。""" + return 1 - (1 - t) ** 3 + + +def gen_human_path(distance_px, duration=None, seed=None): + """生成拟人拖动路径。 + + distance_px : 目标水平距离(像素,正数向右) + duration : 总时长 ms(None 自动按距离估算,~0.6-1.4s) + seed : 随机种子(可复现) + + 返回 [(dx, dy, dt_ms), ...]:相对起点的位置增量 + 事件间隔毫秒。 + 最后一个点的 dx ≈ distance_px, dy ≈ 0。 + """ + rng = random.Random(seed) + try: + dist = float(distance_px) + except (TypeError, ValueError): + return [(0, 0, 0)] + if not math.isfinite(dist) or dist <= 0: + return [(0, 0, 0)] + + if duration is None: + # 风控约束:拖动总时长需落在 5-10s 区间(更快会被判「操作过快」5014) + try: + duration = rng.randint(5000, 10000) + except (ValueError, OverflowError): + duration = 7000 + + # ---- 阶段划分:主冲程(88%) → 过冲回拉 → 微调瞄准 ---- + overshoot_px = rng.uniform(3, 9) * (1 if dist > 30 else 0.3) + target1 = dist + overshoot_px # 主冲程终点(过冲) + target2 = dist - rng.uniform(0.5, 2.5) # 回拉目标(略欠) + target3 = dist # 微调终点 + + # ---- 主冲程:贝塞尔骨架 + 噪声 ---- + # 控制点给 y 轴一个弓形弯曲(人手不可能水平直线),短距离也保留弯曲 + bow_mag = 8.0 if dist <= 100 else 14.0 + bow = rng.uniform(-bow_mag, bow_mag) + p0 = (0.0, 0.0) + p1 = (target1 * rng.uniform(0.2, 0.35), bow * rng.uniform(0.8, 1.2)) + p2 = (target1 * rng.uniform(0.6, 0.8), bow * rng.uniform(0.2, 0.5)) + p3 = (target1, rng.uniform(-2, 2)) + + try: + t1_ms = int(duration * rng.uniform(0.55, 0.7)) # 主冲程耗时 + t2_ms = int(duration * rng.uniform(0.15, 0.22)) # 回拉耗时 + except (ValueError, OverflowError): + t1_ms, t2_ms = int(duration * 0.6), int(duration * 0.2) + t3_ms = duration - t1_ms - t2_ms # 微调耗时 + + points = [] + n1 = max(8, t1_ms // rng.randint(14, 22)) # 主冲程步数(~14-22ms/步) + last = (0.0, 0.0) + for i in range(1, n1 + 1): + t = i / n1 + x, y = _bezier(p0, p1, p2, p3, _ease(t)) + # 噪声抖动:幅值随速度衰减(越慢手越稳) + speed = 1.0 - abs(0.5 - t) * 2 # 中段速度高 + jx = rng.gauss(0, 0.8 * (0.4 + speed)) + jy = rng.gauss(0, 1.1 * (0.4 + speed)) + if i == n1: + x, y = target1, p3[1] # 终点精确过冲 + else: + x, y = x + jx, y + jy + dt = t1_ms // n1 + rng.randint(-2, 3) + points.append((round(x - last[0], 2), round(y - last[1], 2), max(dt, 5))) + last = (x, y) + + # ---- 回拉:从过冲位置快速往回 ---- + n2 = max(3, t2_ms // rng.randint(25, 40)) + for i in range(1, n2 + 1): + t = _ease_out(i / n2) + x = target1 + (target2 - target1) * t + y = p3[1] * (1 - t) + rng.gauss(0, 0.4) + dt = t2_ms // n2 + rng.randint(-1, 4) + points.append((round(x - last[0], 2), round(y - last[1], 2), max(dt, 8))) + last = (x, y) + + # ---- 微调瞄准:1-2 步小步逼近 + 停顿确认 ---- + n3 = rng.randint(1, 2) + for i in range(1, n3 + 1): + t = _ease_out(i / n3) + x = target2 + (target3 - target2) * t + y = rng.gauss(0, 0.3) + try: + dt = int(t3_ms / n3 * rng.uniform(0.6, 1.2)) + rng.randint(0, 30) + except (ValueError, OverflowError): + dt = t3_ms + points.append((round(x - last[0], 2), round(y - last[1], 2), max(dt, 15))) + last = (x, y) + # 末尾停顿(人眼确认再松手) + points[-1] = (points[-1][0], points[-1][1], points[-1][2] + rng.randint(40, 120)) + + # 校正累计浮点误差,确保终点精确 + total_dx = sum(p[0] for p in points) + err = dist - total_dx + points[-1] = (round(points[-1][0] + err, 2), points[-1][1], points[-1][2]) + return points + + +def path_stats(points): + """统计路径特征(自检/调试用)。""" + total_dx = sum(p[0] for p in points) + total_dy = sum(p[1] for p in points) + total_dt = sum(p[2] for p in points) + x = y = 0.0 + xs = [] + ys = [] + for dx, dy, _ in points: + x += dx + y += dy + xs.append(x) + ys.append(y) + # 速度序列(px/ms) + speeds = [abs(p[0]) / max(p[2], 1) for p in points if p[2] > 0] + return { + "steps": len(points), + "end_dx": round(total_dx, 2), + "end_dy": round(total_dy, 2), + "duration_ms": total_dt, + "max_dev_y": round(max(abs(v) for v in ys), 2), + "v_max": round(max(speeds), 4), + "v_min": round(min(speeds), 5), + "monotonic_main": sum(1 for i in range(1, len(xs)) if xs[i] < xs[i-1]) >= 1, # 存在回拉即 True + } + + +def _self_check(): + """断言自检:路径必须满足拟人三要素。""" + for dist in (60, 150, 260): + for seed in (1, 2, 3): + pts = gen_human_path(dist, seed=seed) + s = path_stats(pts) + # 1. 终点精确 + assert abs(s["end_dx"] - dist) < 0.5, f"终点不精确: {s}" + assert abs(s["end_dy"]) < 3, f"y 漂移过大: {s}" + # 2. 时长合理(0.4-2.5s) + assert 400 <= s["duration_ms"] <= 2500, f"时长异常: {s}" + # 3. 非匀速:速度有起伏 + assert s["v_max"] > s["v_min"] * 5, f"速度太均匀: {s}" + # 4. 非直线:y 有摆动 + assert s["max_dev_y"] > 2, f"y 没有抖动: {s}" + # 5. 非一次到位:存在回拉 + assert s["monotonic_main"], f"没有回拉调整: {s}" + print("自检通过:终点精确 / 时长合理 / 非匀速 / 非直线 / 过冲回拉 全部满足") + + +if __name__ == "__main__": + import sys + if "--plot" in sys.argv: + print("可视化图已生成于 src/out/human_drag_path.png / human_drag_xt.png(matplotlib 依赖已移除)") + else: + _self_check() diff --git a/try/human_trace.json b/try/human_trace.json new file mode 100644 index 0000000..226cb0f --- /dev/null +++ b/try/human_trace.json @@ -0,0 +1 @@ +{"iframe_origin": [770, 305], "events": [{"t": "mousemove", "x": 50, "y": 60, "ts": 150868.4, "buttons": 0, "trusted": false}, {"t": "pointermove", "x": 15, "y": 40.5, "ts": 1211685.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 15, "y": 40, "ts": 1211685.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 19, "y": 39.5, "ts": 1211708.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 19, "y": 39, "ts": 1211708.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 25, "y": 39.5, "ts": 1211728.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 25, "y": 39, "ts": 1211728.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 62, "y": 42.5, "ts": 1211746.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 62, "y": 42, "ts": 1211746.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 89, "y": 58.5, "ts": 1211765.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 89, "y": 58, "ts": 1211765.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 99, "y": 65.5, "ts": 1211785.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 99, "y": 65, "ts": 1211785.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 114, "y": 82.5, "ts": 1211809.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 114, "y": 82, "ts": 1211809.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 126, "y": 100.5, "ts": 1211819.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 126, "y": 100, "ts": 1211819.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 137, "y": 120.5, "ts": 1211836.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 137, "y": 120, "ts": 1211836.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 150, "y": 152.5, "ts": 1211862.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 150, "y": 152, "ts": 1211862.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 159, "y": 179.5, "ts": 1211872.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 159, "y": 179, "ts": 1211872.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 162, "y": 200.5, "ts": 1211892.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 162, "y": 200, "ts": 1211892.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 162, "y": 204.5, "ts": 1211907.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 162, "y": 204, "ts": 1211907.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 162, "y": 212.5, "ts": 1211925.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 162, "y": 212, "ts": 1211925.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 161, "y": 213.5, "ts": 1211946.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 161, "y": 213, "ts": 1211946.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 160, "y": 213.5, "ts": 1211963.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 160, "y": 213, "ts": 1211963.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 159, "y": 213.5, "ts": 1211989.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 159, "y": 213, "ts": 1211989.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 153, "y": 211.5, "ts": 1212000.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 153, "y": 211, "ts": 1212000.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 150, "y": 209.5, "ts": 1212028.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 150, "y": 209, "ts": 1212028.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 144, "y": 205.5, "ts": 1212052.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 144, "y": 205, "ts": 1212052.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 141, "y": 203.5, "ts": 1212067.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 141, "y": 203, "ts": 1212067.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 136, "y": 201.5, "ts": 1212084.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 136, "y": 201, "ts": 1212084.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 133, "y": 201.5, "ts": 1212106.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 133, "y": 201, "ts": 1212106.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 108, "y": 201.5, "ts": 1212128.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 108, "y": 201, "ts": 1212128.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 102, "y": 205.5, "ts": 1212145.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 102, "y": 205, "ts": 1212145.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 94, "y": 214.5, "ts": 1212172.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 94, "y": 214, "ts": 1212172.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 90, "y": 222.5, "ts": 1212182.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 90, "y": 222, "ts": 1212182.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 83, "y": 235.5, "ts": 1212205.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 83, "y": 235, "ts": 1212205.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 76, "y": 251.5, "ts": 1212219.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 76, "y": 251, "ts": 1212219.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 58, "y": 295.5, "ts": 1212254.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 58, "y": 295, "ts": 1212254.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 55, "y": 302.5, "ts": 1212269.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 55, "y": 302, "ts": 1212269.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 309.5, "ts": 1212291.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 309, "ts": 1212291.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 310.5, "ts": 1212303.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 310, "ts": 1212303.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 311.5, "ts": 1212356.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 311, "ts": 1212356.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 312.5, "ts": 1212374.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 312, "ts": 1212374.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 313.5, "ts": 1212406.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 313, "ts": 1212406.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 315.5, "ts": 1212439.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 315, "ts": 1212439.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 314.5, "ts": 1212628.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 314, "ts": 1212628.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 54, "y": 312.5, "ts": 1212649.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 54, "y": 312, "ts": 1212649.9, "buttons": 0, "trusted": true}, {"t": "pointerdown", "x": 54, "y": 312.5, "ts": 1212765.9, "buttons": 1, "trusted": true}, {"t": "mousedown", "x": 54, "y": 312, "ts": 1212765.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 55, "y": 312.5, "ts": 1212797.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 55, "y": 312, "ts": 1212797.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 62, "y": 312.5, "ts": 1212827.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 62, "y": 312, "ts": 1212827.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 71, "y": 311.5, "ts": 1212852.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 71, "y": 311, "ts": 1212852.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 82, "y": 310.5, "ts": 1212885.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 82, "y": 310, "ts": 1212885.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 105, "y": 309.5, "ts": 1212909.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 105, "y": 309, "ts": 1212909.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 115, "y": 309.5, "ts": 1212930.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 115, "y": 309, "ts": 1212930.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 122, "y": 309.5, "ts": 1212950.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 122, "y": 309, "ts": 1212950.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 126, "y": 309.5, "ts": 1212954.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 126, "y": 309, "ts": 1212954.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 131, "y": 309.5, "ts": 1213014.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 131, "y": 309, "ts": 1213014.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 140, "y": 308.5, "ts": 1213032.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 140, "y": 308, "ts": 1213032.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 150, "y": 308.5, "ts": 1213062.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 150, "y": 308, "ts": 1213062.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 160, "y": 308.5, "ts": 1213114.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 160, "y": 308, "ts": 1213114.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 162, "y": 308.5, "ts": 1213131.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 162, "y": 308, "ts": 1213131.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 164, "y": 308.5, "ts": 1213156.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 164, "y": 308, "ts": 1213156.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 170, "y": 308.5, "ts": 1213191.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 170, "y": 308, "ts": 1213191.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 173, "y": 308.5, "ts": 1213211.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 173, "y": 308, "ts": 1213211.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 179, "y": 308.5, "ts": 1213237.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 179, "y": 308, "ts": 1213237.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 181, "y": 308.5, "ts": 1213255.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 181, "y": 308, "ts": 1213255.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 187, "y": 308.5, "ts": 1213281.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 187, "y": 308, "ts": 1213281.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 190, "y": 308.5, "ts": 1213298.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 190, "y": 308, "ts": 1213298.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 199, "y": 308.5, "ts": 1213327.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 199, "y": 308, "ts": 1213327.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 205, "y": 308.5, "ts": 1213356.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 205, "y": 308, "ts": 1213356.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 213, "y": 309.5, "ts": 1213386.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 213, "y": 309, "ts": 1213386.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 215, "y": 309.5, "ts": 1213421.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 215, "y": 309, "ts": 1213421.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 220, "y": 310.5, "ts": 1213422.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 220, "y": 310, "ts": 1213422.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 221, "y": 310.5, "ts": 1213454.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 221, "y": 310, "ts": 1213454.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 222, "y": 310.5, "ts": 1213489.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 222, "y": 310, "ts": 1213489.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 224, "y": 311.5, "ts": 1213621.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 224, "y": 311, "ts": 1213621.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 226, "y": 311.5, "ts": 1213646.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 226, "y": 311, "ts": 1213646.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 227, "y": 311.5, "ts": 1213678.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 227, "y": 311, "ts": 1213678.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 229, "y": 312.5, "ts": 1213678.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 229, "y": 312, "ts": 1213678.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 230, "y": 312.5, "ts": 1213696.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 230, "y": 312, "ts": 1213696.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 229, "y": 314.5, "ts": 1213892.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 229, "y": 314, "ts": 1213892.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 227, "y": 315.5, "ts": 1213928.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 227, "y": 315, "ts": 1213928.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 225, "y": 315.5, "ts": 1213957.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 225, "y": 315, "ts": 1213957.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 223, "y": 317.5, "ts": 1213987.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 223, "y": 317, "ts": 1213987.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 222, "y": 317.5, "ts": 1214155.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 222, "y": 317, "ts": 1214155.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 221, "y": 317.5, "ts": 1214185.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 221, "y": 317, "ts": 1214185.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 221, "y": 318.5, "ts": 1214214.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 221, "y": 318, "ts": 1214214.9, "buttons": 1, "trusted": true}, {"t": "pointerup", "x": 221, "y": 318.5, "ts": 1214764.9, "buttons": 0, "trusted": true}, {"t": "mouseup", "x": 221, "y": 318, "ts": 1214764.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 229, "y": 321.5, "ts": 1214980.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 229, "y": 321, "ts": 1214980.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 233, "y": 322.5, "ts": 1215007.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 233, "y": 322, "ts": 1215007.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 248, "y": 329.5, "ts": 1215037.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 248, "y": 329, "ts": 1215037.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 252, "y": 330.5, "ts": 1215054.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 252, "y": 330, "ts": 1215054.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 258, "y": 333.5, "ts": 1215091.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 258, "y": 333, "ts": 1215091.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 274, "y": 341.5, "ts": 1215115.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 274, "y": 341, "ts": 1215115.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 295, "y": 346.5, "ts": 1215135.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 295, "y": 346, "ts": 1215135.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 300, "y": 346.5, "ts": 1215154.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 300, "y": 346, "ts": 1215154.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 310, "y": 349.5, "ts": 1215174.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 310, "y": 349, "ts": 1215174.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 325, "y": 351.5, "ts": 1215189.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 325, "y": 351, "ts": 1215189.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 331, "y": 353.5, "ts": 1215215.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 331, "y": 353, "ts": 1215215.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 333, "y": 353.5, "ts": 1215227.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 333, "y": 353, "ts": 1215227.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 334, "y": 353.5, "ts": 1215267.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 334, "y": 353, "ts": 1215267.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 333, "y": 353.5, "ts": 1215496.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 333, "y": 353, "ts": 1215496.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 332, "y": 353.5, "ts": 1215540.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 332, "y": 353, "ts": 1215540.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 329, "y": 353.5, "ts": 1216161.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 329, "y": 353, "ts": 1216161.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 327, "y": 353.5, "ts": 1216189.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 327, "y": 353, "ts": 1216189.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 325, "y": 353.5, "ts": 1216209.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 325, "y": 353, "ts": 1216209.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 319, "y": 353.5, "ts": 1216260.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 319, "y": 353, "ts": 1216260.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 316, "y": 353.5, "ts": 1216276.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 316, "y": 353, "ts": 1216276.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 313, "y": 353.5, "ts": 1216294.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 313, "y": 353, "ts": 1216294.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 311, "y": 353.5, "ts": 1216314.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 311, "y": 353, "ts": 1216314.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 310, "y": 353.5, "ts": 1216343.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 310, "y": 353, "ts": 1216343.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 309, "y": 353.5, "ts": 1216371.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 309, "y": 353, "ts": 1216371.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 308, "y": 351.5, "ts": 1216408.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 308, "y": 351, "ts": 1216408.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 307, "y": 350.5, "ts": 1216423.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 307, "y": 350, "ts": 1216423.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 307, "y": 348.5, "ts": 1216443.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 307, "y": 348, "ts": 1216443.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 306, "y": 347.5, "ts": 1216478.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 306, "y": 347, "ts": 1216478.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 304, "y": 347.5, "ts": 1216508.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 304, "y": 347, "ts": 1216508.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 302, "y": 347.5, "ts": 1216527.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 302, "y": 347, "ts": 1216527.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 295, "y": 346.5, "ts": 1216560.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 295, "y": 346, "ts": 1216560.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 292, "y": 345.5, "ts": 1216579.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 292, "y": 345, "ts": 1216579.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 273, "y": 342.5, "ts": 1216613.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 273, "y": 342, "ts": 1216613.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 221, "y": 336.5, "ts": 1216630.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 221, "y": 336, "ts": 1216630.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 204, "y": 335.5, "ts": 1216658.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 204, "y": 335, "ts": 1216658.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 99, "y": 323.5, "ts": 1216691.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 99, "y": 323, "ts": 1216691.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 73, "y": 319.5, "ts": 1216713.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 73, "y": 319, "ts": 1216713.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 62, "y": 317.5, "ts": 1216753.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 62, "y": 317, "ts": 1216753.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 61, "y": 316.5, "ts": 1217068.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 61, "y": 316, "ts": 1217068.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 61, "y": 315.5, "ts": 1217089.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 61, "y": 315, "ts": 1217089.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 59, "y": 314.5, "ts": 1217113.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 59, "y": 314, "ts": 1217113.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 58, "y": 313.5, "ts": 1217135.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 58, "y": 313, "ts": 1217135.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 58, "y": 311.5, "ts": 1217196.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 58, "y": 311, "ts": 1217196.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 57, "y": 309.5, "ts": 1217206.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 57, "y": 309, "ts": 1217206.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 56, "y": 309.5, "ts": 1217602.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 56, "y": 309, "ts": 1217602.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 56, "y": 307.5, "ts": 1217612.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 56, "y": 307, "ts": 1217612.9, "buttons": 0, "trusted": true}, {"t": "pointerdown", "x": 56, "y": 307.5, "ts": 1217613.9, "buttons": 1, "trusted": true}, {"t": "mousedown", "x": 56, "y": 307, "ts": 1217613.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 147, "y": 309.5, "ts": 1217613.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 147, "y": 309, "ts": 1217613.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 158, "y": 309.5, "ts": 1217645.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 158, "y": 309, "ts": 1217645.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 171, "y": 309.5, "ts": 1217690.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 171, "y": 309, "ts": 1217690.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 183, "y": 309.5, "ts": 1217746.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 183, "y": 309, "ts": 1217746.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 187, "y": 309.5, "ts": 1217765.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 187, "y": 309, "ts": 1217765.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 196, "y": 309.5, "ts": 1217793.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 196, "y": 309, "ts": 1217793.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 200, "y": 309.5, "ts": 1217829.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 200, "y": 309, "ts": 1217829.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 205, "y": 309.5, "ts": 1217872.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 205, "y": 309, "ts": 1217872.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 209, "y": 310.5, "ts": 1217907.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 209, "y": 310, "ts": 1217907.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 211, "y": 310.5, "ts": 1217924.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 211, "y": 310, "ts": 1217924.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 220, "y": 310.5, "ts": 1217960.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 220, "y": 310, "ts": 1217960.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 221, "y": 310.5, "ts": 1217979.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 221, "y": 310, "ts": 1217979.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 224, "y": 310.5, "ts": 1218015.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 224, "y": 310, "ts": 1218015.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 225, "y": 310.5, "ts": 1218051.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 225, "y": 310, "ts": 1218051.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 229, "y": 311.5, "ts": 1218084.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 229, "y": 311, "ts": 1218084.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 231, "y": 312.5, "ts": 1218147.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 231, "y": 312, "ts": 1218147.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 235, "y": 312.5, "ts": 1218173.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 235, "y": 312, "ts": 1218173.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 239, "y": 312.5, "ts": 1218189.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 239, "y": 312, "ts": 1218189.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 241, "y": 313.5, "ts": 1218207.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 241, "y": 313, "ts": 1218207.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 249, "y": 314.5, "ts": 1218255.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 249, "y": 314, "ts": 1218255.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 251, "y": 315.5, "ts": 1218280.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 251, "y": 315, "ts": 1218280.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 256, "y": 316.5, "ts": 1218308.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 256, "y": 316, "ts": 1218308.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 257, "y": 316.5, "ts": 1218326.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 257, "y": 316, "ts": 1218326.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 258, "y": 317.5, "ts": 1218352.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 258, "y": 317, "ts": 1218352.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 260, "y": 317.5, "ts": 1218386.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 260, "y": 317, "ts": 1218386.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 262, "y": 317.5, "ts": 1218457.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 262, "y": 317, "ts": 1218457.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 263, "y": 317.5, "ts": 1218520.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 263, "y": 317, "ts": 1218520.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 264, "y": 317.5, "ts": 1218639.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 264, "y": 317, "ts": 1218639.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 265, "y": 317.5, "ts": 1218761.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 265, "y": 317, "ts": 1218761.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 266, "y": 317.5, "ts": 1218791.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 266, "y": 317, "ts": 1218791.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 267, "y": 317.5, "ts": 1218809.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 267, "y": 317, "ts": 1218809.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 268, "y": 317.5, "ts": 1218960.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 268, "y": 317, "ts": 1218960.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 269, "y": 317.5, "ts": 1218992.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 269, "y": 317, "ts": 1218992.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 269, "y": 318.5, "ts": 1219054.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 269, "y": 318, "ts": 1219054.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 270, "y": 318.5, "ts": 1219088.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 270, "y": 318, "ts": 1219088.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 271, "y": 318.5, "ts": 1219155.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 271, "y": 318, "ts": 1219155.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 272, "y": 318.5, "ts": 1219192.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 272, "y": 318, "ts": 1219192.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 273, "y": 318.5, "ts": 1219959.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 273, "y": 318, "ts": 1219959.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 273, "y": 319.5, "ts": 1220342.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 273, "y": 319, "ts": 1220342.9, "buttons": 1, "trusted": true}, {"t": "pointerup", "x": 273, "y": 319.5, "ts": 1220498.9, "buttons": 0, "trusted": true}, {"t": "mouseup", "x": 273, "y": 319, "ts": 1220498.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 272, "y": 319.5, "ts": 1220661.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 272, "y": 319, "ts": 1220661.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 270, "y": 320.5, "ts": 1220688.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 270, "y": 320, "ts": 1220688.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 268, "y": 321.5, "ts": 1220721.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 268, "y": 321, "ts": 1220721.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 265, "y": 323.5, "ts": 1220744.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 265, "y": 323, "ts": 1220744.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 262, "y": 324.5, "ts": 1220770.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 262, "y": 324, "ts": 1220770.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 258, "y": 326.5, "ts": 1220783.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 258, "y": 326, "ts": 1220783.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 254, "y": 327.5, "ts": 1220806.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 254, "y": 327, "ts": 1220806.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 239, "y": 330.5, "ts": 1220837.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 239, "y": 330, "ts": 1220837.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 231, "y": 332.5, "ts": 1220855.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 231, "y": 332, "ts": 1220855.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 217, "y": 335.5, "ts": 1220891.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 217, "y": 335, "ts": 1220891.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 212, "y": 337.5, "ts": 1220900.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 212, "y": 337, "ts": 1220900.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 209, "y": 338.5, "ts": 1220913.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 209, "y": 338, "ts": 1220913.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 201, "y": 341.5, "ts": 1220938.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 201, "y": 341, "ts": 1220938.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 197, "y": 342.5, "ts": 1220956.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 197, "y": 342, "ts": 1220956.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 191, "y": 342.5, "ts": 1220979.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 191, "y": 342, "ts": 1220979.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 188, "y": 342.5, "ts": 1220995.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 188, "y": 342, "ts": 1220995.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 180, "y": 342.5, "ts": 1221022.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 180, "y": 342, "ts": 1221022.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 175, "y": 342.5, "ts": 1221041.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 175, "y": 342, "ts": 1221041.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 164, "y": 342.5, "ts": 1221088.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 164, "y": 342, "ts": 1221088.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 162, "y": 342.5, "ts": 1221110.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 162, "y": 342, "ts": 1221110.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 161, "y": 342.5, "ts": 1221136.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 161, "y": 342, "ts": 1221136.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 157, "y": 341.5, "ts": 1221140.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 157, "y": 341, "ts": 1221140.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 156, "y": 341.5, "ts": 1221171.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 156, "y": 341, "ts": 1221171.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 154, "y": 341.5, "ts": 1221194.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 154, "y": 341, "ts": 1221194.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 148, "y": 339.5, "ts": 1221242.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 148, "y": 339, "ts": 1221242.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 146, "y": 338.5, "ts": 1221260.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 146, "y": 338, "ts": 1221260.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 143, "y": 337.5, "ts": 1221287.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 143, "y": 337, "ts": 1221287.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 140, "y": 335.5, "ts": 1221297.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 140, "y": 335, "ts": 1221297.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 138, "y": 334.5, "ts": 1221314.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 138, "y": 334, "ts": 1221314.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 135, "y": 331.5, "ts": 1221343.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 135, "y": 331, "ts": 1221343.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 134, "y": 330.5, "ts": 1221355.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 134, "y": 330, "ts": 1221355.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 133, "y": 328.5, "ts": 1221381.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 133, "y": 328, "ts": 1221381.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 129, "y": 324.5, "ts": 1221398.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 129, "y": 324, "ts": 1221398.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 127, "y": 323.5, "ts": 1221418.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 127, "y": 323, "ts": 1221418.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 126, "y": 322.5, "ts": 1221433.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 126, "y": 322, "ts": 1221433.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 125, "y": 321.5, "ts": 1221459.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 125, "y": 321, "ts": 1221459.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 122, "y": 320.5, "ts": 1221476.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 122, "y": 320, "ts": 1221476.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 120, "y": 319.5, "ts": 1221504.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 120, "y": 319, "ts": 1221504.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 114, "y": 317.5, "ts": 1221515.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 114, "y": 317, "ts": 1221515.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 110, "y": 316.5, "ts": 1221527.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 110, "y": 316, "ts": 1221527.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 107, "y": 315.5, "ts": 1221544.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 107, "y": 315, "ts": 1221544.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 109, "y": 315.5, "ts": 1223085.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 109, "y": 315, "ts": 1223085.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 117, "y": 315.5, "ts": 1223102.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 117, "y": 315, "ts": 1223102.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 120, "y": 315.5, "ts": 1223112.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 120, "y": 315, "ts": 1223112.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 125, "y": 315.5, "ts": 1223135.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 125, "y": 315, "ts": 1223135.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 130, "y": 316.5, "ts": 1223150.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 130, "y": 316, "ts": 1223150.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 140, "y": 317.5, "ts": 1223167.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 140, "y": 317, "ts": 1223167.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 146, "y": 318.5, "ts": 1223183.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 146, "y": 318, "ts": 1223183.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 157, "y": 320.5, "ts": 1223201.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 157, "y": 320, "ts": 1223201.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 162, "y": 320.5, "ts": 1223219.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 162, "y": 320, "ts": 1223219.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 164, "y": 321.5, "ts": 1223241.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 164, "y": 321, "ts": 1223241.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 163, "y": 323.5, "ts": 1223277.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 163, "y": 323, "ts": 1223277.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 156, "y": 326.5, "ts": 1223287.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 156, "y": 326, "ts": 1223287.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 147, "y": 329.5, "ts": 1223296.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 147, "y": 329, "ts": 1223296.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 141, "y": 330.5, "ts": 1223319.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 141, "y": 330, "ts": 1223319.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 127, "y": 334.5, "ts": 1223333.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 127, "y": 334, "ts": 1223333.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 112, "y": 337.5, "ts": 1223354.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 112, "y": 337, "ts": 1223354.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 93, "y": 340.5, "ts": 1223369.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 93, "y": 340, "ts": 1223369.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 74, "y": 343.5, "ts": 1223391.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 74, "y": 343, "ts": 1223391.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 345.5, "ts": 1223404.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 345, "ts": 1223404.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 40, "y": 348.5, "ts": 1223421.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 40, "y": 348, "ts": 1223421.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 37, "y": 349.5, "ts": 1223442.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 37, "y": 349, "ts": 1223442.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 33, "y": 352.5, "ts": 1223456.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 33, "y": 352, "ts": 1223456.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 30, "y": 356.5, "ts": 1223473.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 30, "y": 356, "ts": 1223473.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 28, "y": 361.5, "ts": 1223496.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 28, "y": 361, "ts": 1223496.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 27, "y": 364.5, "ts": 1223512.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 27, "y": 364, "ts": 1223512.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 25, "y": 368.5, "ts": 1223527.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 25, "y": 368, "ts": 1223527.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 25, "y": 370.5, "ts": 1223554.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 25, "y": 370, "ts": 1223554.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 25, "y": 371.5, "ts": 1223569.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 25, "y": 371, "ts": 1223569.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 25, "y": 372.5, "ts": 1223583.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 25, "y": 372, "ts": 1223583.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 27, "y": 372.5, "ts": 1223621.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 27, "y": 372, "ts": 1223621.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 29, "y": 372.5, "ts": 1223642.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 29, "y": 372, "ts": 1223642.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 33, "y": 372.5, "ts": 1223662.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 33, "y": 372, "ts": 1223662.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 36, "y": 372.5, "ts": 1223677.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 36, "y": 372, "ts": 1223677.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 38, "y": 370.5, "ts": 1223697.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 38, "y": 370, "ts": 1223697.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 40, "y": 368.5, "ts": 1223720.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 40, "y": 368, "ts": 1223720.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 41, "y": 367.5, "ts": 1223728.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 41, "y": 367, "ts": 1223728.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 42, "y": 366.5, "ts": 1223753.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 42, "y": 366, "ts": 1223753.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 42, "y": 364.5, "ts": 1223768.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 42, "y": 364, "ts": 1223768.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 42, "y": 363.5, "ts": 1223846.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 42, "y": 363, "ts": 1223846.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 43, "y": 360.5, "ts": 1223890.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 43, "y": 360, "ts": 1223890.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 43, "y": 359.5, "ts": 1223908.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 43, "y": 359, "ts": 1223908.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 43, "y": 357.5, "ts": 1223924.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 43, "y": 357, "ts": 1223924.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 43, "y": 356.5, "ts": 1223953.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 43, "y": 356, "ts": 1223953.9, "buttons": 0, "trusted": true}, {"t": "pointerdown", "x": 43, "y": 356.5, "ts": 1224045.9, "buttons": 1, "trusted": true}, {"t": "mousedown", "x": 43, "y": 356, "ts": 1224045.9, "buttons": 1, "trusted": true}, {"t": "pointerup", "x": 43, "y": 356.5, "ts": 1224134.9, "buttons": 0, "trusted": true}, {"t": "mouseup", "x": 43, "y": 356, "ts": 1224134.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 43, "y": 355.5, "ts": 1224155.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 43, "y": 355, "ts": 1224155.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 41, "y": 357.5, "ts": 1224188.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 41, "y": 357, "ts": 1224188.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 40, "y": 357.5, "ts": 1224207.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 40, "y": 357, "ts": 1224207.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 39, "y": 357.5, "ts": 1224258.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 39, "y": 357, "ts": 1224258.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 39, "y": 356.5, "ts": 1224289.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 39, "y": 356, "ts": 1224289.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 38, "y": 352.5, "ts": 1224308.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 38, "y": 352, "ts": 1224308.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 36, "y": 347.5, "ts": 1224327.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 36, "y": 347, "ts": 1224327.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 342.5, "ts": 1224355.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 342, "ts": 1224355.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 336.5, "ts": 1224365.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 336, "ts": 1224365.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 327.5, "ts": 1224381.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 327, "ts": 1224381.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 322.5, "ts": 1224407.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 322, "ts": 1224407.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 319.5, "ts": 1224421.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 319, "ts": 1224421.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 316.5, "ts": 1224435.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 316, "ts": 1224435.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 36, "y": 314.5, "ts": 1224452.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 36, "y": 314, "ts": 1224452.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 37, "y": 313.5, "ts": 1224473.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 37, "y": 313, "ts": 1224473.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 38, "y": 313.5, "ts": 1224538.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 38, "y": 313, "ts": 1224538.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 40, "y": 312.5, "ts": 1224768.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 40, "y": 312, "ts": 1224768.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 41, "y": 311.5, "ts": 1224788.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 41, "y": 311, "ts": 1224788.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 43, "y": 310.5, "ts": 1224808.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 43, "y": 310, "ts": 1224808.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 45, "y": 308.5, "ts": 1224824.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 45, "y": 308, "ts": 1224824.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 47, "y": 306.5, "ts": 1224841.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 47, "y": 306, "ts": 1224841.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 49, "y": 305.5, "ts": 1224859.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 49, "y": 305, "ts": 1224859.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 304.5, "ts": 1224881.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 304, "ts": 1224881.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 303.5, "ts": 1224899.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 303, "ts": 1224899.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 53, "y": 302.5, "ts": 1224912.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 53, "y": 302, "ts": 1224912.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 54, "y": 301.5, "ts": 1224939.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 54, "y": 301, "ts": 1224939.9, "buttons": 0, "trusted": true}, {"t": "pointerdown", "x": 54, "y": 301.5, "ts": 1225221.9, "buttons": 1, "trusted": true}, {"t": "mousedown", "x": 54, "y": 301, "ts": 1225221.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 68, "y": 303.5, "ts": 1225288.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 68, "y": 303, "ts": 1225288.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 76, "y": 303.5, "ts": 1225322.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 76, "y": 303, "ts": 1225322.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 83, "y": 303.5, "ts": 1225337.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 83, "y": 303, "ts": 1225337.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 90, "y": 303.5, "ts": 1225351.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 90, "y": 303, "ts": 1225351.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 98, "y": 303.5, "ts": 1225377.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 98, "y": 303, "ts": 1225377.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 118, "y": 306.5, "ts": 1225424.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 118, "y": 306, "ts": 1225424.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 121, "y": 306.5, "ts": 1225453.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 121, "y": 306, "ts": 1225453.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 129, "y": 307.5, "ts": 1225487.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 129, "y": 307, "ts": 1225487.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 137, "y": 309.5, "ts": 1225506.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 137, "y": 309, "ts": 1225506.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 145, "y": 310.5, "ts": 1225589.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 145, "y": 310, "ts": 1225589.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 147, "y": 311.5, "ts": 1225618.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 147, "y": 311, "ts": 1225618.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 148, "y": 311.5, "ts": 1225660.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 148, "y": 311, "ts": 1225660.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 149, "y": 311.5, "ts": 1225660.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 149, "y": 311, "ts": 1225660.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 150, "y": 311.5, "ts": 1225686.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 150, "y": 311, "ts": 1225686.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 151, "y": 311.5, "ts": 1225705.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 151, "y": 311, "ts": 1225705.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 157, "y": 313.5, "ts": 1225728.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 157, "y": 313, "ts": 1225728.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 163, "y": 313.5, "ts": 1225763.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 163, "y": 313, "ts": 1225763.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 164, "y": 314.5, "ts": 1225826.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 164, "y": 314, "ts": 1225826.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 166, "y": 314.5, "ts": 1225852.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 166, "y": 314, "ts": 1225852.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 167, "y": 314.5, "ts": 1225891.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 167, "y": 314, "ts": 1225891.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 168, "y": 314.5, "ts": 1225925.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 168, "y": 314, "ts": 1225925.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 168, "y": 315.5, "ts": 1225937.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 168, "y": 315, "ts": 1225937.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 169, "y": 316.5, "ts": 1225958.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 169, "y": 316, "ts": 1225958.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 170, "y": 316.5, "ts": 1225987.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 170, "y": 316, "ts": 1225987.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 171, "y": 317.5, "ts": 1226023.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 171, "y": 317, "ts": 1226023.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 172, "y": 318.5, "ts": 1226096.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 172, "y": 318, "ts": 1226096.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 173, "y": 319.5, "ts": 1226623.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 173, "y": 319, "ts": 1226623.9, "buttons": 1, "trusted": true}, {"t": "pointerup", "x": 173, "y": 319.5, "ts": 1227160.9, "buttons": 0, "trusted": true}, {"t": "mouseup", "x": 173, "y": 319, "ts": 1227160.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 173, "y": 320.5, "ts": 1227255.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 173, "y": 320, "ts": 1227255.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 172, "y": 320.5, "ts": 1227323.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 172, "y": 320, "ts": 1227323.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 170, "y": 320.5, "ts": 1227338.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 170, "y": 320, "ts": 1227338.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 166, "y": 320.5, "ts": 1227376.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 166, "y": 320, "ts": 1227376.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 162, "y": 320.5, "ts": 1227404.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 162, "y": 320, "ts": 1227404.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 160, "y": 320.5, "ts": 1227425.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 160, "y": 320, "ts": 1227425.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 157, "y": 321.5, "ts": 1227440.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 157, "y": 321, "ts": 1227440.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 154, "y": 322.5, "ts": 1227470.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 154, "y": 322, "ts": 1227470.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 150, "y": 322.5, "ts": 1227498.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 150, "y": 322, "ts": 1227498.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 144, "y": 322.5, "ts": 1227531.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 144, "y": 322, "ts": 1227531.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 141, "y": 323.5, "ts": 1227555.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 141, "y": 323, "ts": 1227555.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 138, "y": 324.5, "ts": 1227571.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 138, "y": 324, "ts": 1227571.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 125, "y": 326.5, "ts": 1227603.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 125, "y": 326, "ts": 1227603.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 121, "y": 328.5, "ts": 1227614.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 121, "y": 328, "ts": 1227614.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 115, "y": 330.5, "ts": 1227632.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 115, "y": 330, "ts": 1227632.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 101, "y": 334.5, "ts": 1227660.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 101, "y": 334, "ts": 1227660.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 95, "y": 336.5, "ts": 1227681.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 95, "y": 336, "ts": 1227681.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 90, "y": 339.5, "ts": 1227694.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 90, "y": 339, "ts": 1227694.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 83, "y": 342.5, "ts": 1227715.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 83, "y": 342, "ts": 1227715.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 67, "y": 350.5, "ts": 1227755.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 67, "y": 350, "ts": 1227755.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 60, "y": 354.5, "ts": 1227781.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 60, "y": 354, "ts": 1227781.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 56, "y": 356.5, "ts": 1227801.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 56, "y": 356, "ts": 1227801.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 55, "y": 357.5, "ts": 1227818.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 55, "y": 357, "ts": 1227818.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 52, "y": 357.5, "ts": 1227837.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 52, "y": 357, "ts": 1227837.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 357.5, "ts": 1227863.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 357, "ts": 1227863.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 49, "y": 357.5, "ts": 1227903.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 49, "y": 357, "ts": 1227903.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 48, "y": 357.5, "ts": 1227960.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 48, "y": 357, "ts": 1227960.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 48, "y": 356.5, "ts": 1227981.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 48, "y": 356, "ts": 1227981.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 47, "y": 355.5, "ts": 1227995.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 47, "y": 355, "ts": 1227995.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 45, "y": 352.5, "ts": 1228015.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 45, "y": 352, "ts": 1228015.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 39, "y": 347.5, "ts": 1228053.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 39, "y": 347, "ts": 1228053.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 36, "y": 345.5, "ts": 1228078.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 36, "y": 345, "ts": 1228078.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 32, "y": 343.5, "ts": 1228101.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 32, "y": 343, "ts": 1228101.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 31, "y": 343.5, "ts": 1228111.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 31, "y": 343, "ts": 1228111.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 30, "y": 343.5, "ts": 1228133.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 30, "y": 343, "ts": 1228133.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 29, "y": 343.5, "ts": 1228161.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 29, "y": 343, "ts": 1228161.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 27, "y": 343.5, "ts": 1228180.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 27, "y": 343, "ts": 1228180.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 26, "y": 343.5, "ts": 1228194.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 26, "y": 343, "ts": 1228194.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 22, "y": 343.5, "ts": 1228224.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 22, "y": 343, "ts": 1228224.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 21, "y": 343.5, "ts": 1228321.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 21, "y": 343, "ts": 1228321.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 21, "y": 341.5, "ts": 1228341.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 21, "y": 341, "ts": 1228341.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 21, "y": 339.5, "ts": 1228368.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 21, "y": 339, "ts": 1228368.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 21, "y": 338.5, "ts": 1228378.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 21, "y": 338, "ts": 1228378.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 21, "y": 337.5, "ts": 1228412.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 21, "y": 337, "ts": 1228412.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 21, "y": 336.5, "ts": 1228429.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 21, "y": 336, "ts": 1228429.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 21, "y": 337.5, "ts": 1228667.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 21, "y": 337, "ts": 1228667.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 19, "y": 339.5, "ts": 1229218.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 19, "y": 339, "ts": 1229218.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 19, "y": 340.5, "ts": 1229242.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 19, "y": 340, "ts": 1229242.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 17, "y": 342.5, "ts": 1229274.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 17, "y": 342, "ts": 1229274.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 15, "y": 346.5, "ts": 1229291.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 15, "y": 346, "ts": 1229291.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 14, "y": 347.5, "ts": 1229317.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 14, "y": 347, "ts": 1229317.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 13, "y": 348.5, "ts": 1229336.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 13, "y": 348, "ts": 1229336.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 13, "y": 349.5, "ts": 1229363.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 13, "y": 349, "ts": 1229363.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 12, "y": 349.5, "ts": 1229456.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 12, "y": 349, "ts": 1229456.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 10, "y": 351.5, "ts": 1229622.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 10, "y": 351, "ts": 1229622.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 9, "y": 354.5, "ts": 1229654.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 9, "y": 354, "ts": 1229654.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 9, "y": 356.5, "ts": 1229664.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 9, "y": 356, "ts": 1229664.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 7, "y": 358.5, "ts": 1229673.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 7, "y": 358, "ts": 1229673.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 6, "y": 360.5, "ts": 1229697.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 6, "y": 360, "ts": 1229697.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 6, "y": 362.5, "ts": 1229717.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 6, "y": 362, "ts": 1229717.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 6, "y": 363.5, "ts": 1229730.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 6, "y": 363, "ts": 1229730.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 6, "y": 364.5, "ts": 1229750.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 6, "y": 364, "ts": 1229750.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 6, "y": 365.5, "ts": 1229771.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 6, "y": 365, "ts": 1229771.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 6, "y": 366.5, "ts": 1229788.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 6, "y": 366, "ts": 1229788.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 6, "y": 367.5, "ts": 1229834.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 6, "y": 367, "ts": 1229834.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 7, "y": 367.5, "ts": 1229876.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 7, "y": 367, "ts": 1229876.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 10, "y": 366.5, "ts": 1229898.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 10, "y": 366, "ts": 1229898.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 15, "y": 364.5, "ts": 1229918.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 15, "y": 364, "ts": 1229918.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 19, "y": 362.5, "ts": 1229941.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 19, "y": 362, "ts": 1229941.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 356.5, "ts": 1229964.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 356, "ts": 1229964.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 39, "y": 353.5, "ts": 1229984.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 39, "y": 353, "ts": 1229984.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 40, "y": 353.5, "ts": 1230001.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 40, "y": 353, "ts": 1230001.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 45, "y": 350.5, "ts": 1230025.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 45, "y": 350, "ts": 1230025.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 47, "y": 348.5, "ts": 1230052.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 47, "y": 348, "ts": 1230052.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 48, "y": 347.5, "ts": 1230105.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 48, "y": 347, "ts": 1230105.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 49, "y": 347.5, "ts": 1230123.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 49, "y": 347, "ts": 1230123.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 49, "y": 348.5, "ts": 1230148.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 49, "y": 348, "ts": 1230148.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 49, "y": 349.5, "ts": 1230163.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 49, "y": 349, "ts": 1230163.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 351.5, "ts": 1230182.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 351, "ts": 1230182.9, "buttons": 0, "trusted": true}, {"t": "pointerdown", "x": 50, "y": 351.5, "ts": 1230598.9, "buttons": 1, "trusted": true}, {"t": "mousedown", "x": 50, "y": 351, "ts": 1230598.9, "buttons": 1, "trusted": true}, {"t": "pointerup", "x": 50, "y": 351.5, "ts": 1230755.9, "buttons": 0, "trusted": true}, {"t": "mouseup", "x": 50, "y": 351, "ts": 1230755.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 350.5, "ts": 1231304.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 350, "ts": 1231304.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 347.5, "ts": 1231334.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 347, "ts": 1231334.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 346.5, "ts": 1231366.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 346, "ts": 1231366.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 345.5, "ts": 1231379.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 345, "ts": 1231379.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 344.5, "ts": 1231396.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 344, "ts": 1231396.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 343.5, "ts": 1231421.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 343, "ts": 1231421.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 340.5, "ts": 1231439.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 340, "ts": 1231439.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 50, "y": 338.5, "ts": 1231455.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 50, "y": 338, "ts": 1231455.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 49, "y": 337.5, "ts": 1231470.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 49, "y": 337, "ts": 1231470.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 44, "y": 330.5, "ts": 1231488.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 44, "y": 330, "ts": 1231488.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 41, "y": 326.5, "ts": 1231507.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 41, "y": 326, "ts": 1231507.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 40, "y": 324.5, "ts": 1231526.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 40, "y": 324, "ts": 1231526.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 37, "y": 320.5, "ts": 1231545.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 37, "y": 320, "ts": 1231545.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 36, "y": 318.5, "ts": 1231564.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 36, "y": 318, "ts": 1231564.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 316.5, "ts": 1231580.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 316, "ts": 1231580.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 314.5, "ts": 1231598.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 314, "ts": 1231598.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 313.5, "ts": 1231626.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 313, "ts": 1231626.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 35, "y": 312.5, "ts": 1231759.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 35, "y": 312, "ts": 1231759.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 37, "y": 312.5, "ts": 1231775.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 37, "y": 312, "ts": 1231775.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 38, "y": 312.5, "ts": 1231813.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 38, "y": 312, "ts": 1231813.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 39, "y": 312.5, "ts": 1231823.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 39, "y": 312, "ts": 1231823.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 40, "y": 312.5, "ts": 1231871.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 40, "y": 312, "ts": 1231871.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 41, "y": 311.5, "ts": 1231888.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 41, "y": 311, "ts": 1231888.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 42, "y": 311.5, "ts": 1231921.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 42, "y": 311, "ts": 1231921.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 43, "y": 311.5, "ts": 1231951.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 43, "y": 311, "ts": 1231951.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 44, "y": 311.5, "ts": 1231971.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 44, "y": 311, "ts": 1231971.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 46, "y": 310.5, "ts": 1232000.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 46, "y": 310, "ts": 1232000.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 47, "y": 308.5, "ts": 1232030.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 47, "y": 308, "ts": 1232030.9, "buttons": 0, "trusted": true}, {"t": "pointerdown", "x": 47, "y": 308.5, "ts": 1232150.9, "buttons": 1, "trusted": true}, {"t": "mousedown", "x": 47, "y": 308, "ts": 1232150.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 53, "y": 308.5, "ts": 1232207.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 53, "y": 308, "ts": 1232207.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 57, "y": 308.5, "ts": 1232228.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 57, "y": 308, "ts": 1232228.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 66, "y": 309.5, "ts": 1232249.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 66, "y": 309, "ts": 1232249.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 81, "y": 310.5, "ts": 1232272.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 81, "y": 310, "ts": 1232272.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 88, "y": 311.5, "ts": 1232292.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 88, "y": 311, "ts": 1232292.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 94, "y": 311.5, "ts": 1232318.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 94, "y": 311, "ts": 1232318.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 102, "y": 311.5, "ts": 1232336.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 102, "y": 311, "ts": 1232336.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 124, "y": 313.5, "ts": 1232378.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 124, "y": 313, "ts": 1232378.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 131, "y": 314.5, "ts": 1232397.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 131, "y": 314, "ts": 1232397.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 150, "y": 314.5, "ts": 1232426.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 150, "y": 314, "ts": 1232426.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 156, "y": 314.5, "ts": 1232459.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 156, "y": 314, "ts": 1232459.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 161, "y": 314.5, "ts": 1232480.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 161, "y": 314, "ts": 1232480.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 167, "y": 314.5, "ts": 1232499.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 167, "y": 314, "ts": 1232499.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 169, "y": 314.5, "ts": 1232533.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 169, "y": 314, "ts": 1232533.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 171, "y": 314.5, "ts": 1232566.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 171, "y": 314, "ts": 1232566.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 175, "y": 314.5, "ts": 1232600.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 175, "y": 314, "ts": 1232600.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 178, "y": 313.5, "ts": 1232648.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 178, "y": 313, "ts": 1232648.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 184, "y": 313.5, "ts": 1232666.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 184, "y": 313, "ts": 1232666.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 189, "y": 313.5, "ts": 1232714.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 189, "y": 313, "ts": 1232714.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 193, "y": 313.5, "ts": 1232741.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 193, "y": 313, "ts": 1232741.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 198, "y": 313.5, "ts": 1232757.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 198, "y": 313, "ts": 1232757.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 207, "y": 313.5, "ts": 1232773.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 207, "y": 313, "ts": 1232773.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 209, "y": 313.5, "ts": 1232831.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 209, "y": 313, "ts": 1232831.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 211, "y": 313.5, "ts": 1232855.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 211, "y": 313, "ts": 1232855.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 213, "y": 313.5, "ts": 1232963.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 213, "y": 313, "ts": 1232963.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 214, "y": 313.5, "ts": 1232985.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 214, "y": 313, "ts": 1232985.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 215, "y": 313.5, "ts": 1233006.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 215, "y": 313, "ts": 1233006.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 217, "y": 313.5, "ts": 1233033.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 217, "y": 313, "ts": 1233033.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 219, "y": 312.5, "ts": 1233072.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 219, "y": 312, "ts": 1233072.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 220, "y": 312.5, "ts": 1233109.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 220, "y": 312, "ts": 1233109.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 219, "y": 312.5, "ts": 1233542.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 219, "y": 312, "ts": 1233542.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 218, "y": 313.5, "ts": 1233561.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 218, "y": 313, "ts": 1233561.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 217, "y": 314.5, "ts": 1233605.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 217, "y": 314, "ts": 1233605.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 214, "y": 315.5, "ts": 1233636.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 214, "y": 315, "ts": 1233636.9, "buttons": 1, "trusted": true}, {"t": "pointermove", "x": 213, "y": 315.5, "ts": 1233664.9, "buttons": 1, "trusted": true}, {"t": "mousemove", "x": 213, "y": 315, "ts": 1233664.9, "buttons": 1, "trusted": true}, {"t": "pointerup", "x": 213, "y": 315.5, "ts": 1234512.9, "buttons": 0, "trusted": true}, {"t": "mouseup", "x": 213, "y": 315, "ts": 1234512.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 212, "y": 315.5, "ts": 1234678.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 212, "y": 315, "ts": 1234678.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 211, "y": 315.5, "ts": 1234704.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 211, "y": 315, "ts": 1234704.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 209, "y": 315.5, "ts": 1234740.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 209, "y": 315, "ts": 1234740.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 208, "y": 315.5, "ts": 1234763.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 208, "y": 315, "ts": 1234763.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 207, "y": 315.5, "ts": 1234786.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 207, "y": 315, "ts": 1234786.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 206, "y": 315.5, "ts": 1234838.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 206, "y": 315, "ts": 1234838.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 204, "y": 315.5, "ts": 1234867.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 204, "y": 315, "ts": 1234867.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 203, "y": 315.5, "ts": 1234894.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 203, "y": 315, "ts": 1234894.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 202, "y": 315.5, "ts": 1234910.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 202, "y": 315, "ts": 1234910.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 200, "y": 315.5, "ts": 1234928.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 200, "y": 315, "ts": 1234928.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 198, "y": 316.5, "ts": 1234952.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 198, "y": 316, "ts": 1234952.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 195, "y": 317.5, "ts": 1234973.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 195, "y": 317, "ts": 1234973.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 194, "y": 317.5, "ts": 1234986.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 194, "y": 317, "ts": 1234986.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 187, "y": 320.5, "ts": 1235007.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 187, "y": 320, "ts": 1235007.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 180, "y": 321.5, "ts": 1235027.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 180, "y": 321, "ts": 1235027.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 178, "y": 322.5, "ts": 1235051.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 178, "y": 322, "ts": 1235051.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 168, "y": 324.5, "ts": 1235066.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 168, "y": 324, "ts": 1235066.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 160, "y": 325.5, "ts": 1235087.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 160, "y": 325, "ts": 1235087.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 132, "y": 329.5, "ts": 1235123.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 132, "y": 329, "ts": 1235123.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 118, "y": 330.5, "ts": 1235153.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 118, "y": 330, "ts": 1235153.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 114, "y": 331.5, "ts": 1235173.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 114, "y": 331, "ts": 1235173.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 112, "y": 331.5, "ts": 1235182.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 112, "y": 331, "ts": 1235182.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 111, "y": 331.5, "ts": 1235204.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 111, "y": 331, "ts": 1235204.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 110, "y": 331.5, "ts": 1235229.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 110, "y": 331, "ts": 1235229.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 109, "y": 331.5, "ts": 1235239.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 109, "y": 331, "ts": 1235239.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 106, "y": 331.5, "ts": 1235262.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 106, "y": 331, "ts": 1235262.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 99, "y": 330.5, "ts": 1235273.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 99, "y": 330, "ts": 1235273.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 94, "y": 329.5, "ts": 1235292.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 94, "y": 329, "ts": 1235292.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 88, "y": 329.5, "ts": 1235311.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 88, "y": 329, "ts": 1235311.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 83, "y": 327.5, "ts": 1235336.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 83, "y": 327, "ts": 1235336.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 77, "y": 327.5, "ts": 1235347.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 77, "y": 327, "ts": 1235347.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 68, "y": 327.5, "ts": 1235366.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 68, "y": 327, "ts": 1235366.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 65, "y": 326.5, "ts": 1235385.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 65, "y": 326, "ts": 1235385.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 61, "y": 326.5, "ts": 1235410.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 61, "y": 326, "ts": 1235410.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 54, "y": 325.5, "ts": 1235430.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 54, "y": 325, "ts": 1235430.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 51, "y": 325.5, "ts": 1235445.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 51, "y": 325, "ts": 1235445.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 48, "y": 323.5, "ts": 1235462.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 48, "y": 323, "ts": 1235462.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 42, "y": 321.5, "ts": 1235490.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 42, "y": 321, "ts": 1235490.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 36, "y": 318.5, "ts": 1235509.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 36, "y": 318, "ts": 1235509.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 32, "y": 316.5, "ts": 1235532.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 32, "y": 316, "ts": 1235532.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 30, "y": 314.5, "ts": 1235553.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 30, "y": 314, "ts": 1235553.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 28, "y": 312.5, "ts": 1235573.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 28, "y": 312, "ts": 1235573.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 28, "y": 310.5, "ts": 1235587.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 28, "y": 310, "ts": 1235587.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 31, "y": 297.5, "ts": 1235624.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 31, "y": 297, "ts": 1235624.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 44, "y": 281.5, "ts": 1235674.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 44, "y": 281, "ts": 1235674.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 51, "y": 276.5, "ts": 1235691.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 51, "y": 276, "ts": 1235691.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 59, "y": 271.5, "ts": 1235709.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 59, "y": 271, "ts": 1235709.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 67, "y": 265.5, "ts": 1235734.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 67, "y": 265, "ts": 1235734.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 76, "y": 260.5, "ts": 1235748.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 76, "y": 260, "ts": 1235748.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 90, "y": 250.5, "ts": 1235780.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 90, "y": 250, "ts": 1235780.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 100, "y": 245.5, "ts": 1235796.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 100, "y": 245, "ts": 1235796.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 120, "y": 237.5, "ts": 1235823.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 120, "y": 237, "ts": 1235823.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 130, "y": 232.5, "ts": 1235842.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 130, "y": 232, "ts": 1235842.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 142, "y": 226.5, "ts": 1235856.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 142, "y": 226, "ts": 1235856.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 161, "y": 217.5, "ts": 1235875.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 161, "y": 217, "ts": 1235875.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 173, "y": 212.5, "ts": 1235903.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 173, "y": 212, "ts": 1235903.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 184, "y": 208.5, "ts": 1235914.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 184, "y": 208, "ts": 1235914.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 196, "y": 204.5, "ts": 1235939.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 196, "y": 204, "ts": 1235939.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 214, "y": 199.5, "ts": 1235950.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 214, "y": 199, "ts": 1235950.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 220, "y": 197.5, "ts": 1235968.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 220, "y": 197, "ts": 1235968.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 229, "y": 195.5, "ts": 1235985.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 229, "y": 195, "ts": 1235985.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 234, "y": 194.5, "ts": 1236009.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 234, "y": 194, "ts": 1236009.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 238, "y": 193.5, "ts": 1236029.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 238, "y": 193, "ts": 1236029.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 247, "y": 192.5, "ts": 1236044.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 247, "y": 192, "ts": 1236044.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 250, "y": 190.5, "ts": 1236069.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 250, "y": 190, "ts": 1236069.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 252, "y": 184.5, "ts": 1236079.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 252, "y": 184, "ts": 1236079.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 253, "y": 183.5, "ts": 1236102.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 253, "y": 183, "ts": 1236102.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 253, "y": 182.5, "ts": 1236271.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 253, "y": 182, "ts": 1236271.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 252, "y": 182.5, "ts": 1236290.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 252, "y": 182, "ts": 1236290.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 248, "y": 182.5, "ts": 1236305.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 248, "y": 182, "ts": 1236305.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 237, "y": 182.5, "ts": 1236341.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 237, "y": 182, "ts": 1236341.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 230, "y": 182.5, "ts": 1236363.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 230, "y": 182, "ts": 1236363.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 224, "y": 182.5, "ts": 1236378.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 224, "y": 182, "ts": 1236378.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 219, "y": 182.5, "ts": 1236395.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 219, "y": 182, "ts": 1236395.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 217, "y": 182.5, "ts": 1236421.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 217, "y": 182, "ts": 1236421.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 216, "y": 182.5, "ts": 1236438.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 216, "y": 182, "ts": 1236438.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 214, "y": 182.5, "ts": 1236454.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 214, "y": 182, "ts": 1236454.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 211, "y": 182.5, "ts": 1236481.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 211, "y": 182, "ts": 1236481.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 206, "y": 182.5, "ts": 1236493.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 206, "y": 182, "ts": 1236493.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 202, "y": 181.5, "ts": 1236506.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 202, "y": 181, "ts": 1236506.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 197, "y": 179.5, "ts": 1236532.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 197, "y": 179, "ts": 1236532.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 194, "y": 179.5, "ts": 1236541.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 194, "y": 179, "ts": 1236541.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 192, "y": 179.5, "ts": 1236568.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 192, "y": 179, "ts": 1236568.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 190, "y": 178.5, "ts": 1236598.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 190, "y": 178, "ts": 1236598.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 189, "y": 177.5, "ts": 1236612.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 189, "y": 177, "ts": 1236612.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 186, "y": 175.5, "ts": 1236637.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 186, "y": 175, "ts": 1236637.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 184, "y": 174.5, "ts": 1236651.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 184, "y": 174, "ts": 1236651.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 182, "y": 173.5, "ts": 1236664.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 182, "y": 173, "ts": 1236664.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 173, "y": 170.5, "ts": 1236700.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 173, "y": 170, "ts": 1236700.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 172, "y": 169.5, "ts": 1236717.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 172, "y": 169, "ts": 1236717.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 171, "y": 169.5, "ts": 1236754.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 171, "y": 169, "ts": 1236754.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 170, "y": 169.5, "ts": 1236773.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 170, "y": 169, "ts": 1236773.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 168, "y": 169.5, "ts": 1236792.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 168, "y": 169, "ts": 1236792.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 167, "y": 170.5, "ts": 1236807.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 167, "y": 170, "ts": 1236807.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 163, "y": 172.5, "ts": 1236824.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 163, "y": 172, "ts": 1236824.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 160, "y": 174.5, "ts": 1236846.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 160, "y": 174, "ts": 1236846.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 154, "y": 177.5, "ts": 1236860.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 154, "y": 177, "ts": 1236860.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 147, "y": 181.5, "ts": 1236883.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 147, "y": 181, "ts": 1236883.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 141, "y": 183.5, "ts": 1236898.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 141, "y": 183, "ts": 1236898.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 137, "y": 185.5, "ts": 1236912.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 137, "y": 185, "ts": 1236912.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 132, "y": 187.5, "ts": 1236936.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 132, "y": 187, "ts": 1236936.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 126, "y": 188.5, "ts": 1236946.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 126, "y": 188, "ts": 1236946.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 120, "y": 190.5, "ts": 1236963.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 120, "y": 190, "ts": 1236963.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 104, "y": 191.5, "ts": 1237002.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 104, "y": 191, "ts": 1237002.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 95, "y": 191.5, "ts": 1237022.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 95, "y": 191, "ts": 1237022.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 89, "y": 192.5, "ts": 1237034.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 89, "y": 192, "ts": 1237034.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 85, "y": 192.5, "ts": 1237055.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 85, "y": 192, "ts": 1237055.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 81, "y": 192.5, "ts": 1237070.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 81, "y": 192, "ts": 1237070.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 76, "y": 192.5, "ts": 1237089.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 76, "y": 192, "ts": 1237089.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 74, "y": 192.5, "ts": 1237112.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 74, "y": 192, "ts": 1237112.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 69, "y": 192.5, "ts": 1237124.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 69, "y": 192, "ts": 1237124.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 64, "y": 192.5, "ts": 1237149.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 64, "y": 192, "ts": 1237149.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 58, "y": 193.5, "ts": 1237167.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 58, "y": 193, "ts": 1237167.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 51, "y": 195.5, "ts": 1237178.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 51, "y": 195, "ts": 1237178.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 45, "y": 196.5, "ts": 1237200.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 45, "y": 196, "ts": 1237200.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 39, "y": 197.5, "ts": 1237214.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 39, "y": 197, "ts": 1237214.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 30, "y": 201.5, "ts": 1237232.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 30, "y": 201, "ts": 1237232.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 27, "y": 203.5, "ts": 1237249.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 27, "y": 203, "ts": 1237249.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 20, "y": 207.5, "ts": 1237273.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 20, "y": 207, "ts": 1237273.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 14, "y": 212.5, "ts": 1237285.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 14, "y": 212, "ts": 1237285.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 5, "y": 220.5, "ts": 1237301.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 5, "y": 220, "ts": 1237301.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 2, "y": 234.5, "ts": 1237995.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 2, "y": 234, "ts": 1237995.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 15, "y": 234.5, "ts": 1238016.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 15, "y": 234, "ts": 1238016.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 42, "y": 234.5, "ts": 1238031.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 42, "y": 234, "ts": 1238031.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 79, "y": 233.5, "ts": 1238047.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 79, "y": 233, "ts": 1238047.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 88, "y": 233.5, "ts": 1238066.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 88, "y": 233, "ts": 1238066.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 106, "y": 232.5, "ts": 1238091.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 106, "y": 232, "ts": 1238091.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 122, "y": 229.5, "ts": 1238116.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 122, "y": 229, "ts": 1238116.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 132, "y": 227.5, "ts": 1238131.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 132, "y": 227, "ts": 1238131.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 136, "y": 227.5, "ts": 1238140.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 136, "y": 227, "ts": 1238140.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 137, "y": 226.5, "ts": 1238158.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 137, "y": 226, "ts": 1238158.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 137, "y": 225.5, "ts": 1238175.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 137, "y": 225, "ts": 1238175.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 137, "y": 224.5, "ts": 1238192.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 137, "y": 224, "ts": 1238192.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 138, "y": 222.5, "ts": 1238210.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 138, "y": 222, "ts": 1238210.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 138, "y": 220.5, "ts": 1238228.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 138, "y": 220, "ts": 1238228.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 138, "y": 219.5, "ts": 1238251.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 138, "y": 219, "ts": 1238251.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 138, "y": 218.5, "ts": 1238274.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 138, "y": 218, "ts": 1238274.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 137, "y": 218.5, "ts": 1238287.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 137, "y": 218, "ts": 1238287.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 135, "y": 218.5, "ts": 1238316.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 135, "y": 218, "ts": 1238316.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 124, "y": 218.5, "ts": 1238340.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 124, "y": 218, "ts": 1238340.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 117, "y": 218.5, "ts": 1238359.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 117, "y": 218, "ts": 1238359.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 111, "y": 218.5, "ts": 1238378.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 111, "y": 218, "ts": 1238378.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 105, "y": 219.5, "ts": 1238395.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 105, "y": 219, "ts": 1238395.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 102, "y": 221.5, "ts": 1238421.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 102, "y": 221, "ts": 1238421.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 97, "y": 222.5, "ts": 1238437.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 97, "y": 222, "ts": 1238437.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 95, "y": 224.5, "ts": 1238447.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 95, "y": 224, "ts": 1238447.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 93, "y": 225.5, "ts": 1238470.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 93, "y": 225, "ts": 1238470.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 91, "y": 226.5, "ts": 1238491.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 91, "y": 226, "ts": 1238491.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 90, "y": 226.5, "ts": 1238505.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 90, "y": 226, "ts": 1238505.9, "buttons": 0, "trusted": true}, {"t": "pointermove", "x": 89, "y": 226.5, "ts": 1238639.9, "buttons": 0, "trusted": true}, {"t": "mousemove", "x": 89, "y": 226, "ts": 1238639.9, "buttons": 0, "trusted": true}]} \ No newline at end of file diff --git a/try/human_trace2.json b/try/human_trace2.json new file mode 100644 index 0000000..49647d5 --- /dev/null +++ b/try/human_trace2.json @@ -0,0 +1 @@ +{"iframe_origin": [770, 305], "events": [{"t": "pointerdown", "x": 30, "y": 355.5, "ts": 1707201, "buttons": 1, "trusted": true}, {"t": "mousedown", "x": 30, "y": 355, "ts": 1707201, "buttons": 1, "trusted": true}, {"t": "pointerup", "x": 30, "y": 355.5, "ts": 1707203.8, "buttons": 0, "trusted": true}, {"t": "mouseup", "x": 30, "y": 355, "ts": 1707203.8, "buttons": 0, "trusted": true}]} \ No newline at end of file diff --git a/try/human_trace_pass.json b/try/human_trace_pass.json new file mode 100644 index 0000000..a393a6b --- /dev/null +++ b/try/human_trace_pass.json @@ -0,0 +1 @@ +{"iframe_origin": [770, 305], "events": [{"t": 2802.599998474121, "type": "down", "x": 30, "y": 355, "btns": 1}, {"t": 2805.099998474121, "type": "up", "x": 30, "y": 355, "btns": 0}, {"t": 259020.29999923706, "type": "move", "x": 85, "y": 223, "btns": 0}, {"t": 259168.29999923706, "type": "move", "x": 72, "y": 265, "btns": 0}, {"t": 259282.29999923706, "type": "move", "x": 62, "y": 297, "btns": 0}, {"t": 259319.29999923706, "type": "move", "x": 61, "y": 303, "btns": 0}, {"t": 259433.29999923706, "type": "move", "x": 59, "y": 317, "btns": 0}, {"t": 259502.29999923706, "type": "move", "x": 63, "y": 324, "btns": 0}, {"t": 259601.29999923706, "type": "move", "x": 76, "y": 325, "btns": 0}, {"t": 259713.29999923706, "type": "move", "x": 77, "y": 323, "btns": 0}, {"t": 259817.29999923706, "type": "move", "x": 96, "y": 311, "btns": 0}, {"t": 260080.29999923706, "type": "move", "x": 169, "y": 220, "btns": 0}, {"t": 260238.29999923706, "type": "move", "x": 170, "y": 219, "btns": 0}, {"t": 260298.29999923706, "type": "move", "x": 174, "y": 215, "btns": 0}, {"t": 260444.29999923706, "type": "move", "x": 175, "y": 215, "btns": 0}, {"t": 260654.29999923706, "type": "move", "x": 172, "y": 215, "btns": 0}, {"t": 260759.29999923706, "type": "move", "x": 168, "y": 216, "btns": 0}, {"t": 261248.29999923706, "type": "move", "x": 163, "y": 218, "btns": 0}, {"t": 261352.29999923706, "type": "move", "x": 153, "y": 227, "btns": 0}, {"t": 261380.29999923706, "type": "move", "x": 146, "y": 234, "btns": 0}, {"t": 261699.29999923706, "type": "move", "x": 94, "y": 280, "btns": 0}, {"t": 261788.29999923706, "type": "move", "x": 69, "y": 328, "btns": 0}, {"t": 261819.29999923706, "type": "move", "x": 63, "y": 340, "btns": 0}, {"t": 261863.29999923706, "type": "move", "x": 60, "y": 344, "btns": 0}, {"t": 262146.29999923706, "type": "move", "x": 32, "y": 357, "btns": 0}, {"t": 262206.29999923706, "type": "down", "x": 32, "y": 357, "btns": 1}, {"t": 262303.29999923706, "type": "up", "x": 32, "y": 357, "btns": 0}, {"t": 262748.29999923706, "type": "move", "x": 29, "y": 357, "btns": 0}, {"t": 262861.29999923706, "type": "move", "x": 27, "y": 357, "btns": 0}, {"t": 262961.29999923706, "type": "move", "x": 27, "y": 356, "btns": 0}, {"t": 263073.29999923706, "type": "down", "x": 27, "y": 356, "btns": 1}, {"t": 263186.29999923706, "type": "up", "x": 27, "y": 356, "btns": 0}, {"t": 263595.29999923706, "type": "move", "x": 28, "y": 356, "btns": 0}, {"t": 263686.29999923706, "type": "move", "x": 29, "y": 354, "btns": 0}, {"t": 263784.29999923706, "type": "move", "x": 35, "y": 345, "btns": 0}, {"t": 263826.29999923706, "type": "move", "x": 39, "y": 337, "btns": 0}, {"t": 263865.29999923706, "type": "move", "x": 41, "y": 333, "btns": 0}, {"t": 263981.29999923706, "type": "move", "x": 47, "y": 326, "btns": 0}, {"t": 264017.29999923706, "type": "move", "x": 47, "y": 325, "btns": 0}, {"t": 264130.29999923706, "type": "move", "x": 47, "y": 324, "btns": 0}, {"t": 264246.29999923706, "type": "move", "x": 47, "y": 323, "btns": 0}, {"t": 264358.29999923706, "type": "move", "x": 49, "y": 319, "btns": 0}, {"t": 264452.29999923706, "type": "move", "x": 53, "y": 312, "btns": 0}, {"t": 264555.29999923706, "type": "move", "x": 54, "y": 311, "btns": 0}, {"t": 264579.29999923706, "type": "move", "x": 58, "y": 305, "btns": 0}, {"t": 264667.29999923706, "type": "move", "x": 59, "y": 305, "btns": 0}, {"t": 264778.29999923706, "type": "move", "x": 61, "y": 302, "btns": 0}, {"t": 264895.29999923706, "type": "move", "x": 62, "y": 301, "btns": 0}, {"t": 264997.29999923706, "type": "move", "x": 65, "y": 300, "btns": 0}, {"t": 265145.29999923706, "type": "move", "x": 63, "y": 300, "btns": 0}, {"t": 265180.29999923706, "type": "move", "x": 58, "y": 302, "btns": 0}, {"t": 265331.29999923706, "type": "move", "x": 56, "y": 304, "btns": 0}, {"t": 284663.89999961853, "type": "down", "x": 30, "y": 355, "btns": 1}, {"t": 284666.29999923706, "type": "up", "x": 30, "y": 355, "btns": 0}, {"t": 304965.29999923706, "type": "move", "x": 76, "y": 73, "btns": 0}, {"t": 305040.29999923706, "type": "move", "x": 80, "y": 106, "btns": 0}, {"t": 305099.29999923706, "type": "move", "x": 80, "y": 107, "btns": 0}, {"t": 305226.29999923706, "type": "move", "x": 80, "y": 106, "btns": 0}, {"t": 305316.29999923706, "type": "move", "x": 80, "y": 103, "btns": 0}, {"t": 305361.29999923706, "type": "move", "x": 81, "y": 102, "btns": 0}, {"t": 305399.29999923706, "type": "move", "x": 81, "y": 101, "btns": 0}, {"t": 309401.29999923706, "type": "move", "x": 18, "y": 221, "btns": 0}, {"t": 309466.29999923706, "type": "move", "x": 29, "y": 250, "btns": 0}, {"t": 309550.29999923706, "type": "move", "x": 27, "y": 271, "btns": 0}, {"t": 309639.29999923706, "type": "move", "x": 31, "y": 284, "btns": 0}, {"t": 309755.29999923706, "type": "move", "x": 42, "y": 292, "btns": 0}, {"t": 309852.29999923706, "type": "move", "x": 45, "y": 294, "btns": 0}, {"t": 309917.29999923706, "type": "move", "x": 47, "y": 298, "btns": 0}, {"t": 309968.29999923706, "type": "move", "x": 51, "y": 305, "btns": 0}, {"t": 310003.29999923706, "type": "move", "x": 51, "y": 306, "btns": 0}, {"t": 310275.29999923706, "type": "down", "x": 51, "y": 306, "btns": 1}, {"t": 310370.29999923706, "type": "move", "x": 52, "y": 307, "btns": 1}, {"t": 310393.29999923706, "type": "move", "x": 54, "y": 307, "btns": 1}, {"t": 310428.29999923706, "type": "move", "x": 65, "y": 303, "btns": 1}, {"t": 310482.29999923706, "type": "move", "x": 66, "y": 303, "btns": 1}, {"t": 310566.29999923706, "type": "move", "x": 73, "y": 303, "btns": 1}, {"t": 310642.29999923706, "type": "move", "x": 75, "y": 303, "btns": 1}, {"t": 310725.29999923706, "type": "move", "x": 83, "y": 303, "btns": 1}, {"t": 310745.29999923706, "type": "move", "x": 85, "y": 303, "btns": 1}, {"t": 310782.29999923706, "type": "move", "x": 86, "y": 303, "btns": 1}, {"t": 310814.29999923706, "type": "move", "x": 88, "y": 303, "btns": 1}, {"t": 310942.29999923706, "type": "move", "x": 101, "y": 304, "btns": 1}, {"t": 311117.29999923706, "type": "move", "x": 123, "y": 304, "btns": 1}, {"t": 311236.29999923706, "type": "move", "x": 129, "y": 304, "btns": 1}, {"t": 311372.29999923706, "type": "move", "x": 142, "y": 304, "btns": 1}, {"t": 311638.29999923706, "type": "move", "x": 157, "y": 305, "btns": 1}, {"t": 311839.29999923706, "type": "move", "x": 159, "y": 306, "btns": 1}, {"t": 311861.29999923706, "type": "move", "x": 160, "y": 306, "btns": 1}, {"t": 312874.29999923706, "type": "up", "x": 160, "y": 306, "btns": 0}, {"t": 312875.29999923706, "type": "move", "x": 161, "y": 306, "btns": 0}, {"t": 313019.29999923706, "type": "move", "x": 159, "y": 306, "btns": 0}, {"t": 313066.29999923706, "type": "move", "x": 158, "y": 306, "btns": 0}, {"t": 313490.29999923706, "type": "move", "x": 156, "y": 306, "btns": 0}, {"t": 313535.29999923706, "type": "move", "x": 152, "y": 306, "btns": 0}, {"t": 313585.29999923706, "type": "move", "x": 153, "y": 306, "btns": 0}, {"t": 313618.29999923706, "type": "move", "x": 154, "y": 307, "btns": 0}, {"t": 313636.29999923706, "type": "move", "x": 155, "y": 308, "btns": 0}, {"t": 313699.29999923706, "type": "move", "x": 155, "y": 309, "btns": 0}, {"t": 313718.29999923706, "type": "move", "x": 157, "y": 309, "btns": 0}, {"t": 313774.29999923706, "type": "move", "x": 158, "y": 309, "btns": 0}]} \ No newline at end of file diff --git a/try/live_solve.py b/try/live_solve.py new file mode 100644 index 0000000..cafa30f --- /dev/null +++ b/try/live_solve.py @@ -0,0 +1,69 @@ +"""线上验证码求解(带服务端 tip_y 约束)。 + +服务端 captcha/get 响应中的 tip_y × 2 = 缺口 y 坐标(mark 画布顶)。 +经 10 组线上样本校准:solver 无约束 y 与 2×tip_y 差 ≤4px(定位准的样本), +偏差大的样本(AMBIGUOUS)正是被服务端判 VerifyErr 的。 +用 tip_y 约束 y 后在 score map 上重选 x,可显著提高准确率。 + +用法: + .venv/bin/python try/live_solve.py +输出 JSON: x(拖动目标, 原图px)、score、scale +""" +import json +import sys +from pathlib import Path + +import cv2 + +sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src")) +import method_l_shape as L # noqa: E402 + + +def live_solve(big_path, mark_path, tip_y, y_tol=8): + """tip_y 约束版求解。返回 {x, y, scale, score} 或 None。""" + try: + target_y = int(tip_y) * 2 + except (TypeError, ValueError): + return None + big = cv2.imread(big_path) + mark = cv2.imread(mark_path, cv2.IMREAD_UNCHANGED) + if big is None or mark is None: + return None + try: + d = L.setup(big, mark) + if d is None: + return None + best = [] + for s in L.SCALES: + s = round(float(s), 3) + score, w, h, ptset = L.score_at_scale(d, s) + if score is None: + continue + for v, x, y in L.nms_take(score, 30, int(0.45 * max(w, h))): + if abs(y - target_y) <= y_tol: + best.append((v, s, x, y, w, h)) + except (ValueError, IndexError, TypeError) as e: + print(f"匹配失败: {e}", file=sys.stderr) + return None + if not best: + # 放宽容差重试 + return live_solve(big_path, mark_path, tip_y, y_tol=y_tol * 2) + best.sort(key=lambda c: c[0]) + try: + v, s, x, y, w, h = best[0] + return {"x": x, "y": y, "scale": s, "score": round(float(v), 2), "w": w, "h": h} + except (IndexError, TypeError, ValueError) as e: + print(f"候选解析失败: {e}", file=sys.stderr) + return None + + +if __name__ == "__main__": + if len(sys.argv) < 4: + print(__doc__) + sys.exit(1) + try: + result = live_solve(sys.argv[1], sys.argv[2], int(sys.argv[3])) + except (OSError, ValueError) as e: + result = None + print(f"求解失败: {e}", file=sys.stderr) + print(json.dumps(result) if result else '{"ok": false}') diff --git a/try/rate_limit_probe.py b/try/rate_limit_probe.py new file mode 100644 index 0000000..1614ca8 --- /dev/null +++ b/try/rate_limit_probe.py @@ -0,0 +1,38 @@ +"""低频位探测:每 WAIT 秒单次干净尝试(只选高质量题),直到通过或轮次用完。 + +用法: python try/rate_limit_probe.py [wait_sec] [rounds] [max_score] +""" +import asyncio +import sys + +import cold_start_attempt as csa + + +async def main(): + try: + wait_sec = int(sys.argv[1]) if len(sys.argv) > 1 else 600 + rounds = int(sys.argv[2]) if len(sys.argv) > 2 else 6 + max_score = float(sys.argv[3]) if len(sys.argv) > 3 else 5.0 + except ValueError: + print("用法: python try/rate_limit_probe.py [wait_sec] [rounds] [max_score]", + file=sys.stderr) + return + for i in range(rounds): + print(f"===== round {i + 1}/{rounds} =====", flush=True) + try: + r = await csa.main_once(max_questions=4, max_score=max_score) + except RuntimeError as e: + print(f"attempt error: {e}", flush=True) + r = "error" + print(f"round {i + 1} -> {r}", flush=True) + if r == "PASS": + print("*** PASS ***", flush=True) + return + if i < rounds - 1: + print(f"冷却 {wait_sec}s...", flush=True) + await asyncio.sleep(wait_sec) + print("轮次用完", flush=True) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/try/replay_human.py b/try/replay_human.py new file mode 100644 index 0000000..d108cb0 --- /dev/null +++ b/try/replay_human.py @@ -0,0 +1,241 @@ +"""真人轨迹采集 + CDP 回放(hook 路线的落地实验) + +原理: +1. rec 阶段:在验证码 iframe document 上挂 capture 阶段监听,记录真人拖动产生的 + pointerdown/move/up + mousedown/move/up 完整事件流(含原生时序)。 +2. replay 阶段:CDP Input.dispatchMouseEvent 按录制的坐标与相对时序重放。 + CDP 事件走浏览器输入管道,isTrusted=true,事件密度/节奏与真人一致。 + +用法: + .venv/bin/python try/replay_human.py record # 进入录制模式,等用户手动拖 + .venv/bin/python try/replay_human.py replay # 刷新→solve→回放录制的真人轨迹 +""" +import asyncio +import base64 +import glob +import json +import os +import sys +import time +import urllib.request +from pathlib import Path + +import websockets + +sys.path.insert(0, str(Path(__file__).resolve().parent)) +sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src")) + +CDP_HTTP = "http://127.0.0.1:9222" +CAPT_DIR = Path(__file__).resolve().parent / "captures" +REPLAY_FILE = Path(__file__).resolve().parent / "human_trace.json" +IFRAME_X, IFRAME_Y = 770, 305 # 验证码 iframe 左上角视口坐标 +SCALE = 340 / 552 # UI 显示 / 原图 + + +def _json(path): + try: + with urllib.request.urlopen(f"{CDP_HTTP}{path}", timeout=5) as r: + return json.load(r) + except (OSError, ValueError): + return None + + +HOOK_JS = """ +(() => { + if (window.__traceHook) return 'already'; + window.__traceHook = 1; + window.__trace = []; + const types = ['pointerdown','pointermove','pointerup', + 'mousedown','mousemove','mouseup']; + for (const t of types) { + document.addEventListener(t, e => { + window.__trace.push({ + t, x: e.clientX, y: e.clientY, + ts: Math.round(e.timeStamp * 100) / 100, + buttons: e.buttons, trusted: e.isTrusted, + pressure: e.pressure || 0, + movementX: e.movementX || 0, movementY: e.movementY || 0, + }); + }, {capture: true, passive: true}); + } + return 'trace hook on'; +})() +""" + + +async def main(mode: str): + ver = _json("/json/version") + targets = _json("/json/list") or [] + if not ver: + print("CDP 9222 不可用") + return + page = next((t for t in targets if t["type"] == "page" and "douyin" in t["url"]), None) + ifr = next((t for t in targets if "rmc.bytedance.com" in t.get("url", "")), None) + if not page or not ifr: + print("找不到 douyin 页面或验证码 iframe") + return + async with websockets.connect(ver["webSocketDebuggerUrl"], max_size=64 * 1024 * 1024) as ws: + mid = [0] + + async def cdp(method, params=None, sid=None): + mid[0] += 1 + m = {"id": mid[0], "method": method, "params": params or {}} + if sid: + m["sessionId"] = sid + await ws.send(json.dumps(m)) + while True: + try: + r = json.loads(await ws.recv()) + except json.JSONDecodeError: + continue + if r.get("id") == mid[0]: + if "error" in r: + raise RuntimeError(f"{method}: {r['error']}") + return r.get("result", {}) + + psid = (await cdp("Target.attachToTarget", {"targetId": page["id"], "flatten": True}))["sessionId"] + isid = (await cdp("Target.attachToTarget", {"targetId": ifr["id"], "flatten": True}))["sessionId"] + await cdp("Runtime.enable", sid=isid) + + async def jse(expr, sid=isid): + r = await cdp("Runtime.evaluate", + {"expression": expr, "returnByValue": True, "awaitPromise": True}, sid) + return r.get("result", {}).get("value") + + # 强制重挂(页面可能刷新过,旧 hook 已失效;先拆旧 listener) + await jse(""" +(() => { + window.__trace = []; + if (window.__traceFn) { for (const [t, f] of window.__traceFn) document.removeEventListener(t, f, {capture: true}); } + window.__traceFn = []; + const types = ['pointerdown','pointermove','pointerup','mousedown','mousemove','mouseup']; + for (const t of types) { + const f = e => { + window.__trace.push({t, x: e.clientX, y: e.clientY, ts: Math.round(e.timeStamp*100)/100, + buttons: e.buttons, trusted: e.isTrusted}); + }; + document.addEventListener(t, f, {capture: true, passive: true}); + window.__traceFn.push([t, f]); + } + return 'rehooked'; +})() +""") + + if mode == "record": + print("== 录制模式:请在 20s 内用鼠标手动完成一次滑块拖动 ==") + await asyncio.sleep(20) + raw = await jse("JSON.stringify(window.__trace || [])") + try: + trace = json.loads(raw or "[]") + except (TypeError, ValueError) as e: + print(f"trace 解析失败: {e}") + return + mv = [e for e in trace if e["t"] == "mousemove"] + dn = [e for e in trace if e["t"] == "mousedown"] + print(f"共 {len(trace)} 事件: mousedown={len(dn)} mousemove={len(mv)}") + if len(dn) >= 1 and len(mv) > 10: + # 以第一次 mousedown 为拖动起点,截取到 mouseup + start_ts = dn[0]["ts"] + ups = [e["ts"] for e in trace if e["t"] == "mouseup" and e["ts"] > start_ts] + end_ts = ups[0] if ups else trace[-1]["ts"] + drag = [e for e in trace if start_ts - 50 <= e["ts"] <= end_ts] + try: + with open(REPLAY_FILE, "w") as f: + json.dump({"iframe_origin": [IFRAME_X, IFRAME_Y], "events": drag}, f) + except OSError as e: + print(f"保存失败: {e}") + return + print(f"已保存 {len(drag)} 事件({end_ts - start_ts:.0f}ms)→ {REPLAY_FILE}") + else: + print("没采到拖动,重试") + return + + # ---- replay 模式 ---- + if not REPLAY_FILE.exists(): + print("没有录制文件,先跑 record") + return + try: + with open(REPLAY_FILE) as f: + rec = json.load(f) + except (OSError, ValueError) as e: + print(f"读取录制文件失败: {e}") + return + events = rec["events"] + ox, oy = rec["iframe_origin"] + # 找 mousedown 起点 + dn = next(e for e in events if e["t"] == "mousedown") + start_x, start_y = ox + dn["x"], oy + dn["y"] + t0 = dn["ts"] + ups = [e["ts"] for e in events if e["t"] == "mouseup"] + total_ms = (ups[0] - t0) if ups else 1000 + print(f"回放 {len(events)} 事件,拖动 {total_ms:.0f}ms") + + # 刷新拿新题 + rx, ry = IFRAME_X + 30, IFRAME_Y + 355 + for typ in ("mousePressed", "mouseReleased"): + await cdp("Input.dispatchMouseEvent", + {"type": typ, "x": rx, "y": ry, "button": "left", "buttons": 1, + "clickCount": 1}, psid) + got = None + t0w = time.time() + while time.time() - t0w < 14 and not got: + await asyncio.sleep(0.5) + fs = sorted(glob.glob(str(CAPT_DIR / "net_*_get.json")), reverse=True) + if fs and time.time() - os.path.getmtime(fs[0]) < 10: + ts = os.path.basename(fs[0]).split("_")[1] + await asyncio.sleep(2.5) + jpgs = [f for f in glob.glob(str(CAPT_DIR / f"net_{ts}_*")) if f.endswith((".jpg", ".jpeg"))] + pngs = [f for f in glob.glob(str(CAPT_DIR / f"net_{ts}_*")) if f.endswith(".png")] + if jpgs and pngs: + got = (ts, jpgs[0], pngs[0]) + if not got: + print("没等到题") + return + ts, big_f, mark_f = got + try: + with open(f"{CAPT_DIR}/net_{ts}_get.json") as f: + tip_y = json.load(f)["data"]["question"]["tip_y"] + except (OSError, KeyError, ValueError) as e: + print(f"get.json 读取失败: {e}") + return + from solve import solve + try: + with open(big_f, "rb") as f: + big_b64 = base64.b64encode(f.read()).decode() + with open(mark_f, "rb") as f: + mark_b64 = base64.b64encode(f.read()).decode() + except OSError as e: + print(f"图片读取失败: {e}") + return + result = solve(big_b64, mark_b64) + print(f"[{ts}] tip_y={tip_y} solve:", {k: result[k] for k in ("ok", "x", "score") if k in result}) + if not result.get("ok"): + return + dist_ui = result["x"] * SCALE + print(f"需拖 {dist_ui:.1f}px(UI),录制拖动 {total_ms:.0f}ms") + + # 回放:mousedown → 按 ts 差调度 mousemove → mouseup + await cdp("Input.dispatchMouseEvent", + {"type": "mousePressed", "x": start_x, "y": start_y, + "button": "left", "buttons": 1, "clickCount": 1}, psid) + t_start = time.time() + for e in events: + if e["t"] != "mousemove" or e["ts"] <= t0: + continue + delay = (e["ts"] - t0) / 1000.0 - (time.time() - t_start) + if delay > 0: + await asyncio.sleep(delay) + await cdp("Input.dispatchMouseEvent", + {"type": "mouseMoved", "x": ox + e["x"], "y": oy + e["y"], + "button": "left", "buttons": 1}, psid) + await asyncio.sleep(0.25) + await cdp("Input.dispatchMouseEvent", + {"type": "mouseReleased", "x": ox + events[-1]["x"], "y": oy + events[-1]["y"], + "button": "left", "buttons": 1, "clickCount": 1}, psid) + print("回放完成") + await asyncio.sleep(4) + + +if __name__ == "__main__": + mode = sys.argv[1] if len(sys.argv) > 1 else "record" + asyncio.run(main(mode)) diff --git a/try/rotate_loop.py b/try/rotate_loop.py new file mode 100644 index 0000000..ab210e7 --- /dev/null +++ b/try/rotate_loop.py @@ -0,0 +1,92 @@ +"""5014 零等待换号循环:失败 → 立即重载页面换新随机号重试,PASS 即停。 + +用户指令:不需要等待冷却时间,风控(5014)就直接换账号触发。 +每次尝试 = Page.reload(清 session)→ 新随机手机号/密码 → 触发 → solve → xdotool 拖动。 +""" +import asyncio, sys, time + +sys.path.insert(0, "/home/yanghao05/Workspace/dy-captcha/try") +sys.path.insert(0, "/home/yanghao05/Workspace/dy-captcha/src") +import os +os.environ["XDOTOOL"] = "1" +os.environ["REPLAY"] = "1" +os.environ["REPLAY_FILE"] = "/home/yanghao05/Workspace/dy-captcha/try/human_trace_pass.json" +os.environ["REPLAY_SEG"] = "last" +os.environ["REPLAY_MS"] = "2600" +import cold_start_attempt as cs + + +async def reload_page(): + """Page.reload 清 session,等加载完成。""" + import json, urllib.request as ur + try: + with ur.urlopen("http://127.0.0.1:9222/json/version", timeout=5) as r: + ver = json.load(r) + except (OSError, ValueError) as e: + print(f"CDP 不可达: {e}", flush=True) + return False + targets = cs._json("/json/list") or [] + page = next((t for t in targets if t["type"] == "page" and "douyin" in t.get("url", "")), None) + if not page: + return False + import websockets + async with websockets.connect(ver["webSocketDebuggerUrl"], max_size=64*1024*1024) as ws: + mid = [0] + async def cdp(method, params=None, sid=None): + mid[0] += 1 + m = {"id": mid[0], "method": method, "params": params or {}} + if sid: + m["sessionId"] = sid + await ws.send(json.dumps(m)) + while True: + try: + resp = json.loads(await ws.recv()) + except (json.JSONDecodeError, asyncio.TimeoutError): + continue + if resp.get("id") == mid[0]: + return resp + psid = (await cdp("Target.attachToTarget", {"targetId": page["id"], "flatten": True})).get("result", {}).get("sessionId") + # 清 cookie(用户指令:限流时清 cookie 即可解除触发限制) + await cdp("Network.enable", sid=psid) + await cdp("Network.clearBrowserCookies", sid=psid) + await cdp("Page.enable", sid=psid) + # cookie 清空后 session 失效可能跳转 —— 直接导航回目标页(比 reload 稳) + await cdp("Page.navigate", {"url": "https://www.douyin.com/jingxuan"}, sid=psid) + # 等主 frame 加载完成(最多 15s) + for _ in range(60): + try: + ev = json.loads(await asyncio.wait_for(ws.recv(), timeout=2)) + except (asyncio.TimeoutError, json.JSONDecodeError, ValueError): + continue + if ev.get("method") == "Page.loadEventFired" and ev.get("sessionId") == psid: + break + await asyncio.sleep(3) + return True + + +async def main(): + for i in range(20): + print(f"\n=== 尝试 {i+1} @ {time.strftime('%H:%M:%S')} ===", flush=True) + # 失败后换号:重载页面(首次不重载,页面已是干净状态则直接用) + if i > 0: + try: + ok = await reload_page() + if not ok: + print("页面未找到,跳过", flush=True) + continue + except Exception as e: + print(f"reload 异常: {e}", flush=True) + try: + r = await cs.main_once(3, 9) + except Exception as e: + print(f"异常: {e}", flush=True) + r = "error" + print(f"结果: {r}", flush=True) + if r == "PASS": + print("*** CLOSED LOOP! ***", flush=True) + return + # 5014/500/502 全部立即换号重试,无等待 + print("20 次尝试完毕", flush=True) + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/try/sdk_explore.py b/try/sdk_explore.py new file mode 100644 index 0000000..797036a --- /dev/null +++ b/try/sdk_explore.py @@ -0,0 +1,82 @@ +"""探测验证码 iframe 内 SDK 结构:script 源、addEventListener 采集点、轨迹缓冲。""" +import asyncio, json, urllib.request, sys +import websockets + +CDP_HTTP = "http://127.0.0.1:9222" + +def _json(path): + try: + with urllib.request.urlopen(f"{CDP_HTTP}{path}", timeout=5) as r: + return json.load(r) + except (OSError, ValueError): + return None + +async def main(): + ver = _json("/json/version") + targets = _json("/json/list") or [] + if not ver or "webSocketDebuggerUrl" not in ver: + print("CDP 9222 不可用", file=sys.stderr); return + cand = [t for t in targets if "rmc" in t.get("url","") or "captcha" in t.get("url","").lower()] + if not cand: + print("未找到 captcha iframe,targets:") + for t in targets: print(" ", t["type"], t["url"][:80]) + return + tgt = cand[0] + print("探测目标:", tgt["url"][:100]) + async with websockets.connect(ver["webSocketDebuggerUrl"], max_size=64*1024*1024) as ws: + mid = [0] + async def cdp(method, params=None, sid=None): + mid[0] += 1 + m = {"id": mid[0], "method": method, "params": params or {}} + if sid: m["sessionId"] = sid + await ws.send(json.dumps(m)) + while True: + try: + r = json.loads(await ws.recv()) + except json.JSONDecodeError: + continue + if r.get("id") == mid[0]: + if "error" in r: raise RuntimeError(f"{method}: {r['error']}") + return r.get("result", {}) + sid = (await cdp("Target.attachToTarget", + {"targetId": tgt["id"], "flatten": True}))["sessionId"] + await cdp("Runtime.enable", sid=sid) + + async def js(expr): + r = await cdp("Runtime.evaluate", + {"expression": expr, "returnByValue": True, + "awaitPromise": True, "userGesture": True}, sid) + return r.get("result", {}).get("value") + + # 1) 挂 listener 记录 hook(记录到 window 全局,跨 evaluate 可读) + await js(""" +(() => { + if (window.__lh) return 'already'; + const orig = EventTarget.prototype.addEventListener; + window.__lh = []; + EventTarget.prototype.addEventListener = function(t, f, o){ + try { window.__lh.push([t, String(f && f.name || 'anon'), + String(f).slice(0,120).replace(/\\n/g,' ')]); } catch(e){} + return orig.call(this, t, f, o); + }; + return 'hook installed'; +})() +""") + # 2) 已有 listener(getEventListeners 仅 DevTools 可用,改用枚举 on* + 重放脚本已知点) + scripts = await js("[...document.scripts].map(s=>s.src||('inline:'+s.textContent.length)).join('\\n')") + print("== scripts ==\\n" + str(scripts)) + globals_ = await js(""" +Object.getOwnPropertyNames(window).filter(k=>/captcha|verify|secsdk|byted|rms|rmc|track|slid|nocaptcha/i.test(k)).join('\\n') +""") + print("== 全局候选 ==\\n" + str(globals_)) + await asyncio.sleep(15) + log = await js("JSON.stringify(window.__lh||[])") + try: + rows = json.loads(log or "[]") + except (TypeError, ValueError) as e: + print(f"__lh 解析失败: {e}", file=sys.stderr) + return + print(f"== 15s 内 addEventListener 调用: {len(rows)} ==") + for t, name, src in rows: + print(f" [{t}] {name} :: {src[:110]}") +asyncio.run(main()) diff --git a/try/solo_attempt.py b/try/solo_attempt.py new file mode 100644 index 0000000..bb7d0f6 --- /dev/null +++ b/try/solo_attempt.py @@ -0,0 +1,150 @@ +"""单次干净尝试:刷新→采题→solve(score<=阈值才出手)→force=0.5 拖动→读 verify。 + +用法: python try/solo_attempt.py [wait_sec] [max_score] +频控敏感:每次尝试间隔 wait_sec(默认 600s)。 +""" +import asyncio, json, sys, time, base64, random, urllib.request as ur +from pathlib import Path +import websockets + +sys.path.insert(0, str(Path(__file__).resolve().parent)) +sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "src")) +from solve import solve +from human_drag import gen_human_path + +CDP = "http://127.0.0.1:9222" +IFRAME_X, IFRAME_Y = 770, 305 +SCALE = 340 / 552 +HOOK = """ +(() => { + window.__lastGet=null; window.__lastVerify=null; + const oOpen=XMLHttpRequest.prototype.open, oSend=XMLHttpRequest.prototype.send; + XMLHttpRequest.prototype.open=function(m,u){this.__u=u;return oOpen.apply(this,arguments);}; + XMLHttpRequest.prototype.send=function(){const x=this;this.addEventListener('load',()=>{ + try{ if(/captcha\\/get/.test(x.__u||'')) window.__lastGet=JSON.parse(x.responseText); + if(/captcha\\/verify/.test(x.__u||'')) window.__lastVerify=x.responseText.slice(0,200);}catch(e){}});return oSend.apply(this,arguments);}; + return 'ok'; +})() +""" + + +def _json(path): + try: + with ur.urlopen(f"{CDP}{path}", timeout=5) as r: + return json.load(r) + except (OSError, ValueError): + return None + + +async def one_attempt(ws, mid_ref, max_score): + async def cdp(method, params=None, sid=None): + mid_ref[0] += 1 + m = {"id": mid_ref[0], "method": method, "params": params or {}} + if sid: + m["sessionId"] = sid + await ws.send(json.dumps(m)) + while True: + try: + r = json.loads(await ws.recv()) + except (json.JSONDecodeError, asyncio.TimeoutError): + continue + if r.get("id") == mid_ref[0]: + if "error" in r: + raise RuntimeError(f"{method}: {r['error']}") + return r.get("result", {}) + + targets = _json("/json/list") or [] + page = next((t for t in targets if t["type"] == "page" and "douyin" in t.get("url", "")), None) + ifr = next((t for t in targets if "rmc.bytedance.com" in t.get("url", "")), None) + if not page or not ifr: + print("页面或验证码 iframe 不在", flush=True) + return None + psid = (await cdp("Target.attachToTarget", {"targetId": page["id"], "flatten": True}))["sessionId"] + isid = (await cdp("Target.attachToTarget", {"targetId": ifr["id"], "flatten": True}))["sessionId"] + await cdp("Runtime.enable", sid=isid) + + async def jse(expr, sid=isid): + r = await cdp("Runtime.evaluate", + {"expression": expr, "returnByValue": True, "awaitPromise": True}, sid) + return r.get("result", {}).get("value") + + await jse(HOOK) + for typ in ("mousePressed", "mouseReleased"): + await cdp("Input.dispatchMouseEvent", + {"type": typ, "x": IFRAME_X + 30, "y": IFRAME_Y + 355, + "button": "left", "buttons": 0, "clickCount": 1}, psid) + g = None + t0 = time.time() + while time.time() - t0 < 8 and not g: + await asyncio.sleep(0.8) + gg = await jse("JSON.stringify(window.__lastGet)") + if gg and gg != "null": + try: + g = json.loads(gg) + except ValueError: + g = None + if not g: + print("no get", flush=True) + return None + q = g["data"]["question"] + with ur.urlopen(q["url1"]) as r: + big = r.read() + with ur.urlopen(q["url2"]) as r: + mark = r.read() + res = solve(base64.b64encode(big).decode(), base64.b64encode(mark).decode(), tip_y=q["tip_y"]) + print(f"tip_y={q['tip_y']} solve={ {k: res.get(k) for k in ('x','y','scale','score','confidence')} }", flush=True) + if not res.get("ok") or res.get("confidence") != "OK" or res.get("score", 99) > max_score: + print("低质量题,跳过拖动", flush=True) + return None + dist_ui = res["x"] * SCALE + sx, sy = IFRAME_X + 54, IFRAME_Y + 307 + pts = gen_human_path(dist_ui, seed=random.randint(1, 9999)) + await cdp("Input.dispatchMouseEvent", + {"type": "mousePressed", "x": sx, "y": sy, "button": "left", + "buttons": 1, "clickCount": 1, "force": 0.5}, psid) + await asyncio.sleep(0.25) + cx, cy = sx, sy + for dx, dy, dt in pts: + cx += dx + cy += dy + await asyncio.sleep(dt / 1000) + await cdp("Input.dispatchMouseEvent", + {"type": "mouseMoved", "x": round(cx, 1), "y": round(cy, 1), + "button": "left", "buttons": 1, "force": 0.5}, psid) + await asyncio.sleep(0.35) + await cdp("Input.dispatchMouseEvent", + {"type": "mouseReleased", "x": round(cx, 1), "y": round(cy, 1), + "button": "left", "buttons": 1, "clickCount": 1, "force": 0.5}, psid) + await asyncio.sleep(3) + v = await jse("JSON.stringify(window.__lastVerify)") + print("verify:", (v or "null")[-90:], flush=True) + return v + + +async def main(): + try: + wait_sec = int(sys.argv[1]) if len(sys.argv) > 1 else 600 + max_score = float(sys.argv[2]) if len(sys.argv) > 2 else 4.2 + except ValueError: + print("用法: python try/solo_attempt.py [wait_sec] [max_score]", file=sys.stderr) + return + ver = _json("/json/version") + if not ver or not ver.get("webSocketDebuggerUrl"): + print("无法连接 CDP", file=sys.stderr) + return + async with websockets.connect(ver["webSocketDebuggerUrl"], max_size=64 * 1024 * 1024) as ws: + mid = [0] + while True: + try: + v = await one_attempt(ws, mid, max_score) + if v and '"code":200' in v: + print("*** PASS ***", flush=True) + return + except Exception as e: + print("attempt error:", e, flush=True) + print(f"等待 {wait_sec}s(频控冷却)...", flush=True) + await asyncio.sleep(wait_sec) + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/try/trace_watch.py b/try/trace_watch.py new file mode 100644 index 0000000..b6cf5ae --- /dev/null +++ b/try/trace_watch.py @@ -0,0 +1,77 @@ +"""真人拖动轨迹监视器:等 rmc iframe 出现后 attach,每 0.5s 快照 +window.__dragTrace / __lastVerify 到 /tmp,iframe 销毁(验证通过)后保留最后快照退出。""" +import asyncio, json, time, urllib.request as ur +import websockets + + +def _json(path): + try: + with ur.urlopen(f"http://127.0.0.1:9222{path}", timeout=5) as r: + return json.load(r) + except (OSError, ValueError): + return None + + +async def main(): + ver = _json("/json/version") + if not ver or not ver.get("webSocketDebuggerUrl"): + print("CDP 不可达,退出") + return + # 等待验证码 iframe 出现(最多 180s) + ifr = None + for _ in range(60): + targets = _json("/json/list") or [] + ifr = next((t for t in targets if "rmc.bytedance.com" in t.get("url", "")), None) + if ifr: + break + await asyncio.sleep(3) + if not ifr: + print("无 iframe,退出") + return + async with websockets.connect(ver["webSocketDebuggerUrl"], max_size=64 * 1024 * 1024) as ws: + mid = [0] + + async def cdp(method, params=None, sid=None): + mid[0] += 1 + m = {"id": mid[0], "method": method, "params": params or {}} + if sid: + m["sessionId"] = sid + await ws.send(json.dumps(m)) + while True: + try: + r = json.loads(await ws.recv()) + except (json.JSONDecodeError, asyncio.TimeoutError): + continue + if r.get("id") == mid[0]: + if "error" in r: + raise RuntimeError(str(r["error"])) + return r.get("result", {}) + + isid = (await cdp("Target.attachToTarget", {"targetId": ifr["id"], "flatten": True}))["sessionId"] + await cdp("Runtime.enable", sid=isid) + print("trace_watch 就绪", flush=True) + last_len = -1 + while True: + try: + r = await cdp("Runtime.evaluate", { + "expression": "JSON.stringify({n:(window.__dragTrace||[]).length," + "trace:window.__dragTrace||null,v:window.__lastVerify||null})", + "returnByValue": True}, sid=isid) + val = r.get("result", {}).get("value") + if val: + d = json.loads(val) + if d["n"] != last_len: + last_len = d["n"] + with open("/tmp/trace_snap.json", "w") as f: + json.dump(d, f) + if d["v"]: + with open("/tmp/verify_snap.txt", "w") as f: + f.write(d["v"]) + print(f"[{time.strftime('%H:%M:%S')}] {d['n']} 事件", flush=True) + await asyncio.sleep(0.5) + except (RuntimeError, websockets.exceptions.ConnectionClosed, OSError): + print("iframe 已销毁,保留最后快照退出", flush=True) + return + + +asyncio.run(main())