[ka2] fix connecteur barnes_quebec: la clé Algolia search-only publiée dans le HTML a tourné (403 le 2026-08-29 14:53) — le connecteur relit maintenant la clé à chaque sync depuis /louer/ (regex algolia_search_api_key), nouvelle clé en secours. Testé: 74 annonces — baisse réelle d'inventaire (31 fiches retirées du site, 404 vérifiés), pas un bug
1 changed file +17 −2
modified
louka/connectors/barnes_quebec.py
+17 −2
@@ -23,7 +23,11 @@ from .base import BaseConnector | ||
| 23 | 23 | from . import _detailutil as du |
| 24 | 24 | |
| 25 | 25 | APP_ID = "HCW55VIQNM" |
| 26 | −API_KEY = "f4a20779fb6ded84a9c96a9b5976328b" | |
| 26 | +# clé « search-only » publiée dans le HTML (var AlgoliaPHPVars) — elle TOURNE | |
| 27 | +# (rotation constatée 2026-08-29 : 403 sur l'ancienne clé). On la relit à | |
| 28 | +# chaque sync depuis /louer/ ; cette constante n'est qu'un secours. | |
| 29 | +API_KEY_FALLBACK = "6319a160319545bfd5dafbb01ffa4ca6" | |
| 30 | +_API_KEY_RE = re.compile(r'"algolia_search_api_key"\s*:\s*"([0-9a-f]{16,64})"') | |
| 27 | 31 | INDEX = "quebec_all" |
| 28 | 32 | QUERY_URL = f"https://{APP_ID}-dsn.algolia.net/1/indexes/{INDEX}/query" |
| 29 | 33 | SITE = "https://barnes-quebec.com" |
@@ -57,6 +61,7 @@ class BarnesQuebecConnector(BaseConnector): | ||
| 57 | 61 | request_delay = 0.25 |
| 58 | 62 | |
| 59 | 63 | def fetch(self) -> list[Listing]: |
| 64 | + self._api_key = self._resolve_api_key() | |
| 60 | 65 | # une location apparaît en plusieurs langues (FR/EN) avec des objectID |
| 61 | 66 | # distincts mais le même titre. Clé stable = titre normalisé ; on garde |
| 62 | 67 | # la meilleure fiche (loyer connu + FR). |
@@ -85,10 +90,20 @@ class BarnesQuebecConnector(BaseConnector): | ||
| 85 | 90 | du.enrich(self, listings, DETAIL_LIMIT, parse_barnes_detail, key="v1") |
| 86 | 91 | return listings |
| 87 | 92 | |
| 93 | + def _resolve_api_key(self) -> str: | |
| 94 | + """Relit la clé search dans le HTML de /louer/ (elle tourne).""" | |
| 95 | + try: | |
| 96 | + m = _API_KEY_RE.search(self.get(SITE + "/louer/").text) | |
| 97 | + if m: | |
| 98 | + return m.group(1) | |
| 99 | + except Exception: # noqa: BLE001 — page indisponible : on tente le secours | |
| 100 | + pass | |
| 101 | + return API_KEY_FALLBACK | |
| 102 | + | |
| 88 | 103 | def _query(self, page: int) -> dict: |
| 89 | 104 | resp = self.post( |
| 90 | 105 | QUERY_URL, |
| 91 | − headers={"X-Algolia-API-Key": API_KEY, | |
| 106 | + headers={"X-Algolia-API-Key": self._api_key, | |
| 92 | 107 | "X-Algolia-Application-Id": APP_ID, |
| 93 | 108 | "Content-Type": "application/json"}, |
| 94 | 109 | json={"params": f"hitsPerPage={HITS_PER_PAGE}&page={page}&{FACET_RENTAL}"}, |
| 95 | 110 | |