HTML 82%
Python 14.7%
TypeScript 1.9%
CSS 1%
JavaScript 0.5%
1# =============================================================================2# Job·Ka — Groupe KA3# Auteur : Simon-Pierre Boucher4# Contact : contact@spboucher.ai5# Fichier : scripts/backfill_enrich.py6# Rôle : Backfill de l'enrichissement Phase 3 (exigences structurées,7# séniorité, avantages) sur les offres déjà en base — sans toucher8# content_hash (la prochaine synchro réalignera naturellement)9# Créé : 2026-08-25 Modifié : 2026-08-2510# =============================================================================11"""Réapplique les nouveaux extracteurs (extract_requirements, parse_seniority,12extract_benefits élargi) aux offres stockées, à partir du titre et de la13description déjà en base. Idempotent : ne remplit que les champs manquants,14n'écrase jamais une valeur fournie par un ATS.1516Usage : python -m scripts.backfill_enrich [--all] (défaut : offres actives)17"""18from __future__ import annotations1920import json21import sys22import time23from pathlib import Path2425sys.path.insert(0, str(Path(__file__).resolve().parent.parent))2627from jobka import db # noqa: E40228from jobka.normalize import ( # noqa: E40229 extract_benefits, extract_requirements, parse_seniority)303132def run(only_active: bool = True) -> dict:33 con = db.connect() # applique aussi la migration (colonne seniority)34 where = "WHERE active=1" if only_active else ""35 rows = con.execute(36 f"SELECT uid, title, description, employment_type, requirements,"37 f" benefits, seniority FROM jobs {where}").fetchall()3839 stats = {"scanned": len(rows), "requirements": 0, "seniority": 0,40 "benefits": 0, "updated": 0}41 t0 = time.time()42 for r in rows:43 try:44 reqs = json.loads(r["requirements"] or "{}")45 except ValueError:46 reqs = {}47 try:48 bens = json.loads(r["benefits"] or "[]")49 except ValueError:50 bens = []5152 changed = False53 extracted = extract_requirements(r["title"] or "", r["description"] or "")54 added_req = {k: v for k, v in extracted.items() if k not in reqs}55 if added_req:56 reqs.update(added_req)57 stats["requirements"] += 158 changed = True5960 seniority = r["seniority"]61 if not seniority:62 seniority = parse_seniority(r["title"] or "", reqs,63 r["employment_type"])64 if seniority:65 stats["seniority"] += 166 changed = True6768 if not bens and r["description"]:69 bens = extract_benefits(r["description"])70 if bens:71 stats["benefits"] += 172 changed = True7374 if changed:75 con.execute(76 "UPDATE jobs SET requirements=?, seniority=?, benefits=?"77 " WHERE uid=?",78 (json.dumps(reqs, ensure_ascii=False), seniority,79 json.dumps(bens, ensure_ascii=False), r["uid"]))80 stats["updated"] += 18182 con.commit()83 con.close()84 stats["seconds"] = round(time.time() - t0, 1)85 return stats868788if __name__ == "__main__":89 out = run(only_active="--all" not in sys.argv)90 print(f"[backfill-enrich] {out}")91