89 lines
3.1 KiB
Python
89 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Adversarial probe: do the 9 unverified corpus IDs actually exist on arXiv?
|
|
|
|
Reads the IDs straight out of the corpus JSONL (no retyping), then fetches each
|
|
paper's abs page and classifies it:
|
|
EXISTS -> HTTP 200 and the page contains the arXiv abstract anchor
|
|
NOT_FOUND -> HTTP 404 / "not recognized"
|
|
OTHER -> anything else (recorded verbatim)
|
|
|
|
This is the real test of the digest's integrity: a fabricated ID cannot
|
|
produce a live abs page.
|
|
"""
|
|
import json
|
|
import re
|
|
import sys
|
|
import time
|
|
import urllib.error
|
|
import urllib.request
|
|
|
|
CORPUS = "/root/.hermes/wizard-outputs/sphinx/arxiv_recent_harvest/merged_all.jsonl"
|
|
OUT = "/root/.hermes/wizard-outputs/sphinx/arxiv-digest-verified-2026-10-25/ABS_PROBE.json"
|
|
UA = "sphinx-archive-verifier/1.0 (evidence-lane)"
|
|
|
|
|
|
def main():
|
|
missing = json.load(open(
|
|
"/root/.hermes/wizard-outputs/sphinx/arxiv-digest-verified-2026-10-25/VERIFICATION.json"
|
|
))["unverified"]
|
|
ids = [r["id"] for r in missing]
|
|
|
|
corpus_titles = {}
|
|
for line in open(CORPUS, encoding="utf-8"):
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
rec = json.loads(line)
|
|
m = re.search(r"/abs/([0-9]{4}\.[0-9]{4,5})", rec.get("id", ""))
|
|
if m:
|
|
corpus_titles[m.group(1)] = rec.get("title", "")
|
|
|
|
rows = []
|
|
for bid in ids:
|
|
url = f"https://arxiv.org/abs/{bid}"
|
|
status, note, page_title = None, "", ""
|
|
try:
|
|
req = urllib.request.Request(url, headers={"User-Agent": UA})
|
|
with urllib.request.urlopen(req, timeout=45) as resp:
|
|
status = resp.status
|
|
body = resp.read().decode("utf-8", "replace")
|
|
m = re.search(r"<title>(.*?)</title>", body, re.S)
|
|
page_title = " ".join(m.group(1).split()) if m else ""
|
|
if "not recognized" in body.lower() or "no article found" in body.lower():
|
|
note = "page says not found"
|
|
else:
|
|
note = "live abstract page"
|
|
except urllib.error.HTTPError as exc:
|
|
status = exc.code
|
|
note = f"HTTPError {exc.code}"
|
|
except Exception as exc: # noqa: BLE001
|
|
note = f"error: {exc}"
|
|
rows.append({
|
|
"id": bid,
|
|
"url": url,
|
|
"corpus_title": corpus_titles.get(bid, ""),
|
|
"http_status": status,
|
|
"page_title": page_title,
|
|
"note": note,
|
|
"exists": status == 200 and "not recognized" not in note,
|
|
})
|
|
print(f"{bid} status={status} {note} | {page_title[:70]}", flush=True)
|
|
time.sleep(1.0)
|
|
|
|
exists = sum(1 for r in rows if r["exists"])
|
|
out = {
|
|
"probe": "per-ID abs-page existence check",
|
|
"run_utc": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
|
|
"tested": len(rows),
|
|
"exists": exists,
|
|
"not_found": len(rows) - exists,
|
|
"rows": rows,
|
|
}
|
|
json.dump(out, open(OUT, "w", encoding="utf-8"), indent=1, sort_keys=True)
|
|
print(f"\nexists={exists} not_found={len(rows) - exists}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|