Files
hello_js_reverse_skill/tcaptcha/targets.py
T
yml2213 99565f65f0 feat(web): 新增 Web 观测台(形态 A)+ 抽出 render/targets 共用层
- tcaptcha/web/:FastAPI + SSE + 零构建单页。把同步阻塞的 solve() 包成可观测
  后台任务(工作线程 + 全局串行,因 onnxruntime session 非线程安全),用
  logging.Handler 零侵入把 client 日志变成事件流;按靶子实测 min_interval 强制节流。
- tcaptcha/render.py:标注图(点击顺序编号 + 质心偏差)与点位量尺,CLI 与 web 共用。
- tcaptcha/targets.py:靶子表提为单一来源(含实测频控间隔 1ms=60s / mliev=3s)。
- fastapi/uvicorn 走 optional extra `web`,核心包零 web 依赖(带回归断言)。
- 修两个真 bug:hook 求解器时 args[0] 是实例自身(真入参从 args[1] 起);
  client 默认每次新建 solver,预热实例未被复用(每发重载 56MB ONNX)。
- 复验:icon/text/slider 三题型各拿到 errorCode=0;selftest 全绿;依赖隔离通过。

用法:uv run --extra web python -m tcaptcha.web.app
2026-10-14 19:10:54 +08:00

61 lines
2.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""靶子表 —— aid / 入口 / referer / wb,以及每个 aid **实测出来的频控节流参数**。
为什么靶子要带 `min_interval`:`aid=195672344`(1ms) 有 **aid+IP 级频控**,
短时间连打会被判 `errorCode=12`(2026-10-14 实测,见 har/1ms_dianxuan/PROGRESS.md 已知 #75):
间隔 4s × 12 发 -> 只有前 2 发过,之后 10 连 12(icon/text/slider 一起中招)
冷却 2min + 间隔 30s -> 6 发全 12(冷却不够)
冷却 25min + 间隔 60s -> 4 发全 0(恢复)
所以靶子不是"随便打"的:CLI 与界面都必须按 `min_interval` 节流,否则看到的一片红
全是频控噪声、会被误读成"求解失败"。而 `190758559`(mliev) 是宽松靶,
正确作答 22 次拿到 20 次 `errorCode=0`,适合做回归。
"""
from __future__ import annotations
from typing import Dict, TypedDict
class Target(TypedDict):
aid: str
entry_url: str
referer: str
wb: str
min_interval: float # 两次求解之间的最小间隔(秒)—— 实测频控节流
note: str
TARGETS: Dict[str, Target] = {
# 用户主靶:1ms 签到页。频控很紧,必须低频。
"1ms": {
"aid": "195672344",
"entry_url": "https://1ms.run/console/personal/benefits/check-in",
"referer": "https://1ms.run/",
"wb": "1",
"min_interval": 60.0,
"note": "主靶(2404/2408/2402 三种题型混发);有 aid+IP 频控,≥60s 一发、连打不超过 ~2 发",
},
# 可复现正样本靶:mliev 短信登录。题率低但宽松,适合回归。
"mliev": {
"aid": "190758559",
"entry_url": "https://mliev.login.wang/auth/#/oidc/authorize",
"referer": "https://mliev.login.wang/",
"wb": "1",
"min_interval": 3.0,
"note": "回归靶(约 1/10 抽中 2408);宽松,正确作答 22 次→0×20",
},
}
def get_target(key: str) -> Target:
if key not in TARGETS:
raise KeyError("未知靶子 %r(可选:%s)" % (key, ", ".join(TARGETS)))
return TARGETS[key]
def describe() -> list:
"""给界面用的靶子列表。"""
return [{"key": k, **v} for k, v in TARGETS.items()]