# ----------------------------------------------------------------------------- # Lou-Ka — Agrégateur de logements à louer (province de Québec) # Auteur : Simon-Pierre Boucher — contact@spboucher.ai # connectors/viventi.py : connecteur Complexe Viventi Laval (viventilaval.com) # Immeuble unique pour 45/50 ans et plus au 1100, boul. Vanier (secteur # Saint-Vincent-de-Paul, Laval). WordPress/Elementor rendu serveur : la page # /nos-unites/ affiche une section par TYPOLOGIE (3½, 4½) avec prix # « À partir de X$/mois » et liste d'inclusions. Granularité TYPOLOGIE, # pas de disponibilité par unité. # ----------------------------------------------------------------------------- from __future__ import annotations import re from bs4 import BeautifulSoup from ..schema import Listing, normalize_unit_type from .base import BaseConnector BASE = "https://viventilaval.com" PAGE_URL = f"{BASE}/nos-unites/" ADDRESS = "1100, boul. Vanier" CITY = "Laval" SECTOR = "Saint-Vincent-de-Paul" TYPE_RE = re.compile(r"^\d\s*(?:1/2|½)$") PRICE_RE = re.compile(r"À partir de\s*([\d\s ,]+)\s*\$\s*/\s*mois", re.I) IMG_RE = re.compile( r"https://viventilaval\.com/wp-content/uploads/[^\"'\s\\)]+?" r"\.(?:jpg|jpeg|png|webp)", re.I) class ViventiConnector(BaseConnector): source_id = "viventi" request_delay = 0.6 def fetch(self) -> list[Listing]: listings: list[Listing] = [] try: html = self.get(PAGE_URL).text except Exception: return listings soup = BeautifulSoup(html, "html.parser") # photos communes de l'immeuble (les sections typologie n'ont pas de # galerie propre) — on écarte logos/favicons et miniatures redimensionnées images = [u for u in dict.fromkeys(IMG_RE.findall(html)) if not re.search(r"logo|favicon|icon|-\d+x\d+\.", u, re.I)][:20] # une section par typologie :