feat(纯算): 增加 captcha 域 cookie 透传 + H3 单变量实验脚本

做了什么:
- TencentCaptchaClient 新增可选 cookies 参数, 逐条写入 captcha 域 Cookie 头 (默认 None, 行为不变)
- OneMsAdapter 新增 captcha_cookies 透传
- 新增 scripts/experiment_h3_cookie_ab.py: 只改 cookie 一个变量做 A/B 对照并自动判读

为什么:
- 账本 §7.5 的 H3 (腾讯云登录 cookie uin/skey/qcmainCSRFToken/intl) 是唯一
  尚未单变量验证过的差异; 其余 (环境 / 后端 / 出口 IP / 静默时长) 均已排除

怎么验证:
- 离线: 带 cookie 时请求头为 Cookie=uin=..;intl=1, 不带时为 None (默认行为不变)
- .venv/bin/python -m tcaptcha.selftest 全绿 (crypto_core + glyph 8/8 + xtea_key)
This commit is contained in:
yml2213
2026-10-11 21:36:59 +08:00
parent 47ce74b160
commit 795235ac38
3 changed files with 140 additions and 12 deletions
+113
View File
@@ -0,0 +1,113 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
H3 单变量实验: captcha 域「带 / 不带」腾讯云登录 cookie 对 errorCode=12 的影响
依据: AGENTS.md §2.1 (用服务端响应画生死线) 与 har/1ms_dianxuan/ANALYSIS.md §7.5。
背景 (已确证): 12 与遥测后端 / 出口 IP / 静默时长均无关。成功样本
(har/签到成功-1.har) 的 captcha 域 prehandle 带着腾讯云登录 cookie
(uin / skey / qcmainCSRFToken / intl), 而本客户端此前完全不带 —— 这是唯一
未被单变量验证过的差异 (H3)。
本脚本**只改一个变量 (cookie)**, 其余参数完全相同, 依次跑两次:
A) 不带 cookie B) 带 cookie
判读:
A=12 且 B=0 -> H3 成立 (纯算流程只需补上该 cookie)
A=12 且 B=12 -> H3 排除, 转 H1/H2 (真实验证码页面上下文 / 自动化检测)
用法:
.venv/bin/python scripts/experiment_h3_cookie_ab.py --aid 195672344 \
--entry-url https://1ms.run/console/personal/benefits/check-in \
--uin 100012108023 --skey xxxxxxxx --csrf xxxxxxxx --intl 1 \
[--referer https://1ms.run/] [--proxy http://user:pass@host:port]
cookie 获取: 浏览器 F12 -> Application -> Cookies -> https://turing.captcha.qcloud.com/
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from tcaptcha.client import KIND_TEXT_CLICK, TencentCaptchaClient # noqa: E402
def run_once(tag: str, cookies, args) -> dict:
client = TencentCaptchaClient(
aid=args.aid,
entry_url=args.entry_url,
referer=args.referer,
wb=args.wb,
accept_kinds=(KIND_TEXT_CLICK,),
telemetry_mode=args.telemetry,
proxy=args.proxy,
cookies=cookies,
)
try:
result = client.solve(max_retries=args.retries, max_refreshes=8)
finally:
client.close()
raw = result.get("raw_response") or {}
print(f"\n[{tag}] success={result['success']} "
f"errorCode={raw.get('errorCode')} errMessage={raw.get('errMessage', '')!r}")
print(f" error={result.get('error', '')}")
return result
def main() -> int:
ap = argparse.ArgumentParser(description="H3: captcha 域 cookie 单变量实验")
ap.add_argument("--aid", default="195672344")
ap.add_argument("--entry-url", default="https://1ms.run/console/personal/benefits/check-in")
ap.add_argument("--referer", default="https://1ms.run/")
ap.add_argument("--wb", default="1")
ap.add_argument("--retries", type=int, default=3)
ap.add_argument("--telemetry", default="python_keyed", choices=["python_keyed", "python"])
ap.add_argument("--proxy", default=None)
# 腾讯云登录 cookie (从浏览器取)
ap.add_argument("--uin", default="")
ap.add_argument("--skey", default="")
ap.add_argument("--csrf", dest="csrf", default="", help="qcmainCSRFToken")
ap.add_argument("--intl", default="1")
ap.add_argument("--both", action="store_true",
help="先跑 A(不带) 再跑 B(带); 默认只跑 A")
ap.add_argument("--only", choices=["a", "b"], default="a",
help="只跑 A(不带 cookie) 或 B(带 cookie)")
args = ap.parse_args()
cookies = {k: v for k, v in {
"uin": args.uin, "skey": args.skey, "qcmainCSRFToken": args.csrf, "intl": args.intl,
}.items() if v}
if args.only == "b" or args.both:
if not cookies:
print("[-] 跑 B 必须提供 uin/skey/csrf 等 cookie", file=sys.stderr)
return 2
plan = ["a", "b"] if args.both else [args.only]
summary = {}
for which in plan:
if which == "a":
r = run_once("A 不带 cookie", None, args)
else:
r = run_once("B 带 cookie ", cookies, args)
summary[which] = (r.get("raw_response") or {}).get("errorCode")
print("\n=== 判读 ===")
print(json.dumps({"A_no_cookie": summary.get("a"), "B_with_cookie": summary.get("b")},
ensure_ascii=False))
if args.both:
a, b = summary.get("a"), summary.get("b")
if str(a) == "12" and str(b) == "0":
print("=> H3 成立: 补上 captcha 域 cookie 即可通过")
elif str(a) == "12" and str(b) == "12":
print("=> H3 排除: 转 H1/H2 (真实验证码页面上下文 / 自动化检测)")
return 0
if __name__ == "__main__":
raise SystemExit(main())