#!/usr/bin/env python3 """Crawl the Library of Chadnet into a structured JSON tree for faithful replica.""" import json, os, re, sys, time from html.parser import HTMLParser import requests BASE = "https://wiki.chadnet.org" HDRS = {"User-Agent": "Mozilla/5.0 (compatible; library-mirror/1.0)"} S = requests.Session(); S.headers.update(HDRS) OUT = "/home/hermes/chad-library" DATA = os.path.join(OUT, "site_data.json") def classify_icon(src): s = src.lower() if "folder" in s: return "folder" if "globe" in s: return "globe" if "document" in s: return "document" if "painting" in s: return "painting" if "youtube" in s: return "youtube" if "article" in s: return "article" if "chad-square" in s: return "chadsquare" return "link" class PageParser(HTMLParser): """Capture title, parent (from nav), and category lists as sections of items.""" def __init__(self): super().__init__(convert_charrefs=True) self.title = None self.parent = None self.sections = [] # list of [h2key, [items]] self._intitle = False # element state self._in_a = 0 self._h2 = None # accumulating h2 text or None self._active = None # current items list self._ul_depth = 0 self._li = None # current item dict being built or None # breadcrumbs: capture parent once from nav
', html) if m: parent = m.group(1).strip().lstrip("/") page = {"slug": slug, "title": p.title or slug, "parent": parent, "sections": p.sections, "url": url} pages[slug] = page n = sum(len(s[1]) for s in p.sections) print(f"crawled {slug} ({n} items, parent={parent})", flush=True) for _, items in p.sections: for it in items: if it["type"] == "folder" and it["href"] and not it["href"].startswith("http"): child = it["href"].rstrip("/").split("/")[-1].split("?")[0] if child: to_visit.append((child, slug)) time.sleep(0.3) with open(DATA, "w") as f: json.dump({"pages": pages}, f, ensure_ascii=False, indent=1) print(f"\nTotal pages: {len(pages)}") return pages if __name__ == "__main__": main()