refactor(cmcc): 重放改两轮判别(轮1探活 + 轮2五发作死/活判别)
真机 2026-11-09 08:40 首跑暴露:60 发 + 两次 600s 静默 = 51 分钟,
最后才知道素材死了。三轮砸时间的假设(冷却自愈)在素材真死时纯浪费。
新策略:
- 轮1:15 发快节拍;全 88B → 疑似冷却,静默 600s
- 轮2:只打 5 发作判别 —— 仍全 88B 立即判死早停(stats.verdict=dead_seed);
出现非 88B 形态说明服务在响应素材,继续跑满
- 结论:活的场景 12 分钟内出结果,死的场景也是 12 分钟明确,不再拖 51 分钟
This commit is contained in:
@@ -126,10 +126,8 @@ REPLAY_MAX = 30 # 单轮命中即停:实测中位 1~9 发
|
|||||||
REPLAY_GAP = 5.0 # 3~5s 快节拍(慢节拍推向 236B 通道)
|
REPLAY_GAP = 5.0 # 3~5s 快节拍(慢节拍推向 236B 通道)
|
||||||
WALL_LIMIT = 6 * 60 # 单轮 [A] 墙钟上限(含长静默)
|
WALL_LIMIT = 6 * 60 # 单轮 [A] 墙钟上限(含长静默)
|
||||||
BACKOFF_AFTER = 15 # 连续 15 败 → 静默(防风暴冷却)
|
BACKOFF_AFTER = 15 # 连续 15 败 → 静默(防风暴冷却)
|
||||||
|
COOLDOWN_ROUNDS = 2 # 轮1 探命中 + 轮2 死/活判别(详见 replay_auto_login 文档)
|
||||||
BACKOFF_SECS = 600
|
BACKOFF_SECS = 600
|
||||||
COOLDOWN_ROUNDS = 3 # ★ 冷却自愈:整轮未命中时,静默后重开一轮,最多 3 轮
|
|
||||||
# (素材在冷却期时 88B×15 + 600s 静默 ≈ 12min/轮;
|
|
||||||
# 实测静默 ≥10 分钟恢复命中,3 轮覆盖 ~36 分钟,足够穿出冷却期)
|
|
||||||
THROTTLE = 1.2 # 业务请求间隔
|
THROTTLE = 1.2 # 业务请求间隔
|
||||||
|
|
||||||
MASK = lambda s: (s[:3] + "****" + s[-4:]) if s and len(s) >= 7 else (s or "?")
|
MASK = lambda s: (s[:3] + "****" + s[-4:]) if s and len(s) >= 7 else (s or "?")
|
||||||
@@ -316,14 +314,24 @@ def classify(resp):
|
|||||||
|
|
||||||
def replay_auto_login(seed, stats):
|
def replay_auto_login(seed, stats):
|
||||||
"""重放至 492 命中,命中即停。无状态 post(Session 的 jar 会污染素材 Cookie)。
|
"""重放至 492 命中,命中即停。无状态 post(Session 的 jar 会污染素材 Cookie)。
|
||||||
★ 冷却自愈:单轮 15 败 → 静默 600s → 重开一轮(试数归零),最多 COOLDOWN_ROUNDS 轮。
|
|
||||||
素材在冷却期(88B)时靠这个穿出去;3 轮全 88B 才认输(诊断文案会说「稍后重跑」。)"""
|
★ 两轮判定(2026-11-09 真机重写,取代原三轮砸时间):
|
||||||
|
轮1:15 发快节拍(75s)。全 88B → 可能是冷却期,也可能是素材已死。
|
||||||
|
静默 600s(冷却期实测 ≥10 分钟释放)。
|
||||||
|
轮2:只打 5 发(25s)作判别——
|
||||||
|
仍全 88B → 静默后依然拒收 = **素材本身失效**,立即早停(不再烧时间)
|
||||||
|
出现任何非 88B(64/236/152/492)→ 说明服务在响应素材,继续跑满
|
||||||
|
这样「活了」的场景最多 12 分钟出结果,「死了」的场景也是 12 分钟就明确,
|
||||||
|
不再出现 11-09 那种 60 发 + 20 分钟静默后才说失败的情况。"""
|
||||||
|
DEAD_PROBE = 5 # 轮2 判别发数
|
||||||
total_tried = 0
|
total_tried = 0
|
||||||
for round_no in range(1, COOLDOWN_ROUNDS + 1):
|
for round_no in (1, 2):
|
||||||
start = time.time()
|
start = time.time()
|
||||||
tried = 0
|
tried = 0
|
||||||
backed = False
|
backed = False
|
||||||
while tried < REPLAY_MAX and time.time() - start < WALL_LIMIT:
|
cap = REPLAY_MAX if round_no == 1 else DEAD_PROBE
|
||||||
|
only_88 = True # 本轮是否「清一色 88B」
|
||||||
|
while tried < cap and time.time() - start < WALL_LIMIT:
|
||||||
tried += 1
|
tried += 1
|
||||||
total_tried += 1
|
total_tried += 1
|
||||||
try:
|
try:
|
||||||
@@ -331,11 +339,14 @@ def replay_auto_login(seed, stats):
|
|||||||
seed["headers"], timeout=30)
|
seed["headers"], timeout=30)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
stats["net_error"] = stats.get("net_error", 0) + 1
|
stats["net_error"] = stats.get("net_error", 0) + 1
|
||||||
|
only_88 = False
|
||||||
log("[换会话] 第%d轮 #%d 网络错误 %r" % (round_no, tried, e))
|
log("[换会话] 第%d轮 #%d 网络错误 %r" % (round_no, tried, e))
|
||||||
time.sleep(REPLAY_GAP)
|
time.sleep(REPLAY_GAP)
|
||||||
continue
|
continue
|
||||||
form = classify(r)
|
form = classify(r)
|
||||||
stats[form] = stats.get(form, 0) + 1
|
stats[form] = stats.get(form, 0) + 1
|
||||||
|
if form != "88_business_miss":
|
||||||
|
only_88 = False
|
||||||
if form == "492_hit":
|
if form == "492_hit":
|
||||||
try:
|
try:
|
||||||
raw_list = r.raw.headers.getlist("Set-Cookie")
|
raw_list = r.raw.headers.getlist("Set-Cookie")
|
||||||
@@ -349,17 +360,24 @@ def replay_auto_login(seed, stats):
|
|||||||
log("[换会话] 第%d轮 第%d发 %s" % (round_no, tried, form))
|
log("[换会话] 第%d轮 第%d发 %s" % (round_no, tried, form))
|
||||||
if tried >= BACKOFF_AFTER and not backed:
|
if tried >= BACKOFF_AFTER and not backed:
|
||||||
backed = True
|
backed = True
|
||||||
if round_no < COOLDOWN_ROUNDS:
|
if round_no == 1:
|
||||||
log("[换会话] 连续 %d 败 → 疑似冷却期,静默 %ds 后自动重开一轮" % (tried, BACKOFF_SECS))
|
log("[换会话] 连续 %d 败 → 静默 %ds,之后只打 %d 发作死/活判别"
|
||||||
|
% (tried, BACKOFF_SECS, DEAD_PROBE))
|
||||||
time.sleep(BACKOFF_SECS)
|
time.sleep(BACKOFF_SECS)
|
||||||
break # break 出 while → 下一轮(tried 归零)
|
break # 进轮2
|
||||||
else:
|
else:
|
||||||
log("[换会话] 末轮连续 %d 败,不再静默" % tried)
|
log("[换会话] 判别轮仍全败,判素材失效")
|
||||||
else:
|
else:
|
||||||
time.sleep(REPLAY_GAP)
|
time.sleep(REPLAY_GAP)
|
||||||
# while 正常跑满 REPLAY_MAX 也进入下一轮(若还有轮次)
|
# 轮2 结束(无论跑满还是 break)→ 收工
|
||||||
if round_no < COOLDOWN_ROUNDS:
|
if round_no == 2:
|
||||||
log("[换会话] 第%d轮 %d 发未命中,重开新一轮" % (round_no, tried))
|
if only_88:
|
||||||
|
stats["verdict"] = "dead_seed"
|
||||||
|
log("[换会话] 静默 10 分钟后仍是 100%% 88B → 判定素材失效(早停,不烧时间)")
|
||||||
|
break
|
||||||
|
if only_88 and tried >= BACKOFF_AFTER:
|
||||||
|
continue # 上 break 已 sleep,进轮2
|
||||||
|
log("[换会话] 第1轮 %d 发未命中(有非 88B 形态),进判别轮" % tried)
|
||||||
return None, total_tried
|
return None, total_tried
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user