SPB Git

spb/immo-ka Public

Immo-Ka — agrégateur des propriétés à vendre au Québec (73 connecteurs, ~40 000 annonces, React+FastAPI)

Python 64% TypeScript 21.1% CSS 14.3% HTML 0.6%
2.2 KB · 59 lines python
Raw Blame History
1# -----------------------------------------------------------------------------2# Immo-Ka — Agrégateur de maisons à vendre (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# ingest.py : pipeline d'ingestion — exécute les connecteurs et synchronise5#             la base (ajouts / mises à jour / retraits) = contenu toujours à jour6# -----------------------------------------------------------------------------7from __future__ import annotations89import sys10import time11import traceback1213from . import db14from .connectors import CONNECTORS151617def run(sources: list[str] | None = None) -> list[dict]:18    """Exécute l'ingestion pour toutes les sources (ou celles demandées)."""19    con = db.connect()20    results = []21    targets = sources or list(CONNECTORS.keys())22    for sid in targets:23        cls = CONNECTORS.get(sid)24        if cls is None:25            print(f"[immo-ka] connecteur inconnu : {sid}", file=sys.stderr)26            continue27        t0 = time.time()28        print(f"[immo-ka] sync {sid} ...")29        try:30            listings = cls().fetch()31            finalized, dropped = [], 032            for lst in listings:33                try:34                    finalized.append(lst.finalize())35                except Exception:  # une annonce malformée ne bloque pas la source36                    dropped += 137            stats = db.sync_source(con, sid, finalized)38            stats["seconds"] = round(time.time() - t0, 1)39            if dropped:40                stats["dropped"] = dropped41            if stats.get("alert"):42                print(f"[immo-ka]   ⚠ ALERTE {sid} : {stats['alert']}")43            print(f"[immo-ka]   {stats}")44            results.append(stats)45        except Exception as exc:  # robustesse : une source ne bloque pas les autres46            db.log_failure(con, sid, f"{exc}")47            traceback.print_exc()48            results.append({"source": sid, "error": str(exc)})49    con.close()50    return results515253def watch(interval_seconds: int = 3600) -> None:54    """Boucle de synchronisation périodique (équivalent webhook, via PM2/cron)."""55    while True:56        run()57        print(f"[immo-ka] prochaine synchronisation dans {interval_seconds // 60} min")58        time.sleep(interval_seconds)59