#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""修 crawl_hsq_tztg.py 两处：
  ① stealth 调了 async 方法却未 await → 隐身从未生效（RuntimeWarning 实证）
  ② 无时限保护 → 5 页 × 19 条 × ~6.5s ≈ 650s，必然冲破 600s 被杀、当轮白跑
"""
import ast
import io
import os
import shutil

D = "/root/gov_crawler"
ARCH = os.path.join(D, "Archive")
fn = "crawl_hsq_tztg.py"
p = os.path.join(D, fn)
src = io.open(p, encoding="utf-8").read()
n_edit = 0

# ── ① stealth：async → sync ────────────────────────────────────────────
old1 = "        Stealth().apply_stealth_async(ctx)"
new1 = ("        # 2026-09-22 修复：原来调的是 async 版且从未 await（RuntimeWarning 实证\n"
        "        #   \"coroutine 'Stealth.apply_stealth_async' was never awaited\"）→ 隐身从未生效。\n"
        "        #   同步 API 必须用 apply_stealth_sync。\n"
        "        Stealth().apply_stealth_sync(ctx)")
assert src.count(old1) == 1, "① 锚点命中 %d" % src.count(old1)
src = src.replace(old1, new1)
n_edit += 1

# ── ② 新增 --deadline 解析函数 ─────────────────────────────────────────
old2 = "def main():"
new2 = '''def parse_deadline_arg(default=480):
    """2026-09-22 新增：本轮总时限（秒）。保证在调度器 timeout 前收尾并落库，
    避免被硬杀导致当轮白跑。剩余条目下轮增量继续。"""
    for a in sys.argv[1:]:
        if a.startswith("--deadline="):
            try:
                return int(a.split("=", 1)[1])
            except Exception:
                pass
    return default


def main():'''
assert src.count(old2) == 1, "② 锚点命中 %d" % src.count(old2)
src = src.replace(old2, new2)
n_edit += 1

# ── ③ 计时起点 ────────────────────────────────────────────────────────
old3 = "        page = ctx.new_page()"
new3 = ("        page = ctx.new_page()\n"
        "        _t0 = time.monotonic()   # 2026-09-22: 时限计时起点")
assert src.count(old3) == 1, "③ 锚点命中 %d" % src.count(old3)
src = src.replace(old3, new3)
n_edit += 1

# ── ④ 列表阶段：用掉一半预算就停 ──────────────────────────────────────
old4 = '''            print(f"[列表] 共 {len(items)} 条", flush=True)'''
new4 = '''                if pn > 1 and (time.monotonic() - _t0) > deadline_s * 0.5:
                    print(f"    [时限] 列表阶段已用掉一半预算，停止翻页", flush=True)
                    break

            print(f"[列表] 共 {len(items)} 条", flush=True)'''
assert src.count(old4) == 1, "④ 锚点命中 %d" % src.count(old4)
src = src.replace(old4, new4)
n_edit += 1

# ── ⑤ 详情阶段：超时限就收尾（已抓的照常落库）────────────────────────
old5 = '''            for idx, it in enumerate(items):
                time.sleep(random.uniform(3, 6))'''
new5 = '''            for idx, it in enumerate(items):
                if (time.monotonic() - _t0) > deadline_s:
                    print(f"  [时限] 已达 {deadline_s}s，提前收尾："
                          f"本轮处理 {idx}/{len(items)} 条，剩余下轮继续", flush=True)
                    break
                time.sleep(random.uniform(3, 6))'''
assert src.count(old5) == 1, "⑤ 锚点命中 %d" % src.count(old5)
src = src.replace(old5, new5)
n_edit += 1

# ── ⑥ 读取时限值 ──────────────────────────────────────────────────────
old6 = "    max_pages = parse_pages_arg()"
new6 = ("    max_pages = parse_pages_arg()\n"
        "    deadline_s = parse_deadline_arg()")
assert src.count(old6) == 1, "⑥ 锚点命中 %d" % src.count(old6)
src = src.replace(old6, new6)
n_edit += 1

ast.parse(src)
os.makedirs(ARCH, exist_ok=True)
bak = os.path.join(ARCH, fn + ".bak_20260922_deadline")
if not os.path.exists(bak):
    shutil.copy2(p, bak)
io.open(p, "w", encoding="utf-8").write(src)
print("   ✅ %s 完成 %d 处修改（备份 Archive/%s.bak_20260922_deadline）" % (fn, n_edit, fn))
