Revert "[ka6] connecteur cusm_ir: diagnostic du mur Radware hCaptcha host-wide *.njoyn.com (2026-09-02) — non contournable (Scrapfly/BrightData/Oxylabs/Chromium réel tous bloqués), erreur explicite via _radware_hint, offres en base préservées"
This reverts commit c8f84a32fd7bf5528e737523b81b0410486e581e.
1 changed file +2 −32
modified
jobka/connectors/njoyn.py
+2 −32
@@ -5,7 +5,7 @@ | |||||
| 5 | # Fichier : jobka/connectors/njoyn.py | 5 | # Fichier : jobka/connectors/njoyn.py | ||
| 6 | # Rôle : Classe de plateforme Njoyn (CGI) — très répandu au secteur public | 6 | # Rôle : Classe de plateforme Njoyn (CGI) — très répandu au secteur public | ||
| 7 | # québécois (santé, villes, sociétés d'État). HTML serveur + jeton. | 7 | # québécois (santé, villes, sociétés d'État). HTML serveur + jeton. | ||
| 8 | −# Créé : 2026-08-18 Modifié : 2026-09-04 | 8 | +# Créé : 2026-08-18 Modifié : 2026-08-26 | ||
| 9 | # ============================================================================= | 9 | # ============================================================================= | ||
| 10 | """Plateforme Njoyn (CGI). | 10 | """Plateforme Njoyn (CGI). | ||
| 11 | 11 | ||||
@@ -20,18 +20,6 @@ une ligne de tableau (habillage classique) pointant vers | |||||
| 20 | tenants, mettre ``USE_SCRAPFLY = True`` (contournement ASP). Les babillards | 20 | tenants, mettre ``USE_SCRAPFLY = True`` (contournement ASP). Les babillards | ||
| 21 | servis sur un domaine personnalisé (ex. emplois.santemontreal.qc.ca) se | 21 | servis sur un domaine personnalisé (ex. emplois.santemontreal.qc.ca) se | ||
| 22 | consultent directement. | 22 | consultent directement. | ||
| 23 | − | ||||
| 24 | −⚠⚠ Incident 2026-09-02 : CGI a durci Radware sur TOUT *.njoyn.com — mur | ||||
| 25 | −hCaptcha INTERACTIF (validate.perfdrive.com) servi à chaque nouveau | ||||
| 26 | −visiteur, humains compris. Toute la pile d'escalade échoue : Scrapfly | ||||
| 27 | −(ASP, render_js, pool résidentiel → page captcha ou 422), Bright Data | ||||
| 28 | −(reject_block « captcha or protection page found »), Oxylabs (Realtime | ||||
| 29 | −render + proxies résidentiels -cc-CA), et même un vrai Chromium headed | ||||
| 30 | −(le clic sur la case hCaptcha ouvre un puzzle imagé). Rien à contourner | ||||
| 31 | −côté code : ``_fetch_listing`` identifie le mur dans son message d'erreur | ||||
| 32 | −et le sync reste en échec (les offres en base ne sont pas retirées). | ||||
| 33 | −Surveiller la levée du mur — les tenants sur domaine personnalisé | ||||
| 34 | −(sante_montreal, stl_laval, villes) ne sont PAS touchés. | ||||
| 35 | """ | 23 | """ | ||
| 36 | from __future__ import annotations | 24 | from __future__ import annotations | ||
| 37 | 25 | ||||
@@ -267,23 +255,6 @@ class NjoynConnector(BaseConnector): | |||||
| 267 | it.get("fields", {}).get("villes et arrondissements") or "") | 255 | it.get("fields", {}).get("villes et arrondissements") or "") | ||
| 268 | return bool(place) and is_quebec_location(place.replace("-", " ")) | 256 | return bool(place) and is_quebec_location(place.replace("-", " ")) | ||
| 269 | 257 | ||||
| 270 | − def _radware_hint(self) -> str: | ||||
| 271 | − """Diagnostic post-échec : sonde la page liste en direct (une seule | ||||
| 272 | − requête, sans Scrapfly) pour vérifier si le domaine sert le mur | ||||
| 273 | − hCaptcha Radware (redirection validate.perfdrive.com). Voir le | ||||
| 274 | − docstring du module — incident host-wide *.njoyn.com du 2026-09-02, | ||||
| 275 | − aucune voie de contournement dans la pile d'escalade.""" | ||||
| 276 | − try: | ||||
| 277 | − r = self.get(self._url("joblisting")) | ||||
| 278 | − if "perfdrive" in (r.url or "") or "Radware" in r.text[:4000]: | ||||
| 279 | − return (" — cause identifiée : mur anti-bot Radware " | ||||
| 280 | − "(hCaptcha interactif, validate.perfdrive.com) sur " | ||||
| 281 | − "tout *.njoyn.com; pile d'escalade complète en échec " | ||||
| 282 | − "(vu 2026-09-02→), attendre la levée du mur") | ||||
| 283 | − except Exception: | ||||
| 284 | − pass | ||||
| 285 | − return "" | ||||
| 286 | − | ||||
| 287 | def _fetch_listing(self) -> tuple[str, list[dict]]: | 258 | def _fetch_listing(self) -> tuple[str, list[dict]]: | ||
| 288 | """Page liste + items parsés, avec garde-fou : une réponse vide ou | 259 | """Page liste + items parsés, avec garde-fou : une réponse vide ou | ||
| 289 | anti-bot (Scrapfly en échec renvoie "" — voir base.get_scrapfly) ne | 260 | anti-bot (Scrapfly en échec renvoie "" — voir base.get_scrapfly) ne | ||
@@ -300,8 +271,7 @@ class NjoynConnector(BaseConnector): | |||||
| 300 | time.sleep(10) | 271 | time.sleep(10) | ||
| 301 | raise RuntimeError( | 272 | raise RuntimeError( | ||
| 302 | f"njoyn {self.source_id}: page liste illisible " | 273 | f"njoyn {self.source_id}: page liste illisible " | ||
| 303 | − f"(vide ou anti-bot, {len(page)} octets) — sync avorté" | 274 | + f"(vide ou anti-bot, {len(page)} octets) — sync avorté") | ||
| 304 | − + self._radware_hint()) | ||||
| 305 | 275 | ||||
| 306 | def fetch(self) -> list[JobPosting]: | 276 | def fetch(self) -> list[JobPosting]: | ||
| 307 | page, items = self._fetch_listing() | 277 | page, items = self._fetch_listing() | ||
| 308 | 278 | ||||