SPB Git forge

spb/lou-ka

Public

Lou·Ka — tous les logements à louer du Québec, un seul endroit.

232commits 1branches 0releases
172.9 MBsize
maindefault branch
2 days agolast push
HTML 98.9% Python 0.6%
3.5 KB · 86 lines python
Raw Blame History
1# -----------------------------------------------------------------------------2# Lou-Ka — Agrégateur de logements à louer (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# connectors/st_charles_granby.py : connecteur Le St-Charles (stcharlesgranby.com)5#   Condos locatifs modernes au 41, rue Saint-Charles Nord à Granby (studios,6#   3½, 4½, 5½). WordPress/Elementor rendu serveur : la page d'accueil affiche7#   une carte par typologie (« 3 1/2 / À partir de 900$ / mois* »).8#   Granularité : typologie (pas d'unités individuelles publiées).9# -----------------------------------------------------------------------------10from __future__ import annotations1112import re1314from bs4 import BeautifulSoup1516from .base import BaseConnector17from ..schema import Listing, normalize_unit_type1819BASE = "https://www.stcharlesgranby.com"2021ADDRESS = "41, rue Saint-Charles Nord, Granby"22CITY = "Granby"2324TYPE_RE = re.compile(r"^(studio|\d\s*(?:1/2|½))$", re.I)25PRICE_RE = re.compile(r"À\s*partir\s*de\s*(\d[\d\s  ]{2,6})\$\s*/\s*mois",26                      re.I)27IMG_RE = re.compile(r'https://www\.stcharlesgranby\.com/wp-content/uploads/'28                    r'[^"\s\\)]+\.(?:jpe?g|png|webp)', re.I)293031class StCharlesGranbyConnector(BaseConnector):32    source_id = "st_charles_granby"33    request_delay = 0.63435    def fetch(self) -> list[Listing]:36        listings: list[Listing] = []37        try:38            html = self.get(BASE + "/").text39        except Exception:40            return listings41        soup = BeautifulSoup(html, "html.parser")42        lines = soup.get_text("\n", strip=True).split("\n")4344        images = [u for u in dict.fromkeys(IMG_RE.findall(html))45                  if not re.search(r"logo|icon|favicon|plan|"46                                   r"-\d{2,4}x\d{2,4}\.", u, re.I)][:15]4748        # cartes « Studio / À partir de 900$ / mois* » (le menu répète les49        # typologies sans prix : on n'accepte que type suivi d'un prix)50        for i, line in enumerate(lines):51            raw = line.strip()52            if not TYPE_RE.match(raw):53                continue54            nxt = lines[i + 1].strip() if i + 1 < len(lines) else ""55            if TYPE_RE.match(nxt):56                continue          # menu de navigation (types à la suite)57            m = PRICE_RE.search(nxt)58            if not m:59                continue60            unit_type = ("Studio" if raw.lower() == "studio"61                         else normalize_unit_type(raw))62            try:63                price = float(m.group(1).replace(" ", "").replace(" ", ""))64            except ValueError:65                continue66            ext_id = ("granby-studio" if unit_type == "Studio" else67                      f"granby-{unit_type.replace('½', '.5')}")68            if any(l.external_id == ext_id for l in listings):69                continue70            listings.append(Listing(71                source=self.source_id,72                external_id=ext_id,73                url=BASE + "/",74                title=f"{unit_type} — Le St-Charles",75                address=ADDRESS,76                city=CITY,77                unit_type=unit_type,78                price=price,79                price_label=f"À partir de {m.group(1).strip()}$ / mois",80                description="Condos locatifs modernes, lumineux et bien "81                            "pensés au cœur de Granby (studios, 3½, 4½ "82                            "et 5½), à distance de marche des services.",83                images=images,84            ))85        return listings86