SPB Git

spb/job-ka

Public

[ka6] fix connecteur cssdd: garde-fou sitemap DigitalRecruiters — une réponse vide/anti-bot (challenge en 200) ne passe plus pour un babillard à 0 offre; retente une fois puis lève une erreur (digitalrecruiters.py, même pattern que njoyn 33dba44)

Simon-Pierre Boucher committed (Aug 26, 2026) parent 33dba44 Browse files

1 changed file +20 −2

Unified Split
modified jobka/connectors/digitalrecruiters.py +20 −2
@@ -5,7 +5,7 @@
5 # Fichier : jobka/connectors/digitalrecruiters.py 5 # Fichier : jobka/connectors/digitalrecruiters.py
6 # Rôle : Classe de plateforme Cegid Digital Recruiters (sites carrières) — 6 # Rôle : Classe de plateforme Cegid Digital Recruiters (sites carrières) —
7 # sitemap + JSON-LD des pages annonce (ex. Santé Québec) 7 # sitemap + JSON-LD des pages annonce (ex. Santé Québec)
8−# Créé : 2026-08-18 Modifié : 2026-08-18 8+# Créé : 2026-08-18 Modifié : 2026-08-26
9 # ============================================================================= 9 # =============================================================================
10 """Plateforme Cegid Digital Recruiters. 10 """Plateforme Cegid Digital Recruiters.
11 11
@@ -19,6 +19,7 @@ from __future__ import annotations
19 19
20 import os 20 import os
21 import re 21 import re
22+import time
22 23
23 from ..schema import JobPosting, is_quebec_location 24 from ..schema import JobPosting, is_quebec_location
24 from . import _jsonld 25 from . import _jsonld
@@ -46,8 +47,25 @@ class DigitalRecruitersConnector(BaseConnector):
46 node = _jsonld.extract_jobposting(html) 47 node = _jsonld.extract_jobposting(html)
47 return _jsonld.jobposting_fields(node) if node else {} 48 return _jsonld.jobposting_fields(node) if node else {}
48 49
50+ def _fetch_sitemap(self) -> str:
51+ """Sitemap de la liste, avec garde-fou : une réponse vide ou anti-bot
52+ (challenge en 200, escalade en échec) ne doit JAMAIS passer pour un
53+ babillard à 0 offre — cause des syncs « 0 trouvé » intermittents de
54+ cssdd. Tout sitemap DR légitime, même sans annonce, contient <urlset>
55+ — sinon on retente une fois puis on lève (sync en échec, pas 0)."""
56+ url = f"{self.BASE}/{self.LOCALE}/sitemap.xml"
57+ for attempt in range(2):
58+ xml = self.get(url).text
59+ if _AD_RE.search(xml) or re.search(r"<urlset", xml, re.I):
60+ return xml
61+ if attempt == 0:
62+ time.sleep(10)
63+ raise RuntimeError(
64+ f"digitalrecruiters {self.source_id}: sitemap illisible "
65+ f"(vide ou anti-bot, {len(xml)} octets) — sync avorté")
66+
49 def fetch(self) -> list[JobPosting]: 67 def fetch(self) -> list[JobPosting]:
50− xml = self.get(f"{self.BASE}/{self.LOCALE}/sitemap.xml").text 68+ xml = self._fetch_sitemap()
51 out: list[JobPosting] = [] 69 out: list[JobPosting] = []
52 details_used = 0 70 details_used = 0
53 seen: set[str] = set() 71 seen: set[str] = set()
54 72
Menu

Theme