# msi — MSI Gestion immobilière - site: https://www.msimmobiliers.com/appartements-a-louer/{quebec,levis,montreal} (BFS des secteurs + fiches unité) - méthode: html + json embarqué (payload « flight » Next.js dans les fiches) - annonces: 99 → 96 (3 annonces périmées désactivées au passage) - couverture après (sur 96 annonces): prix 100%, adresse 100%, dispo 100%, superficie 6%, commodités 100% - fixture: ok · test: ok ## Champs extraits - Cartes liste (inchangé) : type (4 1/2…), prix, catégorie, adresse, quartier, disponibilité (« Libre immédiatement », « Disponibilité : 01 septembre 2026 ») ; stationnements/commerciaux exclus. - Fiches unité — objet JSON `rental` extrait du payload Next.js `self.__next_f.push` (nouveau) : - adresse complète avec ville (« 167 Avenue Ruel, Québec, QC, Canada ») ; - lat/lng structurés (100 % des annonces) ; - date de disponibilité ISO (repli si la carte liste n'a pas de texte) ; - étage structuré -> details.floor ; superficie (`area`, quand > 0 : 6 annonces — la source affiche « N/C » ailleurs) ; - galerie photo complète (avant : regex wp-content sur toute la page). - Liste « Caractéristiques » affichée (li de .rental-content__hero--facilities) -> amenities brutes : « Balcon », « Entrée laveuse/sécheuse », « Espace de rangement », « Stationnement inclus », « Chien interdit », « Non fumeur », « Dernier étage »… (« N/C » et « ** Location sur approbation » filtrés) ; repli sur les `features` JSON. ## Champs indisponibles à la source - Superficie pour ~94 % des unités (champ `area` à 0, « N/C » affiché). - Description libre (le champ `catchphrase` est presque toujours vide — extrait quand présent), meublé, contact direct par unité. - Politique animaux limitée aux chiens (`dogPolicy` / « Chien interdit » — rien sur les chats). ## Fragilités - Le payload flight Next.js est un format interne non documenté (extraction par dés-échappement + appariement d'accolades) ; repli conservé (regex images wp-content, features JSON). - BFS plafonné à 90 pages liste ; fiches plafonnées à 150 vraies requêtes/sync (cache BD self.detail, clé = hash de la carte liste) — 1er sync ~86 s, syncs suivants ~23 s. - Redirection 301 www -> apex suivie automatiquement par requests. ## Améliorations apportées - Pages détail migrées vers self.detail(...) (cache BD) avec plafond de vraies requêtes (avant : 200 fetchs directs à CHAQUE sync, uniquement pour les images). - Nouveaux champs : lat/lng (0 -> 100 %), amenities (0 -> 100 %), details.floor, adresse complète avec ville, superficie/dispo ISO quand présentes, images plus fiables (galerie JSON ordonnée). - 2026-08-08 — Expansion provinciale (lot 0) : racine `/appartements-a-louer/thetford-mine` ajoutée (ROOTS + `_ROOT_CITY` → « Thetford Mines »). Page valide (200) mais 0 unité affichée actuellement — flux intermittent, les annonces remonteront automatiquement quand MSI en publiera. 96 annonces au total (inchangé : Québec 72, Lévis 10, Montréal 14). Fixture réenregistrée, 2 tests verts. ## Échantillon avant/après - Avant : « 167 Avenue Ruel » — 1095 $, 4½, « Libre immédiatement », superficie NULL, pets NULL, details {}, amenities [], adresse « 167 Avenue Ruel », pas de lat/lng. - Après : même annonce — details `{"appliances": {"dishwasher": true, "washer_dryer_hookup": true}, "balcony": true, "storage": true, "smoking": false, "parking": {"available": true, "included": true}, "floor": 2}`, 8 amenities brutes, adresse « 167 Avenue Ruel, Québec, QC, Canada », lat 46.8745 / lng -71.1607. ## Lacunes génériques de normalisation observées - « Chien interdit » (item courant chez MSI) n'est reconnu par aucun motif pets (_PETS_NO_RE/_PETS_COND_RE) -> pets reste NULL alors que l'info existe. - « Entrée lave-vaisselle » (= sortie/branchement, pas d'appareil fourni) matche la règle dishwasher -> appliances.dishwasher=true à tort ; il existe un traitement « entrées laveuse-sécheuse » (washer_dryer_hookup) mais pas d'équivalent pour le lave-vaisselle.