spb/lou-ka Public
Lou·Ka — tous les logements à louer du Québec, un seul endroit.
HTML 99.7%
1# -----------------------------------------------------------------------------2# Lou-Ka — Agrégateur de logements à louer (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# connectors/alexcellence.py : connecteur Immeubles Alexcellence5# (immeublesalexcellence.com) — apparts à Sherbrooke, secteurs Université de6# Sherbrooke et Mont-Bellevue (clientèle étudiante). WordPress + thème7# immobilier Houzez : 4e membre de la famille Houzez de l'Estrie — hérite de8# DynamicConnector (lesgestionsdynamic.com) et n'en redéfinit que les9# constantes et le crochet de disponibilité. Archive /appartements-a-louer/10# paginée (cartes item-listing-wrap v6 avec data-listid, data-images,11# item-price « 1,010$/par mois »). Particularité locale : les étiquettes12# label-status portent à la fois le statut (« À LOUER » / « LOUÉ ») et la13# date de libération (« 1er août 2026 ») — les logements LOUÉ sont écartés,14# la date devient la disponibilité. Fiches détail Houzez sans bloc adresse15# structuré ni GPS : description + address.item-address seulement.16# -----------------------------------------------------------------------------17from __future__ import annotations1819import re2021from .dynamic import DynamicConnector222324class AlexcellenceConnector(DynamicConnector):25 source_id = "alexcellence"26 request_delay = 0.727 max_pages = 628 max_details = 402930 BASE = "https://immeublesalexcellence.com"31 LIST_PATH = "/appartements-a-louer/"32 CITY_DEFAULT = "Sherbrooke"3334 def _card_availability(self, card, title: str) -> str:35 """Étiquettes label-status de la carte : « LOUÉ » fait écarter le36 logement (le parent filtre toute disponibilité contenant « loué ») ;37 sinon l'étiquette de date (« 1er août 2026 ») est la disponibilité."""38 labels = [re.sub(r"\s+", " ", el.get_text(" ", strip=True)).strip()39 for el in card.select(".label-status")]40 labels = [l for l in labels if l]41 for label in labels:42 if re.search(r"\blou[ée]s?\b", label, re.I):43 return label # « LOUÉ » -> carte écartée44 for label in labels:45 if not re.fullmatch(r"[àa] louer", label, re.I):46 return label # date de libération47 return ""48