SPB Git

spb/lou-ka

Public

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

docs: README v3 — chiffres live vérifiés, pastilles dynamiques, sections complètes

Simon-Pierre Boucher committed (Aug 24, 2026) parent 5b2bff8 Browse files

1 changed file +144 −60

Unified Split
modified README.md +144 −60
@@ -6,25 +6,46 @@
6 <h1 align="center">Lou·Ka</h1> 6 <h1 align="center">Lou·Ka</h1>
7 <p align="center"><b>Tous les logements à louer</b></p> 7 <p align="center"><b>Tous les logements à louer</b></p>
8 8
9−<p align="center"> 9+<div align="center">
10− <a href="https://www.lou-ka.com"><img src="https://img.shields.io/website?url=https%3A%2F%2Fwww.lou-ka.com&style=flat-square&label=www.lou-ka.com&up_color=ff6a00&up_message=en%20ligne" alt="Site"></a> 10+
11− <a href="https://www.lou-ka.com/doc/"><img src="https://img.shields.io/badge/📖_documentation-%2Fdoc-ff6a00?style=flat-square" alt="Documentation"></a> 11+<a href="https://www.lou-ka.com"><img src="https://img.shields.io/website?url=https%3A%2F%2Fwww.lou-ka.com&style=flat-square&label=www.lou-ka.com&up_color=ff6a00&up_message=en%20ligne" alt="Site"></a>
12− <a href="https://www.lou-ka.com/doc/lou-ka-documentation.pdf"><img src="https://img.shields.io/badge/guide-PDF-ff6a00?style=flat-square" alt="PDF"></a> 12+<a href="https://www.lou-ka.com/doc/"><img src="https://img.shields.io/badge/📖_documentation-%2Fdoc-ff6a00?style=flat-square" alt="Documentation"></a>
13− <img src="https://img.shields.io/badge/n%C5%93ud-M3U96b-1f6feb?style=flat-square" alt="Nœud"> 13+<a href="https://www.lou-ka.com/doc/lou-ka-documentation.pdf"><img src="https://img.shields.io/badge/guide-PDF-ff6a00?style=flat-square" alt="PDF"></a>
14− <img src="https://img.shields.io/badge/port-8095-141814?style=flat-square" alt="Port"> 14+<img src="https://img.shields.io/badge/n%C5%93ud-M3U96b-1f6feb?style=flat-square" alt="Nœud">
15− <img src="https://img.shields.io/badge/process-PM2-2b037a?style=flat-square" alt="PM2"> 15+<img src="https://img.shields.io/badge/port-8095-141814?style=flat-square" alt="Port">
16−</p> 16+<img src="https://img.shields.io/badge/process-PM2-2b037a?style=flat-square" alt="PM2">
17−<p align="center"> 17+
18− <img src="https://img.shields.io/badge/Python-3.14-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python"> 18+</div>
19− <img src="https://img.shields.io/badge/FastAPI-API_+_SSR-009688?style=flat-square&logo=fastapi&logoColor=white" alt="FastAPI"> 19+
20− <img src="https://img.shields.io/badge/React_18-Vite_+_TS-087EA4?style=flat-square&logo=react&logoColor=white" alt="React"> 20+<div align="center">
21− <img src="https://img.shields.io/badge/SQLite-WAL-003B57?style=flat-square&logo=sqlite&logoColor=white" alt="SQLite"> 21+
22− <img src="https://img.shields.io/badge/Groupe-KA-ff6a00?style=flat-square" alt="Groupe KA"> 22+<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.lou-ka.com%2Fapi%2Fstats&query=%24.total&label=annonces%20actives&color=ff6a00&style=flat-square" alt="Annonces actives (live)">
23−</p> 23+<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.lou-ka.com%2Fapi%2Fstats&query=%24.sources&label=sources%20actives&color=ff6a00&style=flat-square" alt="Sources actives (live)">
24+<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.lou-ka.com%2Fapi%2Fstats%2Fdetailed&query=%24.totals.cities&label=villes&color=ff6a00&style=flat-square" alt="Villes (live)">
25+<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.lou-ka.com%2Fapi%2Fstats%2Fdetailed&query=%24.totals.regions&label=r%C3%A9gions&color=ff6a00&style=flat-square" alt="Régions (live)">
26+<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.lou-ka.com%2Fapi%2Fstats%2Fdetailed&query=%24.totals.median&label=loyer%20m%C3%A9dian&suffix=%20%24&color=ff6a00&style=flat-square" alt="Loyer médian (live)">
27+<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.lou-ka.com%2Fapi%2Fstats%2Fdetailed&query=%24.totals.gps_pct&label=g%C3%A9olocalis%C3%A9es&suffix=%20%25&color=ff6a00&style=flat-square" alt="Géolocalisées (live)">
28+<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.lou-ka.com%2Fapi%2Fkascores%2Fstats&query=%24.couverture_pct&label=couverture%20KA%20Scores&suffix=%20%25&color=ff6a00&style=flat-square" alt="Couverture KA Scores (live)">
29+<img src="https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fwww.lou-ka.com%2Fapi%2Fct%2Fstats&query=%24.total&label=s%C3%A9jours%20court%20terme&color=ff6a00&style=flat-square" alt="Séjours court terme (live)">
30+
31+</div>
32+
33+<div align="center">
34+
35+<img src="https://img.shields.io/badge/Python-3.14-3776AB?style=flat-square&logo=python&logoColor=white" alt="Python">
36+<img src="https://img.shields.io/badge/FastAPI-API_+_SSR-009688?style=flat-square&logo=fastapi&logoColor=white" alt="FastAPI">
37+<img src="https://img.shields.io/badge/React_18-Vite_+_TS-087EA4?style=flat-square&logo=react&logoColor=white" alt="React">
38+<img src="https://img.shields.io/badge/SQLite-WAL-003B57?style=flat-square&logo=sqlite&logoColor=white" alt="SQLite">
39+<img src="https://img.shields.io/badge/Mapbox_GL-ka--maps-000000?style=flat-square&logo=mapbox&logoColor=white" alt="Mapbox GL">
40+<img src="https://img.shields.io/badge/tunnel-ngrok-1F1E37?style=flat-square&logo=ngrok&logoColor=white" alt="ngrok">
41+<img src="https://img.shields.io/badge/Groupe-KA-ff6a00?style=flat-square" alt="Groupe KA">
42+<a href="https://git.spboucher.ai"><img src="https://img.shields.io/badge/remote--first-spbgit-8250df?style=flat-square&logo=git&logoColor=white" alt="spbgit"></a>
43+
44+</div>
24 45
25 Chercher un appartement au Québec, c'est ouvrir des dizaines de sites différents — chacun avec sa navigation, ses filtres, son format. **Lou·Ka retourne le problème** : un **connecteur dédié par gestionnaire immobilier** visite chaque site, **normalise chaque annonce** vers un schéma unique et **détecte les changements en continu** (synchronisation périodique + hash de contenu → ajouts, mises à jour et retraits automatiques ; une annonce disparue répond `410 Gone`). Chaque fiche renvoie vers l'annonce originale du gestionnaire via une passerelle de sortie transparente (`/passerelle/{uid}`). 46 Chercher un appartement au Québec, c'est ouvrir des dizaines de sites différents — chacun avec sa navigation, ses filtres, son format. **Lou·Ka retourne le problème** : un **connecteur dédié par gestionnaire immobilier** visite chaque site, **normalise chaque annonce** vers un schéma unique et **détecte les changements en continu** (synchronisation périodique + hash de contenu → ajouts, mises à jour et retraits automatiques ; une annonce disparue répond `410 Gone`). Chaque fiche renvoie vers l'annonce originale du gestionnaire via une passerelle de sortie transparente (`/passerelle/{uid}`).
26 47
27−Pour qui ? Les locataires qui cherchent (recherche filtrée, carte 3D, fiches complètes), les curieux du marché (observatoire des loyers, rapports PDF) et les gestionnaires (pages réclamables). **En chiffres** : 22 900+ annonces actives, 265 sources recensées, 212 connecteurs, 820 villes, 11 régions, ~70 % des annonces géolocalisées. 48+Pour qui ? Les locataires qui cherchent (recherche filtrée, carte 3D, fiches complètes), les curieux du marché (observatoire des loyers, rapports PDF) et les gestionnaires (pages réclamables). **En chiffres (au 2026-08-24)** : 45 762 annonces actives publiées, 281 sources recensées, 250 connecteurs (221 location long terme + 29 court terme), 1 233 villes, 11 régions, 97,4 % des annonces géolocalisées, loyer médian 1 700 $ — plus **41 460 séjours court terme** (chalets, Airbnb…) dans la section `/court-terme`.
28 49
29 ## Visite guidée 50 ## Visite guidée
30 51
@@ -82,33 +103,48 @@ Pour qui ? Les locataires qui cherchent (recherche filtrée, carte 3D, fiches co
82 - **Recherche filtrée** — ville, quartier, type (3½, 4½…), loyer min/max, animaux, meublé, superficie, texte libre. 103 - **Recherche filtrée** — ville, quartier, type (3½, 4½…), loyer min/max, animaux, meublé, superficie, texte libre.
83 - **Vue carte 3D** — Lou-Ka Maps (framework `@groupe-ka/ka-maps`, moteur Mapbox GL JS) : clusters par prix moyen, « Rechercher dans cette zone », bascule 3D/2D, synchro liste ↔ carte. 104 - **Vue carte 3D** — Lou-Ka Maps (framework `@groupe-ka/ka-maps`, moteur Mapbox GL JS) : clusters par prix moyen, « Rechercher dans cette zone », bascule 3D/2D, synchro liste ↔ carte.
84 - **Fiches complètes** — toutes les photos, digest structuré de la description (text mining regex FR, aucun LLM), badge marché, historique de prix (`price_log`), fiche PDF avec QR code. 105 - **Fiches complètes** — toutes les photos, digest structuré de la description (text mining regex FR, aucun LLM), badge marché, historique de prix (`price_log`), fiche PDF avec QR code.
85−- **Couches de données de quartier** — recensement 2021, registre des loyers, inondation (BDZI), criminalité (SPVM), qualité de l'air, prix de l'essence, commerces et transport en commun, estimation Hydro-Québec, **KA Scores**. 106+- **Couches de données de quartier** — recensement 2021, registre des loyers (57 433 déclarations géocodées), inondation (BDZI), criminalité (SPVM, 12 mois par catégorie), qualité de l'air (RSQAQ/PST), prix de l'essence, commerces et transport en commun (métro/REM aux couleurs officielles), estimation Hydro-Québec live, **KA Scores** (95,5 % du parc couvert au 2026-08-24).
107+- **Location court terme** — section isolée `/court-terme` (sous-système `louka/shortterm/`, API `/api/ct/*`) : chalets, Airbnb (quadrillage carte quadtree limité à la frontière du Québec), Vrbo, Booking… 41 460 séjours, 22 sources actives sur 38 recensées, 27 régions (au 2026-08-24) ; SEO complet (JSON-LD `VacationRental`, sitemaps `sitemap-ct-N.xml`).
86 - **Pages villes SEO** — `/villes`, `/ville/{slug}`, `/ville/{slug}/{type}` en SSR léger, sitemaps dynamiques (chunks de 10 000), JSON-LD (`RealEstateListing` + `Offer` CAD), vrais `404`/`410`. 108 - **Pages villes SEO** — `/villes`, `/ville/{slug}`, `/ville/{slug}/{type}` en SSR léger, sitemaps dynamiques (chunks de 10 000), JSON-LD (`RealEstateListing` + `Offer` CAD), vrais `404`/`410`.
87−- **Observatoire du marché** — KPI temps réel, loyers médians par région/ville/taille, rapport de marché PDF multi-pages (`/api/stats/rapport.pdf`). 109+- **Observatoire du marché** — KPI temps réel, loyers médians par région/ville/taille, panneaux territoire (registre des loyers, population, essence), rapport de marché PDF multi-pages (`/api/stats/rapport.pdf`) et rapports PDF personnalisés (catalogue + `ReportBuilder`).
88−- **Registre des sources** — chaque gestionnaire, son statut, sa dernière synchro ; toute source non connectable est documentée avec sa raison dans `data/sources.json`. 110+- **Registre des sources** — chaque gestionnaire, son statut, sa dernière synchro ; toute source non connectable est documentée avec sa raison dans `data/sources.json` (281 entrées recensées).
111+- **Qualité éditoriale** — porte de pertinence (quarantaine des stationnements, garages, locaux commerciaux, locations à la nuit) : 59 668 annonces publiées / 1 175 en quarantaine, complétude moyenne 91,4 % (au 2026-08-24).
89 - **Comptes & SSO KA** — « Se connecter avec KA » via le hub groupe-ka.com (JWT HS256, `ka_id` émis par le hub) + Google OAuth direct ; favoris synchronisés vers « Mon univers Ka » ; pages gestionnaires réclamables (`/g/{source_id}`). 112 - **Comptes & SSO KA** — « Se connecter avec KA » via le hub groupe-ka.com (JWT HS256, `ka_id` émis par le hub) + Google OAuth direct ; favoris synchronisés vers « Mon univers Ka » ; pages gestionnaires réclamables (`/g/{source_id}`).
90−- **Widget KA Agent** — bulle de chat IA du Groupe KA intégrée au site. 113+- **Widget KA Agent** — bulle de chat IA du Groupe KA intégrée au site (déplaçable, position mémorisée).
91 - **PWA installable** + app iOS SwiftUI 100 % native (dépôt séparé `lou-ka-ios` sur spbgit). 114 - **PWA installable** + app iOS SwiftUI 100 % native (dépôt séparé `lou-ka-ios` sur spbgit).
92−- **Robustesse** — garde-fou anti-dérive (`DRIFT_RATIO = 0.25`) : si une source retourne soudainement beaucoup moins d'annonces, les retraits sont suspendus au lieu de vider l'inventaire. 115+- **Robustesse** — garde-fou anti-dérive (`DRIFT_RATIO = 0.25`, `louka/db.py`) : si une source retourne soudainement beaucoup moins d'annonces, les retraits sont suspendus au lieu de vider l'inventaire ; chaîne de fetch anti-bot résiliente (Oxylabs → Scrapfly → Bright Data).
93 116
94 ## API (endpoints principaux) 117 ## API (endpoints principaux)
95 118
96 Servis par `louka/web.py` (FastAPI) sur le port 8095. 119 Servis par `louka/web.py` (FastAPI) sur le port 8095.
97 120
98−| Endpoint | Rôle | 121+### Location long terme
99−|---|---| 122+
100−| `GET /api/search` | recherche unifiée liste ↔ carte (mêmes filtres, même compteur) | 123+| Méthode | Endpoint | Rôle |
101−| `GET /api/listings` · `GET /api/listings/{uid}` | annonces paginées + fiche détaillée (`410 Gone` si retirée) | 124+|---|---|---|
102−| `GET /api/listings.geojson` | flux GeoJSON pour la carte 3D | 125+| `GET` | `/api/search` | recherche unifiée liste ↔ carte (mêmes filtres, même compteur) |
103−| `GET /api/listings/{uid}/pdf` | fiche PDF avec QR code | 126+| `GET` | `/api/listings` · `/api/listings/{uid}` | annonces paginées + fiche détaillée (`410 Gone` si retirée) |
104−| `GET /api/facets` · `GET /api/sources` | facettes de filtres, registre des sources | 127+| `GET` | `/api/listings.geojson` | flux GeoJSON pour la carte 3D |
105−| `GET /api/fairvalue/{uid}` | badge marché (juste prix) d'une annonce | 128+| `GET` | `/api/listings/{uid}/pdf` | fiche PDF avec QR code |
106−| `GET /api/rdl` · `/api/inondation` · `/api/air` · `/api/gaz` · `/api/commerces` · `/api/hydro` | couches de quartier : registre des loyers, BDZI, qualité de l'air, essence, commerces/transport, estimation Hydro-Québec | 129+| `GET` | `/api/facets` · `/api/sources` | facettes de filtres, registre des sources |
107−| `GET /api/kascores/stats` | statistiques du moteur KA Scores | 130+| `GET` | `/api/fairvalue/{uid}` | badge marché (juste prix) d'une annonce |
108−| `GET /api/stats` · `/detailed` · `/dashboard` · `/report` · `/catalog` · `POST /api/stats/report/custom` | observatoire + rapports PDF (catalogue et personnalisés) | 131+| `GET` | `/api/rdl` · `/api/inondation` · `/api/air` · `/api/gaz` · `/api/commerces` · `/api/hydro` | couches de quartier : registre des loyers, BDZI, qualité de l'air, essence, commerces/transport, estimation Hydro-Québec |
109−| `GET /api/stats/rapport.pdf` | rapport de marché PDF multi-pages | 132+| `GET` | `/api/kascores/stats` | statistiques du moteur KA Scores |
110−| `POST /api/sync` | déclenchement d'une synchronisation | 133+| `GET` | `/api/stats` · `/detailed` · `/dashboard` · `/report` · `/catalog` | observatoire : KPI, détail, tableau de bord, rapports |
111−| `GET /doc/` | guide d'utilisation en ligne | 134+| `POST` | `/api/stats/report/custom` | rapport PDF personnalisé (ReportBuilder) |
135+| `GET` | `/api/stats/rapport.pdf` | rapport de marché PDF multi-pages |
136+| `POST` | `/api/sync` | déclenchement d'une synchronisation |
137+| `GET` | `/doc/` | guide d'utilisation en ligne |
138+
139+### Location court terme (`/api/ct`, préfixe du sous-système `louka/shortterm/`)
140+
141+| Méthode | Endpoint | Rôle |
142+|---|---|---|
143+| `GET` | `/api/ct/listings` · `/api/ct/listings/{uid}` | séjours paginés + fiche détaillée |
144+| `GET` | `/api/ct/listings.geojson` | flux GeoJSON de la carte court terme |
145+| `GET` | `/api/ct/facets` · `/api/ct/sources` | facettes, registre des sources court terme |
146+| `GET` | `/api/ct/stats` | KPI court terme (total, sources, régions, prix/nuit) |
147+| `POST` | `/api/ct/sync` | déclenchement d'une synchronisation court terme |
112 148
113 ## Architecture 149 ## Architecture
114 150
@@ -116,36 +152,96 @@ Pipeline : **connecteurs → normalisation → déduplication → SQLite → API
116 152
117 - **Backend Python 3.14 / FastAPI / Uvicorn** (`louka/web.py`) : API JSON + service du build Vite + SSR SEO (`louka/seo.py`). 153 - **Backend Python 3.14 / FastAPI / Uvicorn** (`louka/web.py`) : API JSON + service du build Vite + SSR SEO (`louka/seo.py`).
118 - **SQLite (WAL)** (`louka/db.py`) : migrations auto, upsert par hash de contenu, anti-dérive ; bases annexes dans `data/` (quartier, air, gaz, hydro, commerces, inondation…). 154 - **SQLite (WAL)** (`louka/db.py`) : migrations auto, upsert par hash de contenu, anti-dérive ; bases annexes dans `data/` (quartier, air, gaz, hydro, commerces, inondation…).
119−- **212 connecteurs** auto-découverts (`louka/connectors/`), extraction directe / Firecrawl / Scrapfly selon la source. 155+- **250 connecteurs** auto-découverts : 221 long terme (`louka/connectors/`) + 29 court terme (`louka/shortterm/connectors/`), extraction directe / Firecrawl / Scrapfly / Bright Data / acteurs Apify maison selon la source.
120 - **Enrichissement** : géocodage (Nominatim + Adresses Québec), POI OSM, stats de quartier, KA Scores, estimation Hydro-Québec. 156 - **Enrichissement** : géocodage (Nominatim + Adresses Québec), POI OSM, stats de quartier, KA Scores, estimation Hydro-Québec.
121 - **Frontend React 18 + Vite + TypeScript** (`frontend/`), cartographie `@groupe-ka/ka-maps` (Mapbox GL). 157 - **Frontend React 18 + Vite + TypeScript** (`frontend/`), cartographie `@groupe-ka/ka-maps` (Mapbox GL).
122−- **CLI `run.py`** : `sync` · `watch` · `serve` · `geocode` · `poi` · `quartier` · `record` (fixtures HTTP pour tests hors-ligne). 158+- **CLI `run.py`** : `sync` · `watch` · `sync-ct` · `watch-ct` · `serve` · `geocode` · `quality` · `imgaudit` · `fairvalue` · `poi` · `quartier` · `kascores` · `rdl` · `air-refresh` · `gaz-refresh` · `hydro-precompute` · `record` (fixtures HTTP pour tests hors-ligne).
123 159
124 Processus PM2 sur le nœud : 160 Processus PM2 sur le nœud :
125 161
126−| Processus | Rôle | Cadence | 162+| Processus | Commande réelle | Rôle | Cadence |
127−|---|---|---| 163+|---|---|---|---|
128−| `lou-ka-web` | serveur FastAPI/Uvicorn (API + frontend + SSR) sur le port **8095** | continu | 164+| `lou-ka-web` | `.venv/bin/python run.py serve 8095` | serveur FastAPI/Uvicorn (API + frontend + SSR) sur le port **8095** | continu |
129−| `lou-ka-sync` | boucle de resynchronisation des connecteurs (`run.py watch 60`) | cycle de 60 min | 165+| `lou-ka-sync` | `.venv/bin/python run.py watch 60` | boucle de resynchronisation des connecteurs long terme | cycle de 60 min |
130−| `lou-ka-ngrok` | tunnel ngrok vers **www.lou-ka.com** | continu | 166+| `lou-ka-ngrok` | `ngrok http --url=www.lou-ka.com 8095` | tunnel ngrok vers **www.lou-ka.com** | continu |
167+
168+La section court terme se resynchronise via `run.py watch-ct` (défaut 360 min) ou à la demande (`run.py sync-ct`, `POST /api/ct/sync`).
169+
170+## Démarrage rapide
131 171
132−Points de configuration notables (variables d'environnement, sans secrets dans le repo) : clés Scrapfly/Firecrawl pour certains connecteurs, jeton Mapbox du frontend, secret SSO partagé avec le hub KA ID. Le registre des sources vit dans `data/sources.json` ; les bases SQLite de prod sont gitignorées. 172+```bash
173+# Backend (Python 3.14)
174+python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
175+
176+# Frontend (nécessite le framework ka-maps bâti à côté : ../ka-maps)
177+cd frontend && npm install && npm run build && cd ..
178+
179+.venv/bin/python run.py sync # ingestion (toutes les sources ou une liste)
180+.venv/bin/python run.py sync-ct # ingestion court terme
181+.venv/bin/python run.py serve 8095 # API + frontend sur http://localhost:8095
182+.venv/bin/python run.py watch 60 # resynchronisation en boucle (minutes)
183+
184+# Tests (pytest + fixtures HTTP rejouables hors-ligne)
185+.venv/bin/python -m pytest tests/
186+```
187+
188+En développement frontend : `cd frontend && npm run dev` (Vite sur `:5173`, proxy `/api`).
189+
190+## Variables d'environnement
191+
192+Aucun secret dans le repo — tout passe par l'environnement du nœud. Noms attendus :
193+
194+| Variable | Rôle |
195+|---|---|
196+| `SCRAPFLY_KEY` · `FIRECRAWL_API_KEY` · `APIFY_TOKEN` | extraction anti-bot / rendu / acteurs Apify maison |
197+| `BRIGHTDATA_API_KEY` · `BRIGHTDATA_ZONE` | Web Unlocker Bright Data (repli anti-bot) |
198+| `OXYLABS_PROXY` · `OXYLABS_PROXY_USER` · `OXYLABS_PROXY_PASS` | proxies résidentiels (1er maillon de la chaîne de fetch) |
199+| `GOOGLE_CLIENT_ID` · `GOOGLE_CLIENT_SECRET` | connexion Google OAuth directe |
200+| `KA_SSO_SECRET` · `KA_HUB_URL` · `SESSION_SECRET` | SSO KA ID (JWT HS256 partagé avec groupe-ka.com) + sessions |
201+| `HQ_CAPTCHA_PROVIDER` · `HQ_CAPTCHA_KEY` | résolution reCAPTCHA de l'estimation Hydro-Québec |
202+| `LOUKA_BASE_URL` | URL publique de base (liens PDF, sitemaps) |
203+| `LOUKA_<SOURCE>_*` (≈70 variables) | tuning par connecteur : limites de détail, TTL, pages max, cadence (ex. `LOUKA_KIJIJI_DETAIL_LIMIT`, `LOUKA_FBMP_CITIES`, `LOUKA_AIRBNB_BUDGET`) |
204+| `VITE_MAPBOX_TOKEN` (frontend) | jeton public Mapbox de la carte 3D |
205+
206+## Données & conformité
207+
208+- **Agrégateur indépendant** : aucune affiliation avec les gestionnaires immobiliers ; chaque fiche renvoie vers l'annonce originale via la passerelle de sortie transparente `/passerelle/{uid}` (mention affichée au pied du site).
209+- **Provenance** : sites publics des gestionnaires et portails d'annonces (281 sources recensées dans `data/sources.json`, statut et raison documentés pour chaque source non connectable) ; couches de quartier issues de données ouvertes (recensement 2021, registre des loyers, BDZI, SPVM, RSQAQ, Régie de l'énergie, OSM).
210+- **Cadence** : resynchronisation long terme en boucle de 60 min (`lou-ka-sync`), court terme par cycles de 360 min ; détection de changement par hash de contenu → ajouts, mises à jour et retraits automatiques.
211+- **Cycle de vie honnête** : une annonce retirée chez la source répond `410 Gone` et sort des sitemaps ; le garde-fou anti-dérive suspend les retraits massifs suspects plutôt que de vider l'inventaire.
212+- **Qualité** : porte de pertinence (quarantaine du hors-périmètre : stationnements, commerciaux, nuitées) et score de complétude par annonce (moyenne 91,4 %).
133 213
134 ## Structure du repo 214 ## Structure du repo
135 215
136 ``` 216 ```
137 lou-ka/ 217 lou-ka/
138−├── run.py # point d'entrée CLI (sync / watch / serve / geocode / poi / quartier / record) 218+├── run.py # point d'entrée CLI (sync / watch / sync-ct / watch-ct / serve / geocode / poi / quartier / record)
139−├── louka/ # paquet backend : web, seo, db, ingest, normalize, textmine, auth, kascores… + connectors/ (212) 219+├── louka/ # paquet backend : web, seo, db, ingest, normalize, textmine, auth, kascores…
220+│ ├── connectors/ # 221 connecteurs long terme auto-découverts
221+│ └── shortterm/ # sous-système court terme isolé (db, ingest, web + 29 connecteurs)
140 ├── frontend/ # React 18 + Vite + TypeScript (pages, composants, kamaps/) + public/doc/ (guide) 222 ├── frontend/ # React 18 + Vite + TypeScript (pages, composants, kamaps/) + public/doc/ (guide)
141−├── data/ # sources.json (registre) + bases SQLite de prod (gitignorées) 223+├── data/ # sources.json (registre, 281 entrées) + bases SQLite de prod (gitignorées)
142−├── scripts/ # build recensement/contexte/environnement, screenshots, check-order 224+├── scripts/ # build recensement/contexte/environnement, docs connecteurs, screenshots, check-order
143 ├── tests/ # pytest + fixtures HTTP rejouables hors-ligne 225 ├── tests/ # pytest + fixtures HTTP rejouables hors-ligne
144−├── actors/ # acteurs Apify d'appoint 226+├── actors/ # acteurs Apify d'appoint (ka-fb-marketplace, ka-apartments-com…)
145 ├── reports/ # audits (fiches connecteurs, expansion par région, quartier…) 227 ├── reports/ # audits (fiches connecteurs, expansion par région, quartier…)
146 └── docs/ # captures d'écran + docs connecteurs + ka-maps 228 └── docs/ # captures d'écran + docs connecteurs + ka-maps
147 ``` 229 ```
148 230
231+## Historique
232+
233+Repère des jalons (128 commits depuis la naissance) :
234+
235+| Date | Jalon |
236+|---|---|
237+| 2026-08-06 | naissance du projet : agrégateur Québec/Lévis/Grand Montréal, page Statistiques (`fb48938`, `ece6ed0`) |
238+| 2026-08-08 | Mission 1a — couche commune : schéma enrichi, normalisation centrale, robustesse, tests (`7323079`) |
239+| 2026-08-19 | KA Scores calculés sur 94,7 % du parc + standard « ordre des sections = ordre du DOM » (`747f631`, `a6e30ef`) |
240+| 2026-08-21→22 | porte de pertinence (quarantaine hors-périmètre) + chaîne de fetch anti-bot Oxylabs→Scrapfly→Bright Data + acteurs Apify maison FB Marketplace / Apartments.com (`8547737`, `8598785`, `e7f4876`) |
241+| 2026-08-22→23 | section « Location court terme » : sous-système isolé, Airbnb en quadrillage carte, 38 sources recensées, SEO complet (`38b708b`, `5c571bc`, `63456a0`) |
242+| 2026-08-23 | couches de quartier : registre des loyers (57 433 déclarations), inondation BDZI, criminalité SPVM, air, essence, commerces/transport, estimation Hydro-Québec live + rapports PDF personnalisés (`604455e` → `4d17c17`, `834c92c`) |
243+| 2026-08-24 | page documentation `/doc` + guide PDF + README v2/v3 (`963ba8f`, `4fa8714`) |
244+
149 ## Documentation 245 ## Documentation
150 246
151 - **Guide en ligne** : [www.lou-ka.com/doc/](https://www.lou-ka.com/doc/) — à quoi sert le site, le parcours en 4 étapes (recherche → résultats → fiche → /stats), d'où viennent les données, FAQ. 247 - **Guide en ligne** : [www.lou-ka.com/doc/](https://www.lou-ka.com/doc/) — à quoi sert le site, le parcours en 4 étapes (recherche → résultats → fiche → /stats), d'où viennent les données, FAQ.
@@ -160,21 +256,9 @@ lou-ka/
160 - L'agent forwarding SSH est actif : le `git push origin main` fonctionne pendant une session SSH depuis le laptop. 256 - L'agent forwarding SSH est actif : le `git push origin main` fonctionne pendant une session SSH depuis le laptop.
161 257
162 ```bash 258 ```bash
163−# Backend
164−python3 -m venv .venv && .venv/bin/pip install -r requirements.txt
165−
166−# Frontend (nécessite le framework ka-maps bâti à côté : ../ka-maps)
167−cd frontend && npm install && npm run build && cd ..
168−
169−.venv/bin/python run.py sync # ingestion (toutes les sources ou une liste)
170−.venv/bin/python run.py serve 8095 # API + frontend
171−.venv/bin/python run.py watch 60 # resynchronisation en boucle (minutes)
172−
173 pm2 restart lou-ka-web # après un changement en production 259 pm2 restart lou-ka-web # après un changement en production
174 ``` 260 ```
175 261
176−En développement frontend : `cd frontend && npm run dev` (Vite sur `:5173`, proxy `/api`).
177−
178 ## Déploiement 262 ## Déploiement
179 263
180 - **Nœud** : M3U96b (Mac Studio, cluster MacLustr) — répertoire `~/apps/lou-ka` 264 - **Nœud** : M3U96b (Mac Studio, cluster MacLustr) — répertoire `~/apps/lou-ka`
181 265
Menu

Theme