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:
@@ -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())
|
||||
Reference in New Issue
Block a user