SPB Git forge

spb/job-ka

Public
229commits 1branches 0releases
38.1 MBsize
maindefault branch
1 h agolast push
HTML 82.1% Python 14.6% TypeScript 1.9% CSS 1% JavaScript 0.5%

[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

Simon-Pierre Boucher committed 20 days ago (Sep 4, 2026) parent 7217386

1 changed file +32 −2

modified jobka/connectors/njoyn.py +32 −2
@@ -5,7 +5,7 @@
5 5 # Fichier : jobka/connectors/njoyn.py
6 6 # Rôle : Classe de plateforme Njoyn (CGI) — très répandu au secteur public
7 7 # québécois (santé, villes, sociétés d'État). HTML serveur + jeton.
8 −# Créé : 2026-08-18 Modifié : 2026-08-26
8 +# Créé : 2026-08-18 Modifié : 2026-09-04
9 9 # =============================================================================
10 10 """Plateforme Njoyn (CGI).
11 11
@@ -20,6 +20,18 @@ une ligne de tableau (habillage classique) pointant vers
20 20 tenants, mettre ``USE_SCRAPFLY = True`` (contournement ASP). Les babillards
21 21 servis sur un domaine personnalisé (ex. emplois.santemontreal.qc.ca) se
22 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.
23 35 """
24 36 from __future__ import annotations
25 37
@@ -255,6 +267,23 @@ class NjoynConnector(BaseConnector):
255 267 it.get("fields", {}).get("villes et arrondissements") or "")
256 268 return bool(place) and is_quebec_location(place.replace("-", " "))
257 269
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 +
258 287 def _fetch_listing(self) -> tuple[str, list[dict]]:
259 288 """Page liste + items parsés, avec garde-fou : une réponse vide ou
260 289 anti-bot (Scrapfly en échec renvoie "" — voir base.get_scrapfly) ne
@@ -271,7 +300,8 @@ class NjoynConnector(BaseConnector):
271 300 time.sleep(10)
272 301 raise RuntimeError(
273 302 f"njoyn {self.source_id}: page liste illisible "
274 − f"(vide ou anti-bot, {len(page)} octets) — sync avorté")
303 + f"(vide ou anti-bot, {len(page)} octets) — sync avorté"
304 + + self._radware_hint())
275 305
276 306 def fetch(self) -> list[JobPosting]:
277 307 page, items = self._fetch_listing()
278 308