Resto·Ka — tous les restaurants du Québec, menus complets et prix réels (famille ·Ka)
Python 69.3%
TypeScript 16.7%
CSS 7.9%
JavaScript 4.7%
HTML 1.4%
1# ==============================================================================2# Author: Simon-Pierre Boucher <contact@spboucher.ai>3# File: scripts/backfill_images.py4# Desc: Rattrapage ponctuel — photos des restos site-resto captés AVANT5# l'extraction d'images du connecteur (2026-08-23) : re-visite la page6# d'accueil du site de chaque fiche site-resto sans images (et de sa7# fiche OSM jumelle) et pose jusqu'à 6 photos via8# SiteRestoConnector._extract_images. Idempotent : ne touche que les9# fiches où images est vide.10# Usage : .venv/bin/python scripts/backfill_images.py [max_sites]11# ==============================================================================12from __future__ import annotations1314import json15import sys16from concurrent.futures import ThreadPoolExecutor1718sys.path.insert(0, ".")19from restoka import db # noqa: E40220from restoka.connectors.siteresto import SiteRestoConnector, _domain # noqa: E4022122MAX = int(sys.argv[1]) if len(sys.argv) > 1 else 40023WORKERS = 62425con = db.connect()26rows = con.execute(27 """SELECT uid, external_id, name, website, url FROM restaurants28 WHERE source='site-resto' AND active=129 AND (images IS NULL OR images='' OR images='[]')30 LIMIT ?""", (MAX,)).fetchall()31print(f"{len(rows)} fiches site-resto sans images à rattraper")323334def _one(row):35 worker = SiteRestoConnector()36 site = (row["website"] or "").strip()37 if not site:38 # la fiche site-resto garde le site dans la fiche OSM jumelle ; url =39 # page du menu, son domaine suffit pour retrouver l'accueil40 site = "https://" + _domain(row["url"] or "")41 if not site.startswith("http"):42 site = "https://" + site43 try:44 html = worker._get_html(site)45 imgs = worker._extract_images(html, site)46 return row["uid"], row["external_id"], imgs47 except Exception as exc:48 print(f" {row['name']}: erreur {exc}", file=sys.stderr)49 return row["uid"], row["external_id"], []505152done = with_img = 053with ThreadPoolExecutor(max_workers=WORKERS) as pool:54 for uid, ext_id, imgs in pool.map(_one, rows):55 done += 156 if not imgs:57 continue58 blob = json.dumps(imgs)59 # fiche site-resto + fiche OSM jumelle (même external_id), si vides60 for target in (uid, f"osm:{ext_id.split(':', 1)[-1]}", f"osm:{ext_id}"):61 con.execute(62 "UPDATE restaurants SET images=? WHERE uid=? AND"63 " (images IS NULL OR images='' OR images='[]')",64 (blob, target))65 con.commit()66 with_img += 167 if with_img % 25 == 0:68 print(f" {with_img}/{done} fiches avec photos…")6970print(f"terminé : {with_img}/{done} fiches enrichies de photos")71