onesvm-browser-server/bench/site-matrix/lp_probe.py
chii 983259836d chore: init workspace with onesvm-dev-md + casa-commander
docs: 联网搜索服务架构方案全套(plan-final/design-arch/选型决策/整合导览/MCP文档/部署预设/联调手册)
bench: 5 方案 + 代理 + 站点矩阵本机实测工程(无密钥)
部署目标:primary mgr1 先行测试(待批准后执行)
2026-09-01 15:19:52 +08:00

137 lines
5.4 KiB
Python
Executable file

#!/usr/bin/env python3
"""Drive lightpanda CDP fetches from the host. Writes raw JSON. No secrets."""
from __future__ import annotations
import argparse
import json
import subprocess
import sys
import time
from pathlib import Path
from classify import classify_intercept, extractable, title_ok
def main() -> int:
ap = argparse.ArgumentParser()
ap.add_argument("--targets", required=True)
ap.add_argument("--group", required=True, choices=["foreign", "domestic"])
ap.add_argument("--cdp", required=True)
ap.add_argument("--out", required=True)
ap.add_argument("--cdp-fetch", required=True)
ap.add_argument("--resolved", default="")
ap.add_argument("--timeout", type=int, default=20)
ap.add_argument("--slug", default="")
args = ap.parse_args()
raw_dir = Path(args.out)
raw_dir.mkdir(parents=True, exist_ok=True)
data = json.loads(Path(args.targets).read_text(encoding="utf-8"))
sites = [s for s in data["sites"] if s["group"] == args.group]
if args.slug:
sites = [s for s in sites if s["slug"] == args.slug]
resolved = {}
if args.resolved and Path(args.resolved).exists():
resolved = json.loads(Path(args.resolved).read_text(encoding="utf-8"))
rows = []
for site in sites:
url = resolved.get(site["slug"]) or site["url"]
print(f"[lp_probe] start id={site['id']} {site['slug']} {url}", flush=True)
t0 = time.perf_counter()
try:
proc = subprocess.run(
["node", args.cdp_fetch, args.cdp, url, str(args.timeout)],
capture_output=True,
text=True,
timeout=args.timeout + 15,
)
line = (proc.stdout or "").strip().splitlines()[-1] if proc.stdout.strip() else "{}"
d = json.loads(line)
except subprocess.TimeoutExpired:
d = {"ok": False, "error": "subprocess timeout", "http_status": 0, "title": "", "text": "", "textLen": 0}
except Exception as exc: # noqa: BLE001
d = {"ok": False, "error": f"{type(exc).__name__}: {exc}", "http_status": 0, "title": "", "text": "", "textLen": 0}
elapsed = round(time.perf_counter() - t0, 3)
title = d.get("title") or ""
text = d.get("text") or ""
html_head = d.get("htmlHead") or ""
status = int(d.get("http_status") or 0)
final_url = d.get("finalUrl") or url
hops = len(d.get("redirect_chain") or [])
intercept = classify_intercept(
http_status=status,
final_url=final_url,
start_url=url,
title=title,
text=text,
html_head=html_head,
headers={},
error=d.get("error") or d.get("errorText"),
redirect_hops=hops,
)
# prefer CDP vendor when it is more specific
vendor = d.get("challenge_vendor") or intercept
if vendor in {"cloudflare", "waf", "captcha", "paywall", "redirect", "empty"} and intercept == "none":
intercept = vendor
if vendor == "cloudflare":
intercept = "cloudflare"
tok = title_ok(title, site.get("title_needles") or [], intercept)
if not tok and intercept == "none":
blob = (title + "\n" + text[:1500]).lower()
tok = any(n.lower() in blob for n in (site.get("title_needles") or []))
text_len = int(d.get("textLen") or len(text))
rec = {
"id": site["id"],
"slug": site["slug"],
"group": site["group"],
"channel": "lightpanda",
"start_url": site["url"],
"used_url": url,
"http_status": status,
"final_url": final_url,
"title": title[:240],
"title_ok": bool(tok),
"text_len": text_len,
"html_len": int(d.get("htmlLen") or 0),
"extractable": extractable(intercept, text_len, tok),
"intercept": intercept,
"elapsed_s": elapsed,
"redirect_chain": d.get("redirect_chain") or [],
"error": d.get("error") or d.get("errorText"),
"text_head": text[:1200],
"cdp_ok": bool(d.get("ok")),
"cdp_errors": d.get("cdp_errors") or [],
"loadFired": d.get("loadFired"),
"scenario": site.get("scenario"),
"known_risk": site.get("known_risk"),
}
(raw_dir / f"lp-{site['id']:02d}-{site['slug']}.json").write_text(
json.dumps(rec, ensure_ascii=False, indent=2) + "\n", encoding="utf-8"
)
excerpt = {
"title": title[:200],
"final_url": final_url,
"http_status": status,
"html_head": html_head[:2000],
"text_head": text[:1500],
"cdp": {k: d.get(k) for k in ("ok", "error", "errorText", "cdp_mode", "challenge_vendor", "header_bits")},
}
(raw_dir / f"lp-{site['id']:02d}-{site['slug']}.excerpt.json").write_text(
json.dumps(excerpt, ensure_ascii=False, indent=2) + "\n", encoding="utf-8"
)
rows.append(rec)
print(
f"[lp_probe] done id={site['id']} status={status} intercept={intercept} "
f"text_len={text_len} t={elapsed}",
flush=True,
)
outp = raw_dir / f"lp-{args.group}.jsonl"
outp.write_text("".join(json.dumps(r, ensure_ascii=False) + "\n" for r in rows), encoding="utf-8")
print(f"[lp_probe] wrote {outp}", flush=True)
return 0
if __name__ == "__main__":
sys.exit(main())