# ============================================================================= # Job·Ka — Groupe KA # Auteur : Simon-Pierre Boucher # Contact : contact@spboucher.ai # Fichier : scripts/backfill_enrich.py # Rôle : Backfill de l'enrichissement Phase 3 (exigences structurées, # séniorité, avantages) sur les offres déjà en base — sans toucher # content_hash (la prochaine synchro réalignera naturellement) # Créé : 2026-08-25 Modifié : 2026-08-25 # ============================================================================= """Réapplique les nouveaux extracteurs (extract_requirements, parse_seniority, extract_benefits élargi) aux offres stockées, à partir du titre et de la description déjà en base. Idempotent : ne remplit que les champs manquants, n'écrase jamais une valeur fournie par un ATS. Usage : python -m scripts.backfill_enrich [--all] (défaut : offres actives) """ from __future__ import annotations import json import sys import time from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) from jobka import db # noqa: E402 from jobka.normalize import ( # noqa: E402 extract_benefits, extract_requirements, parse_seniority) def run(only_active: bool = True) -> dict: con = db.connect() # applique aussi la migration (colonne seniority) where = "WHERE active=1" if only_active else "" rows = con.execute( f"SELECT uid, title, description, employment_type, requirements," f" benefits, seniority FROM jobs {where}").fetchall() stats = {"scanned": len(rows), "requirements": 0, "seniority": 0, "benefits": 0, "updated": 0} t0 = time.time() for r in rows: try: reqs = json.loads(r["requirements"] or "{}") except ValueError: reqs = {} try: bens = json.loads(r["benefits"] or "[]") except ValueError: bens = [] changed = False extracted = extract_requirements(r["title"] or "", r["description"] or "") added_req = {k: v for k, v in extracted.items() if k not in reqs} if added_req: reqs.update(added_req) stats["requirements"] += 1 changed = True seniority = r["seniority"] if not seniority: seniority = parse_seniority(r["title"] or "", reqs, r["employment_type"]) if seniority: stats["seniority"] += 1 changed = True if not bens and r["description"]: bens = extract_benefits(r["description"]) if bens: stats["benefits"] += 1 changed = True if changed: con.execute( "UPDATE jobs SET requirements=?, seniority=?, benefits=?" " WHERE uid=?", (json.dumps(reqs, ensure_ascii=False), seniority, json.dumps(bens, ensure_ascii=False), r["uid"])) stats["updated"] += 1 con.commit() con.close() stats["seconds"] = round(time.time() - t0, 1) return stats if __name__ == "__main__": out = run(only_active="--all" not in sys.argv) print(f"[backfill-enrich] {out}")