#!/usr/bin/env python3 """ Rank the Criterion films you're missing by their Letterboxd rating. Reads the JSON written by criterion_crossref.py, fetches each missing film's Letterboxd page for its average rating, and writes a plain-text list sorted best-first (unrated films at the bottom). Usage: python fetch_ratings.py [criterion_crossref.json] [criterion_missing.txt] Requires only the Python standard library. """ import json, urllib.request, re, time, sys IN_PATH = sys.argv[1] if len(sys.argv) > 1 else "criterion_crossref.json" OUT_PATH = sys.argv[2] if len(sys.argv) > 2 else "criterion_missing.txt" USER_AGENT = "Mozilla/5.0 (criterion-crossref/1.0)" with open(IN_PATH) as f: data = json.load(f) missing = data["missing"] + [m["criterion"] for m in data["fuzzy"]] print(f"Fetching Letterboxd ratings for {len(missing)} films...", file=sys.stderr) results = [] for i, film in enumerate(missing, 1): slug = film["slug"] url = f"https://letterboxd.com/film/{slug}/" rating = None year = film.get("year") try: req = urllib.request.Request(url, headers={"User-Agent": USER_AGENT}) with urllib.request.urlopen(req, timeout=30) as r: html = r.read().decode("utf-8", errors="replace") m = re.search(r'"ratingValue"\s*:\s*(\d+\.?\d*)', html) if m: rating = float(m.group(1)) if not year: ym = re.search(r'