refactor(纯算): 移除全部补环境后端,收敛为纯算单一路径 + 修复两处红灯

做了什么:
- 删除 generate_telemetry_node/browser/probe 三个伪造环境后端, 以及 apply_real_environment、
  4 段拼接旧结构、human_dt_ms、generate_collect_pure (crypto.py 955 -> 389 行)
- 遥测只剩纯算: python_keyed = Node 仅提取 XTEA 密钥字 + Python 模板回填 + 教科书 XTEA
- 修复 crypto.py 重复的 xtea_encrypt_block (内置自测从失败到通过), 并并入 selftest
- 修复 glyph_solver 强校验: 改用集成得分矩阵行 argmax 自洽校验, 回归 5/8 -> 8/8
- 移除注释里无证据的 errorCode=12 归因; 移除 12 自动换 IP 重试
- extract_eks 不再写死变量名; UA 常量统一为 Chrome/155
- 文档对齐: ANALYSIS §8 修订 / PROGRESS 重写 / TOOLCHAIN_REPORT §三 更正

为什么:
- 本项目证据账本已证: 12 与遥测后端/出口 IP/静默时长均无关, 补环境无收益且引入脆弱面
- 强校验用单引擎 ocr_text 会误杀正确解 (实测 簿->垂 / 笆->芭 / 筹->努)

怎么验证:
- .venv/bin/python -m tcaptcha.selftest 全绿 (crypto_core + glyph 8/8 + xtea_key)
- 端到端纯算: python / python_keyed 均可解回 '{"cd":[' 开头明文, probe 模式被拒绝
This commit is contained in:
yml2213
2026-10-11 21:30:26 +08:00
parent 60ae14d54a
commit 47ce74b160
11 changed files with 297 additions and 753 deletions
+10 -6
View File
@@ -55,10 +55,10 @@ class OneMsAdapter:
def __init__(self, cookie: Optional[str] = None, user_agent: str = DEFAULT_USER_AGENT,
timeout: float = 15.0, proxy: Optional[str] = None,
proxy_api: Optional[str] = None, telemetry_mode: str = "probe"):
proxy_api: Optional[str] = None, telemetry_mode: str = "python_keyed"):
self.user_agent = user_agent
self.timeout = timeout
# 腾讯天御按出口 IP 做滚动风控 (errorCode=12); 给了 proxy_api 就能自动换 IP 重试
# 出口代理 (可选)。注意: 实测换出口 IP 并不能解决 errorCode=12 (见 ANALYSIS.md §7)
self.proxy = proxy
self.proxy_api = proxy_api
self.telemetry_mode = telemetry_mode
@@ -101,8 +101,9 @@ class OneMsAdapter:
"""
取得可提交给毫秒业务接口的 (ticket, randstr)。
若配置了 `proxy_api`, 在遇到 `errorCode=12` (f_limit, IP 级滚动风控) 时会
自动换一个出口 IP 重试, 最多 `max_proxy_rotations` 次。
仅在**网络/代理异常**时换出口 IP 重试 (最多 max_proxy_rotations 次)。
业务层失败 (errorCode 12 / 50) **不换 IP** —— 实测换 IP 对 errorCode=12
无效 (见 har/1ms_dianxuan/ANALYSIS.md §7)。
"""
params = self.fetch_captcha_params(scene=scene)
logger.info("毫秒验证码参数: provider=%s appId=%s enabled=%s sessionUuid=%s",
@@ -130,11 +131,13 @@ class OneMsAdapter:
proxy=proxy,
telemetry_mode=self.telemetry_mode,
)
connectivity_error = False
try:
result = client.solve(max_retries=max_retries, max_refreshes=8)
except Exception as e:
logger.error("客户端解题发生异常 (可能代理失效或超时): %s", e)
result = {"success": False, "error": str(e)}
connectivity_error = True
finally:
client.close()
@@ -142,14 +145,15 @@ class OneMsAdapter:
if result.get("success"):
return result.get("ticket") or None, result.get("randstr") or None, result
if not self.proxy_api:
# 业务层失败 (坐标错 / 风控 12) 与出口 IP 无关: 不换 IP, 直接返回
if not connectivity_error or not self.proxy_api:
break
from tcaptcha.proxy import fetch_proxy
new_proxy = fetch_proxy(self.proxy_api)
if new_proxy:
proxy = new_proxy
logger.warning("换出口 IP 继续尝试 (%d/%d): %s",
logger.warning("代理不可用, 换出口 IP 重试 (%d/%d): %s",
rotation + 1, max_proxy_rotations, proxy)
else:
logger.warning("未能从代理 API 取到新代理,终止重试")