[ka2] fix connecteur location_saguenay: retry (3 essais, espacés par le throttling 10 s) de la page liste — une page 200 servie sans le menu « Logements disponibles » (raté transitoire, vu 2026-08-29 03:47) produisait un faux « 0 trouvé ok »; après 3 essais infructueux le connecteur lève une erreur franche au lieu d'un zéro silencieux. Testé: 21 annonces (= médiane 21)
1 changed file +24 −15
modified
louka/connectors/location_saguenay.py
+24 −15
@@ -37,22 +37,19 @@ class LocationSaguenayConnector(BaseConnector): | ||
| 37 | 37 | max_details = 12 # garde-fou fiches détail (vraies requêtes par sync) |
| 38 | 38 | |
| 39 | 39 | def fetch(self) -> list[Listing]: |
| 40 | − html = self.get(LIST_URL).text | |
| 41 | − soup = BeautifulSoup(html, "html.parser") | |
| 42 | − | |
| 43 | − menu = soup.select_one("ul.blog-menu") | |
| 44 | − if menu is None: | |
| 45 | − return [] | |
| 46 | − | |
| 47 | − # entrée « Logements disponibles » du menu principal | |
| 48 | − root = None | |
| 49 | − for li in menu.find_all("li", recursive=False): | |
| 50 | − a = li.find("a", recursive=False) | |
| 51 | − if a and "logements disponibles" in a.get_text(strip=True).lower(): | |
| 52 | − root = li.find("ul", class_="sub-menu") | |
| 40 | + # Un raté transitoire (page 200 sans le menu « Logements disponibles », | |
| 41 | + # vu 2026-08-29) produisait un faux « 0 trouvé ok » : retry court, puis | |
| 42 | + # erreur franche plutôt qu'un zéro silencieux. Le throttling de get() | |
| 43 | + # (10 s) espace naturellement les essais. | |
| 44 | + for _ in range(3): | |
| 45 | + html = self.get(LIST_URL).text | |
| 46 | + soup = BeautifulSoup(html, "html.parser") | |
| 47 | + root = self._find_menu_root(soup) | |
| 48 | + if root is not None: | |
| 53 | 49 | break |
| 54 | − if root is None: | |
| 55 | − return [] | |
| 50 | + else: | |
| 51 | + raise RuntimeError( | |
| 52 | + "menu « Logements disponibles » introuvable après 3 essais") | |
| 56 | 53 | |
| 57 | 54 | self._fetched = 0 |
| 58 | 55 | listings: dict[str, Listing] = {} |
@@ -72,6 +69,18 @@ class LocationSaguenayConnector(BaseConnector): | ||
| 72 | 69 | continue |
| 73 | 70 | return list(listings.values()) |
| 74 | 71 | |
| 72 | + @staticmethod | |
| 73 | + def _find_menu_root(soup: BeautifulSoup): | |
| 74 | + """Sous-menu de l'entrée « Logements disponibles » du menu principal.""" | |
| 75 | + menu = soup.select_one("ul.blog-menu") | |
| 76 | + if menu is None: | |
| 77 | + return None | |
| 78 | + for li in menu.find_all("li", recursive=False): | |
| 79 | + a = li.find("a", recursive=False) | |
| 80 | + if a and "logements disponibles" in a.get_text(strip=True).lower(): | |
| 81 | + return li.find("ul", class_="sub-menu") | |
| 82 | + return None | |
| 83 | + | |
| 75 | 84 | # -- entrée du menu (une fiche WP par immeuble/type) ------------------------------- |
| 76 | 85 | def _parse_entry(self, a, bedrooms: str, |
| 77 | 86 | listings: dict[str, Listing]) -> None: |
| 78 | 87 | |