# ----------------------------------------------------------------------------- # Immo-Ka — Agrégateur de maisons à vendre (province de Québec) # Auteur : Simon-Pierre Boucher — contact@spboucher.ai # connectors/agenceimage.py : Image, l'agence immobilière (agenceimage.ca) — # Saguenay, Jonquière, Roberval, Dolbeau-Mistassini, Lac-Saint-Jean. # Plateforme Yoamo (ID-3 Innovations) + photos Centris. La page /mes-proprietes/ # rend TOUT l'inventaire côté serveur : chaque carte porte n° Centris (rel/URL), # type + ville (dans l'URL et l'alt), coordonnées (data-geo-lat/lng), prix et # photo (yoamo.immo/ALSPicture.axd?propId={Centris}). # # Page détail (rel="/proprietes/a-vendre/{type}/{ville}/{centris}/") rendue # serveur elle aussi : galerie complète (ALSPicture.axd, une URL par seq=N, # pleine taille sans &w=), description JSON-LD (Product), sections # libellé (#building/#land/#more-carac), # pièces (#rooms), « En complément » (taxes, évaluation, année, terrain), # inclusions/exclusions, courtier (#broker_list, schema.org/RealEstateAgent) # et lien Google Maps (adresse + GPS). ⚠ la section #related (« Aussi # disponibles ») liste d'AUTRES propriétés — tout est parsé AVANT elle. # # source_id « image_ag_qc » : infixe _ag_ = dédup Centris (db.refresh_dedup) — # masque les fiches déjà portées par une bannière couverte au Saguenay–LSJ. # ----------------------------------------------------------------------------- from __future__ import annotations import html as _html import os import re from .base import BaseConnector from . import _detailutil as du from ..normalize import parse_lot_sqft from ..schema import PropertyListing SITE = "https://agenceimage.ca" LISTING = SITE + "/mes-proprietes/" AGENCY = "Image, l'agence immobilière" DETAIL_LIMIT = int(os.environ.get("IMMOKA_IMAGE_DETAIL_LIMIT", os.environ.get("IMMOKA_DETAIL_LIMIT", "100"))) # chaque fiche = un
dont les data-filter-* portent # tout (prix, ville, genre, chambres, sdb, coords) — plus fiable que le HTML visible. _ART_SPLIT = re.compile(r']+', re.I) _SUP_LABEL_RE = re.compile(r'([^<]+)\s*', re.I) _MAPS_RE = re.compile(r'google\.[^"\']*?[?&]q=([^@"\']+)@(-?\d{1,2}\.\d+),(-?\d{2,3}\.\d+)') def _attr(blk: str, name: str) -> str: m = re.search(name + r'="([^"]*)"', blk, re.I) return _html.unescape(m.group(1)).strip() if m else "" def _deslug(s: str) -> str: return _html.unescape(s.replace("-", " ")).strip().title() def _section(html: str, sid: str) -> str: m = re.search(r'
' % re.escape(sid), html, re.S | re.I) return m.group(0) if m else "" def _text(fragment: str) -> str: return re.sub(r"\s+", " ", _html.unescape(re.sub(r"<[^>]+>", " ", fragment))).strip() def parse_image_detail(html: str) -> dict: """Fiche Yoamo/agenceimage.ca : galerie complète (ordre seq=), description JSON-LD, caractéristiques /