[ka2] fix connecteur gwlra: rejeter les rendus Scrapfly partiels (200 + shell sans grille de plans) qui produisaient un faux « 0 trouvé ok ». Le sync du 2026-09-06 10:53 a rapporté found=0 ok=1 (missed=1 sur Le Demetrius, médiane 1) : reproduit en live — Scrapfly renvoie parfois un rendu partiel de ~7 Ko (GTM/OneTrust seulement, statut 200, contenu non vide) qui passait le garde `status==200 and html` du retry de _building (le fix du 2026-08-30 ne couvrait que le contenu VIDE). Une page floorplans complète contient toujours le JSON-LD ApartmentComplex (rendu serveur) même sans dispo : on exige désormais fp-container OU ApartmentComplex dans le HTML avant d'accepter, sinon retry (3 essais, backoff 5/10 s) puis RuntimeError franche. Testé : run.py sync gwlra → found=1 (Le Demetrius 1 cc 1 819 $, miss_count remis à 0), pm2 restart lou-ka-sync, site :8095 → 200.
1 changed file +9 −2
modified
louka/connectors/gwlra.py
+9 −2
@@ -88,6 +88,11 @@ class GwlraConnector(BaseConnector): | ||
| 88 | 88 | # le sitemap contient des immeubles retirés (404) : vérifier le statut. |
| 89 | 89 | # Les ratés transitoires (5xx, contenu vide) sont retentés 3 fois puis |
| 90 | 90 | # remontés en erreur franche — seul un 404/410 vaut « immeuble retiré ». |
| 91 | + # Vu 2026-09-06 : Scrapfly renvoie parfois un rendu PARTIEL (200, ~7 Ko | |
| 92 | + # de shell GTM/OneTrust sans grille de plans ni JSON-LD) → faux « 0 | |
| 93 | + # trouvé ok ». Une page floorplans complète contient toujours le | |
| 94 | + # JSON-LD ApartmentComplex (rendu serveur), même sans dispo : exiger | |
| 95 | + # fp-container OU ApartmentComplex avant d'accepter le HTML. | |
| 91 | 96 | html = "" |
| 92 | 97 | for attempt in range(3): |
| 93 | 98 | result = self.scrapfly(url, render_js=True) |
@@ -95,14 +100,16 @@ class GwlraConnector(BaseConnector): | ||
| 95 | 100 | if status in (404, 410): |
| 96 | 101 | return [] |
| 97 | 102 | html = result.get("content") or "" |
| 98 | − if status == 200 and html: | |
| 103 | + complete = "fp-container" in html or "ApartmentComplex" in html | |
| 104 | + if status == 200 and html and complete: | |
| 99 | 105 | break |
| 100 | 106 | if attempt < 2: |
| 101 | 107 | time.sleep(5 * (attempt + 1)) |
| 102 | 108 | else: |
| 103 | 109 | raise RuntimeError( |
| 104 | 110 | f"page floorplans {url} en échec après 3 essais " |
| 105 | − f"(statut {status!r}, contenu {'vide' if not html else 'ok'})") | |
| 111 | + f"(statut {status!r}, contenu " | |
| 112 | + f"{'vide' if not html else 'partiel/incomplet'})") | |
| 106 | 113 | soup = BeautifulSoup(html, "html.parser") |
| 107 | 114 | |
| 108 | 115 | # JSON-LD ApartmentComplex : nom, adresse, animaux, détail des plans |
| 109 | 116 | |