SPB Git forge

spb/job-ka

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

[ka6] fix connecteur stl_laval: garde-fou njoyn — une page liste vide/anti-bot (Scrapfly en échec renvoie "") ne passe plus pour un babillard à 0 offre; retente une fois puis lève une erreur (njoyn.py)

Simon-Pierre Boucher committed 29 days ago (Aug 26, 2026) parent 1953afc

1 changed file +21 −4

modified jobka/connectors/njoyn.py +21 −4
@@ -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-25
8 +# Créé : 2026-08-18 Modifié : 2026-08-26
9 9 # =============================================================================
10 10 """Plateforme Njoyn (CGI).
11 11
@@ -27,6 +27,7 @@ import hashlib
27 27 import html as _html
28 28 import os
29 29 import re
30 +import time
30 31
31 32 from ..schema import JobPosting, clean_html
32 33 from .base import BaseConnector
@@ -254,10 +255,26 @@ class NjoynConnector(BaseConnector):
254 255 it.get("fields", {}).get("villes et arrondissements") or "")
255 256 return bool(place) and is_quebec_location(place.replace("-", " "))
256 257
258 + def _fetch_listing(self) -> tuple[str, list[dict]]:
259 + """Page liste + items parsés, avec garde-fou : une réponse vide ou
260 + anti-bot (Scrapfly en échec renvoie "" — voir base.get_scrapfly) ne
261 + doit JAMAIS passer pour un babillard vide. Toute page Njoyn légitime,
262 + même sans offre, contient le formulaire xweb.asp — sinon on retente
263 + une fois puis on lève une erreur (sync en échec, pas « 0 trouvé »)."""
264 + for attempt in range(2):
265 + page = self._html(self._url("joblisting"))
266 + items = (self._parse_articles(page) or self._parse_table(page)
267 + or self._parse_rows(page))
268 + if items or re.search(r"xweb\.asp", page, re.I):
269 + return page, items
270 + if attempt == 0:
271 + time.sleep(10)
272 + raise RuntimeError(
273 + f"njoyn {self.source_id}: page liste illisible "
274 + f"(vide ou anti-bot, {len(page)} octets) — sync avorté")
275 +
257 276 def fetch(self) -> list[JobPosting]:
258 − page = self._html(self._url("joblisting"))
259 − items = (self._parse_articles(page) or self._parse_table(page)
260 − or self._parse_rows(page))
277 + page, items = self._fetch_listing()
261 278 items = self._paginate(page, items)
262 279 items = [it for it in items if self._keep(it)]
263 280 out: list[JobPosting] = []
264 281