SPB Git forge

spb/immo-ka

Public

Immo-Ka — agrégateur des propriétés à vendre au Québec (73 connecteurs, ~40 000 annonces, React+FastAPI)

112commits 1branches 0releases
125.4 MBsize
maindefault branch
13 days agolast push
Python 47.5% HTML 27.9% TypeScript 15.5% CSS 7.2% JavaScript 2%

Vague 3 : Realtor.ca (MLS pan-bannières via Scrapfly ASP), Sotheby's complet (AJAX interne, 60→869), 7 agences source.immo (dont chambre CIEMCQ ~3 900), Guide Habitation (projets neufs)

- realtor_ca.py : rejoue PropertySearch_Post via Scrapfly ASP sans render_js
  (DataDome contourné) ; 14 shards bbox QC, tri récentes d abord, budget
  IMMOKA_REALTOR_MAX (défaut 2 000/sync ≈ 10-14 appels) ; external_id = MLS
  + _ag_ → dédup Centris masque les recoupements (2 145 fiches, 343 uniques).
- sothebys_quebec.py : endpoint /include/ajax_results.php débloqué
  (p_territories[]=4, p_status neutre, remap serveur documenté) ; 869 fiches
  à vendre au lieu de ~60 ; repli pages région conservé.
- agences source.immo : si_ag_ciemcq (Mon-Toit, Estrie-Mauricie-CdQ, 3 920
  fiches / 1 169 uniques), avenue, provad, peladeau, ferri, si_ag_jga,
  si_ag_katiasamson.
- guidehabitation.py : répertoire des projets neufs (microdonnées schema.org,
  9 régions, 95 projets à vendre, locatifs écartés).
- sources.json + source_immo_agencies.json + docs régénérées (50 fiches).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Simon-Pierre Boucher committed 1 mo ago (Aug 18, 2026) parent a6094f7

60 changed files +1,473 −275

modified data/source_immo_agencies.json +125 −55
@@ -1,56 +1,126 @@
1 1 [
2 − {
3 − "id": "realta",
4 − "name": "Réalta Agence Immobilière",
5 − "domain": "www.realta.ca",
6 − "account": "e194f20f-f55f-4667-969a-eaa682cf057e",
7 − "api": "68a52c3d-0e3c-46fa-be6a-6a77b53f0941",
8 − "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
9 − "view": "c2c07cb5-2208-4d99-9011-e79f8e126230"
10 − },
11 − {
12 − "id": "immodev",
13 − "name": "Immodev Agence Immobilière",
14 − "domain": "www.immodev.ca",
15 − "account": "4aabc46f-23a9-4933-8b7e-87fd85c87a18",
16 − "api": "b495482c-5c80-4818-b225-ee79817d25db",
17 − "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
18 − "view": "18446f15-3781-487e-8758-58a1b9d53465"
19 − },
20 − {
21 − "id": "gaillardetz",
22 − "name": "Gaillardetz Agence Immobilière",
23 − "domain": "www.gaillardetz.ca",
24 − "account": "44654d27-d2ef-4362-a408-8e5bc41ba147",
25 − "api": "bc1adc4c-f206-4129-b3be-ae8b6206a7c2",
26 − "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
27 − "view": "d5368a27-402b-44b4-9f10-067af7e3f2f2"
28 − },
29 − {
30 − "id": "domicilia",
31 − "name": "Domicilia Agence Immobilière",
32 − "domain": "www.domicilia.com",
33 − "account": "02f9532b-c512-483a-9354-5ddf9fda8468",
34 − "api": "75a0468e-8405-410f-a80a-6ce87a975e80",
35 − "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
36 − "view": "eb448815-be1d-4592-91a5-12908bdc2e24"
37 − },
38 − {
39 − "id": "niddamour",
40 − "name": "Nid d'Amour Agence Immobilière",
41 − "domain": "www.niddamour.ca",
42 − "account": "08d1a0fd-0673-48d0-bb86-e40fe529bfdb",
43 − "api": "80e7941c-66b1-45a0-b6e0-622b401367e0",
44 − "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
45 − "view": "25cb8710-6c99-47ce-b137-8c667b63062c"
46 − },
47 − {
48 − "id": "si_ag_theagency",
49 − "name": "The Agency Montréal",
50 − "domain": "theagencymontreal.com",
51 − "account": "dcb0f01e-8f29-4347-84f0-170875281872",
52 − "api": "2941096d-6a2e-418e-9783-5c3d59790bd0",
53 − "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
54 − "view": "4cf4819e-a0e9-4288-93d2-002cd8f40435"
55 − }
56 −]
\ No newline at end of file
2 + {
3 + "id": "realta",
4 + "name": "Réalta Agence Immobilière",
5 + "domain": "www.realta.ca",
6 + "account": "e194f20f-f55f-4667-969a-eaa682cf057e",
7 + "api": "68a52c3d-0e3c-46fa-be6a-6a77b53f0941",
8 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
9 + "view": "c2c07cb5-2208-4d99-9011-e79f8e126230"
10 + },
11 + {
12 + "id": "immodev",
13 + "name": "Immodev Agence Immobilière",
14 + "domain": "www.immodev.ca",
15 + "account": "4aabc46f-23a9-4933-8b7e-87fd85c87a18",
16 + "api": "b495482c-5c80-4818-b225-ee79817d25db",
17 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
18 + "view": "18446f15-3781-487e-8758-58a1b9d53465"
19 + },
20 + {
21 + "id": "gaillardetz",
22 + "name": "Gaillardetz Agence Immobilière",
23 + "domain": "www.gaillardetz.ca",
24 + "account": "44654d27-d2ef-4362-a408-8e5bc41ba147",
25 + "api": "bc1adc4c-f206-4129-b3be-ae8b6206a7c2",
26 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
27 + "view": "d5368a27-402b-44b4-9f10-067af7e3f2f2"
28 + },
29 + {
30 + "id": "domicilia",
31 + "name": "Domicilia Agence Immobilière",
32 + "domain": "www.domicilia.com",
33 + "account": "02f9532b-c512-483a-9354-5ddf9fda8468",
34 + "api": "75a0468e-8405-410f-a80a-6ce87a975e80",
35 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
36 + "view": "eb448815-be1d-4592-91a5-12908bdc2e24"
37 + },
38 + {
39 + "id": "niddamour",
40 + "name": "Nid d'Amour Agence Immobilière",
41 + "domain": "www.niddamour.ca",
42 + "account": "08d1a0fd-0673-48d0-bb86-e40fe529bfdb",
43 + "api": "80e7941c-66b1-45a0-b6e0-622b401367e0",
44 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
45 + "view": "25cb8710-6c99-47ce-b137-8c667b63062c"
46 + },
47 + {
48 + "id": "si_ag_theagency",
49 + "name": "The Agency Montréal",
50 + "domain": "theagencymontreal.com",
51 + "account": "dcb0f01e-8f29-4347-84f0-170875281872",
52 + "api": "2941096d-6a2e-418e-9783-5c3d59790bd0",
53 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
54 + "view": "4cf4819e-a0e9-4288-93d2-002cd8f40435"
55 + },
56 + {
57 + "id": "si_ag_ciemcq",
58 + "name": "Chambre immobilière Estrie–Mauricie–Centre-du-Québec (Mon-Toit)",
59 + "domain": "www.mon-toit.net",
60 + "account": "e494abe8-cb57-4f96-ad3f-19d3ee9829de",
61 + "api": "fe3dbcfd-c48f-4a43-bcad-065f405df0df",
62 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
63 + "view": "f05abe23-54e0-4f3b-9ac4-dc686a630818",
64 + "note": "Chambre = flux co-listé avec les bannières (≈600 courtiers) → si_ag_ pour la dédup Centris. ~3 900 fiches à vendre (2026-08-18). Config aussi sur ciemcq.com."
65 + },
66 + {
67 + "id": "avenue",
68 + "name": "Avenue Immobilier",
69 + "domain": "avenueimmo.com",
70 + "account": "abbb1cbd-d342-4ed4-8644-ac50392a8ad0",
71 + "api": "96f47605-b917-494c-972d-f5b62e6cea29",
72 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
73 + "view": "3f93275f-a8fb-442b-8604-c72e53e86bc2",
74 + "note": "Agence indépendante (Brossard). ~42 fiches à vendre (2026-08-18)."
75 + },
76 + {
77 + "id": "provad",
78 + "name": "Proulx Vadnais & Associés",
79 + "domain": "provad.ca",
80 + "account": "941e16f0-4cb6-413e-b9b1-257657b54717",
81 + "api": "d0c3b02c-45e2-4406-94de-aa4be5ad5c3d",
82 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
83 + "view": "2cf82736-4de7-44d2-bfa9-126d4874b872",
84 + "note": "Agence indépendante commerciale/industrielle (Laval, Rive-Nord). ~80 fiches à vendre (2026-08-18)."
85 + },
86 + {
87 + "id": "peladeau",
88 + "name": "Péladeau Agence Immobilière",
89 + "domain": "www.epeladeau.com",
90 + "account": "5602193c-a49c-4693-906f-8095cd5d2666",
91 + "api": "6f4339b4-a5eb-4826-a98b-a8d3b85bc92b",
92 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
93 + "view": "914b348a-48fe-42c5-96a2-52dd5f6c4307",
94 + "note": "Agence indépendante. ~47 fiches à vendre (2026-08-18)."
95 + },
96 + {
97 + "id": "ferri",
98 + "name": "Ferri Services Immobiliers",
99 + "domain": "www.ferri.ca",
100 + "account": "8b83609e-52b5-4955-8322-020d156e9198",
101 + "api": "8a1d59c0-282b-43f4-a559-88f942a08036",
102 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
103 + "view": "56eb1796-fae8-4ffa-86a3-90a6c59c414f",
104 + "note": "Agence indépendante (Laval/Montréal). ~22 fiches à vendre (2026-08-18)."
105 + },
106 + {
107 + "id": "si_ag_jga",
108 + "name": "JGA Équipe Commerciale (Royal LePage)",
109 + "domain": "jgacommercial.com",
110 + "account": "7d8a1086-f038-436d-ba6c-8fc1a81dc187",
111 + "api": "66d60651-2d83-4e82-91cc-b80a0c7e07b1",
112 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
113 + "view": "a1f2e4b6-ef44-4d97-a608-3cc9d7762f1f",
114 + "note": "Équipe commerciale/industrielle Royal LePage → si_ag_ (co-inscriptions Centris). ~64 fiches à vendre (2026-08-18)."
115 + },
116 + {
117 + "id": "si_ag_katiasamson",
118 + "name": "Katia Samson (RE/MAX L'Espace)",
119 + "domain": "www.katiasamson.com",
120 + "account": "5cd485f7-9aa3-4d32-a42a-1fbaff506ec7",
121 + "api": "ede21420-ea2b-4027-b0eb-bb6d6f2d7446",
122 + "app": "ead7575f-8d1c-42e7-9f59-4cf9e065167e",
123 + "view": "f0319c2d-b2eb-4328-b32a-f7219f769708",
124 + "note": "Équipe RE/MAX L'Espace → si_ag_ (co-inscriptions Centris, remax_ag_lespace couvert). ~30 fiches à vendre (2026-08-18)."
125 + }
126 +]
modified data/sources.json +100 −1
@@ -129,7 +129,7 @@
129 129 "connector": "sothebys_quebec",
130 130 "status": "actif",
131 131 "type": "luxe",
132 − "note": "Recherche rendue côté client. Fiches enumérées via pages de résultats (grid public plafonné ~40 fiches province-wide ; pagination AJAX non exposée en URL). Chaque fiche enrichie via son JSON-LD Product : prix, galerie S3 complète (35-75 photos), description, MLS (sku), type. Limite : couverture = set public courant (~40) ; coverage complète nécessiterait l'endpoint AJAX de pagination."
132 + "note": "Inventaire COMPLET via l'API AJAX interne /include/ajax_results.php (dowhat=getgridresults, jeton ajaxtoken de la page province, p_territories[]=4 = Québec, 64 fiches/page). Particularité : les valeurs du filtre statut de l'UI (1=For Sale, 3=For Rent) sont remappées côté serveur — on passe p_status[]=2 (neutre → aucun filtre → tout l'inventaire actif) et on écarte les locations («…/mo») au parsing. ~1 100 fiches QC dont ~965 à vendre (2026-08-18) contre ~40-60 avant (grid public plafonné). Enrichissement JSON-LD Product par fiche : prix, galerie S3 complète, description, MLS (sku). Repli : ancien parcours des pages région."
133 133 },
134 134 {
135 135 "id": "profusion",
@@ -438,6 +438,105 @@
438 438 "status": "actif",
439 439 "type": "franchise",
440 440 "note": "WordPress (MW Properties / marketingwebsites.ca), liste SSR paginée ?pages=N (~9/page, ~11 pages). Carte col-lg-4: no Centris (URL+image+property-meta), région, adresse, ville, prix ($US), chambres/sdb, photo. source_id _ag_ = dédup Centris."
441 + },
442 + {
443 + "id": "realtor_ag_ca",
444 + "name": "Realtor.ca (MLS Québec)",
445 + "url": "https://www.realtor.ca",
446 + "listing_url": "https://www.realtor.ca/map#view=list&Province=QC",
447 + "coverage": "Toute la province — agrégateur MLS pan-bannières (SCI/CREA)",
448 + "connector": "realtor_ca",
449 + "status": "actif",
450 + "type": "agrégateur",
451 + "note": "API interne api2.realtor.ca/Listing.svc/PropertySearch_Post (POST form). Protégée DataDome/Incapsula : accès direct = 403, mais REJOUABLE via Scrapfly ASP SANS render_js (vérifié 2026-08-18) → JSON riche : MLS, GPS, prix, CAC/SDB, superficie, photos, courtier+agence. 200 fiches/page, plafond serveur 600/recherche → sharding par 14 boîtes lat/lng QC, tri plus récentes d'abord (Sort=6-D). Budget borné IMMOKA_REALTOR_MAX (défaut 2 000 fiches/sync ≈ 10 appels Scrapfly — les ~10 shards les plus denses ; augmenter pour couvrir les régions éloignées ; 0 = désactivé). external_id = n° MLS Centris + infixe _ag_ → la dédup masque tout recoupement avec les connecteurs directs ; seules les fiches des bannières non couvertes restent visibles. Fenêtre glissante : les fiches anciennes sortent du budget au fil des syncs (miss_count → inactif)."
452 + },
453 + {
454 + "id": "guidehabitation",
455 + "name": "Guide Habitation (projets neufs)",
456 + "url": "https://www.guidehabitation.ca",
457 + "listing_url": "https://www.guidehabitation.ca/fr/projets-immobiliers/montreal/",
458 + "coverage": "Québec habité (9 régions) — projets neufs des promoteurs (condos et maisons neuves à vendre)",
459 + "connector": "guidehabitation",
460 + "status": "actif",
461 + "type": "répertoire",
462 + "note": "Répertoire de référence des projets neufs. Pages région /fr/projets-immobiliers/{region}/ rendues serveur avec microdonnées schema.org par carte : adresse, ville, GPS, prix « À partir de » (itemprop=price), type, description, chambres, photo. Aucune clé, aucun JS. Projets LOCATIFS écartés (prix mensuel < 50 000 $ ou « locatif » dans le texte). 1 fiche = 1 projet (prix plancher, details.price_from)."
463 + },
464 + {
465 + "id": "si_ag_ciemcq",
466 + "name": "Chambre immobilière Estrie–Mauricie–Centre-du-Québec (Mon-Toit)",
467 + "url": "https://www.mon-toit.net",
468 + "listing_url": "https://www.mon-toit.net/proprietes/",
469 + "coverage": "Estrie, Mauricie, Centre-du-Québec — ~600 courtiers (chambre régionale)",
470 + "connector": "si_ag_ciemcq",
471 + "status": "actif",
472 + "type": "chambre",
473 + "note": "Plateforme source.immo (config publique _configs.json sur mon-toit.net et ciemcq.com). ~3 900 fiches à vendre (2026-08-18). Flux co-listé avec les bannières → si_ag_ (dédup Centris). Généré par agences_source_immo.py."
474 + },
475 + {
476 + "id": "avenue",
477 + "name": "Avenue Immobilier",
478 + "url": "https://avenueimmo.com",
479 + "listing_url": "https://avenueimmo.com/proprietes/",
480 + "coverage": "Agence indépendante (Brossard / Rive-Sud)",
481 + "connector": "avenue",
482 + "status": "actif",
483 + "type": "agence",
484 + "note": "Plateforme source.immo (API publique, config auto _configs.json). ~42 propriétés à vendre (2026-08-18). Généré par agences_source_immo.py."
485 + },
486 + {
487 + "id": "provad",
488 + "name": "Proulx Vadnais & Associés",
489 + "url": "https://provad.ca",
490 + "listing_url": "https://provad.ca/nos-proprietes/",
491 + "coverage": "Agence indépendante commerciale/industrielle (Laval, Rive-Nord)",
492 + "connector": "provad",
493 + "status": "actif",
494 + "type": "agence",
495 + "note": "Plateforme source.immo (API publique, config auto _configs.json). ~80 propriétés à vendre (2026-08-18). Généré par agences_source_immo.py."
496 + },
497 + {
498 + "id": "peladeau",
499 + "name": "Péladeau Agence Immobilière",
500 + "url": "https://www.epeladeau.com",
501 + "listing_url": "https://www.epeladeau.com/proprietes/",
502 + "coverage": "Agence indépendante",
503 + "connector": "peladeau",
504 + "status": "actif",
505 + "type": "agence",
506 + "note": "Plateforme source.immo (API publique, config auto _configs.json). ~47 propriétés à vendre (2026-08-18). Généré par agences_source_immo.py."
507 + },
508 + {
509 + "id": "ferri",
510 + "name": "Ferri Services Immobiliers",
511 + "url": "https://www.ferri.ca",
512 + "listing_url": "https://www.ferri.ca/proprietes/",
513 + "coverage": "Agence indépendante (Laval / Montréal)",
514 + "connector": "ferri",
515 + "status": "actif",
516 + "type": "agence",
517 + "note": "Plateforme source.immo (API publique, config auto _configs.json). ~22 propriétés à vendre (2026-08-18). Généré par agences_source_immo.py."
518 + },
519 + {
520 + "id": "si_ag_jga",
521 + "name": "JGA Équipe Commerciale (Royal LePage)",
522 + "url": "https://jgacommercial.com",
523 + "listing_url": "https://jgacommercial.com/proprietes/",
524 + "coverage": "Équipe commerciale/industrielle Royal LePage",
525 + "connector": "si_ag_jga",
526 + "status": "actif",
527 + "type": "équipe",
528 + "note": "Plateforme source.immo. ~64 fiches à vendre (2026-08-18). Équipe co-listée → si_ag_ (dédup Centris). Généré par agences_source_immo.py."
529 + },
530 + {
531 + "id": "si_ag_katiasamson",
532 + "name": "Katia Samson (RE/MAX L'Espace)",
533 + "url": "https://www.katiasamson.com",
534 + "listing_url": "https://www.katiasamson.com/proprietes/",
535 + "coverage": "Équipe RE/MAX L'Espace (Montréal)",
536 + "connector": "si_ag_katiasamson",
537 + "status": "actif",
538 + "type": "équipe",
539 + "note": "Plateforme source.immo. ~30 fiches à vendre (2026-08-18). Équipe co-listée (remax_ag_lespace couvert) → si_ag_ (dédup Centris). Généré par agences_source_immo.py."
441 540 }
442 541 ]
443 542 }
modified docs/connecteurs/INDEX.md +26 −17
@@ -1,10 +1,10 @@
1 1 # Immo-Ka — Connecteurs (documentation standardisée)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 −**92 connecteurs** enregistrés (auto-découverte `immoka/connectors/__init__.py`) : 41 connecteurs nommés (`data/sources.json`) + 4 familles dynamiques (RE/MAX sous-agences, Via Capitale, Century 21, source.immo).
5 +**101 connecteurs** enregistrés (auto-découverte `immoka/connectors/__init__.py`) : 50 connecteurs nommés (`data/sources.json`) + 4 familles dynamiques (RE/MAX sous-agences, Via Capitale, Century 21, source.immo).
6 6
7 −Base vivante `data/immoka.db` : 138 468 annonces, 122 797 actives, 77 668 visibles après dédup (45 129 masquées).
7 +Base vivante `data/immoka.db` : 145 724 annonces, 129 862 actives, 79 229 visibles après dédup (50 633 masquées).
8 8
9 9 ## Mécanismes transverses (tous connecteurs)
10 10
@@ -15,14 +15,14 @@ Base vivante `data/immoka.db` : 138 468 annonces, 122 797 actives, 77 668 visibl
15 15 sur plusieurs cycles, tout le parc finit enrichi.
16 16 - **Dédup Centris + adresse** (`immoka/db.py`) : les doublons inter-sources
17 17 (même n° Centris via les sous-agences, ou même adresse normalisée) sont
18 − marqués `dup_hidden=1` — 45 129 annonces masquées actuellement — et la
18 + marqués `dup_hidden=1` — 50 633 annonces masquées actuellement — et la
19 19 lecture filtre en `AND dup_hidden=0`.
20 20 - **Jointure rôle d'évaluation** (`immoka/vraiprix_local.py`) : appariement
21 21 local FTS par adresse contre `data/vraiprix.db` (3,7 M unités d'évaluation).
22 22 Remplit lat/lng manquants, l'estimation Vrai-Prix (P10-P90 + lien) et les
23 23 champs du rôle (année de construction, superficies, évaluations). Impact :
24 − **year_built rempli à 67 %** des annonces visibles, dont
25 − 71 % proviennent du rôle (`year_built_source: role`).
24 + **year_built rempli à 68 %** des annonces visibles, dont
25 + 31 % proviennent du rôle (`year_built_source: role`).
26 26 - **Historique — vagues du 2026-08-18** :
27 27 - `7911d58` Vague 1 : clé Algolia auto-extraite (Barnes), taxes/éval RE/MAX
28 28 (cache détail v4), specs Via Capitale, Kijiji étendu.
@@ -33,21 +33,21 @@ Base vivante `data/immoka.db` : 138 468 annonces, 122 797 actives, 77 668 visibl
33 33
34 34 | Famille | Fiche | Membres | Visibles |
35 35 |---|---|---|---|
36 −| Famille RE/MAX sous-agences | [famille-remax-ag](famille-remax-ag.md) | 50 | 3 349 |
37 −| Famille Via Capitale agences | [famille-via-ag](famille-via-ag.md) | 4 | 82 |
36 +| Famille RE/MAX sous-agences | [famille-remax-ag](famille-remax-ag.md) | 50 | 3 150 |
37 +| Famille Via Capitale agences | [famille-via-ag](famille-via-ag.md) | 4 | 50 |
38 38 | Famille Century 21 | [famille-c21-ag](famille-c21-ag.md) | 2 | 1 576 |
39 −| Famille source.immo | [famille-source-immo](famille-source-immo.md) | 6 | 1 877 |
39 +| Famille source.immo | [famille-source-immo](famille-source-immo.md) | 13 | 3 312 |
40 40
41 41 ## Connecteurs nommés
42 42
43 43 | id | Nom | Type | Statut | Visibles | Année (dont rôle) | Dernier sync | OK |
44 44 |---|---|---|---|---|---|---|---|
45 −| [`remax_quebec`](remax_quebec.md) | RE/MAX Québec | franchise | actif | 25 348 | 77.0 % | 2026-08-18 01:45 | ✅ |
45 +| [`remax_quebec`](remax_quebec.md) | RE/MAX Québec | franchise | actif | 25 348 | 82.8 % | 2026-08-18 05:11 | ✅ |
46 46 | [`duproprio`](duproprio.md) | DuProprio (sans courtier) | fsbo | actif | 7 393 | 79.3 % | 2026-08-18 02:37 | ✅ |
47 47 | [`kijiji`](kijiji.md) | Kijiji Québec | — | actif | 7 104 | 4.2 % | 2026-08-18 02:59 | ✅ |
48 48 | [`via_capitale`](via_capitale.md) | Via Capitale | franchise | actif | 5 153 | 68.9 % | 2026-08-18 00:27 | ✅ |
49 49 | [`sutton`](sutton.md) | Groupe Sutton Québec | franchise | actif | 4 515 | 65.4 % | 2026-08-18 02:17 | ✅ |
50 −| [`lespac`](lespac.md) | LesPAC Québec | — | actif | 2 720 | 57.5 % | 2026-08-18 03:10 | ✅ |
50 +| [`lespac`](lespac.md) | LesPAC Québec | — | actif | 2 756 | 57.9 % | 2026-08-18 03:10 | ✅ |
51 51 | [`proprio_direct`](proprio_direct.md) | Proprio Direct | agence | actif | 2 464 | 67.5 % | 2026-08-18 03:14 | ✅ |
52 52 | [`c21_ag_quebec`](c21_ag_quebec.md) | Century 21 Québec (All Quebec) | — | actif | 1 576 | 75.6 % | 2026-08-18 02:35 | ✅ |
53 53 | [`domicilia`](domicilia.md) | Domicilia Agence Immobilière | agence | actif | 1 445 | 73.4 % | 2026-08-18 02:27 | ✅ |
@@ -55,29 +55,38 @@ Base vivante `data/immoka.db` : 138 468 annonces, 122 797 actives, 77 668 visibl
55 55 | [`engel_volkers`](engel_volkers.md) | Engel & Völkers Montréal / Québec | luxe | actif | 1 228 | 69.9 % | 2026-08-18 02:37 | ✅ |
56 56 | [`ubee`](ubee.md) | Ubee | — | actif | 1 176 | 100.0 % | 2026-08-18 00:23 | ✅ |
57 57 | [`vendirect`](vendirect.md) | Vendirect | agence | actif | 1 170 | 79.4 % | 2026-08-18 00:23 | ✅ |
58 −| [`royal_lepage`](royal_lepage.md) | Royal LePage (Québec) | franchise | actif | 1 009 | 85.7 % | 2026-08-18 02:20 | ✅ |
58 +| [`si_ag_ciemcq`](si_ag_ciemcq.md) | Chambre immobilière Estrie–Mauricie–Centre-du-Québec (Mon-Toit) | chambre | actif | 1 169 | 62.8 % | 2026-08-18 05:56 | ✅ |
59 +| [`royal_lepage`](royal_lepage.md) | Royal LePage (Québec) | franchise | actif | 1 008 | 89.0 % | 2026-08-18 05:19 | ✅ |
59 60 | [`exp_ag_qc`](exp_ag_qc.md) | eXp Agence immobilière (Québec) | agence | actif | 888 | 55.6 % | 2026-08-18 02:40 | ✅ |
61 +| [`sothebys_quebec`](sothebys_quebec.md) | Sotheby's International Realty Québec | luxe | actif | 869 | 3.5 % | 2026-08-18 06:05 | ✅ |
60 62 | [`charisma_ag_qc`](charisma_ag_qc.md) | Les Immeubles Charisma | agence | actif | 696 | 81.2 % | 2026-08-18 02:37 | ✅ |
61 63 | [`kw_urbain`](kw_urbain.md) | Keller Williams Urbain | franchise | actif | 351 | 68.7 % | 2026-08-18 02:59 | ✅ |
62 64 | [`profusion`](profusion.md) | Profusion Immobilier (Christie's) | luxe | actif | 351 | 61.5 % | 2026-08-18 03:14 | ✅ |
65 +| [`realtor_ag_ca`](realtor_ag_ca.md) | Realtor.ca (MLS Québec) | agrégateur | actif | 343 | 0.0 % | 2026-08-18 06:06 | ✅ |
63 66 | [`barnes_quebec`](barnes_quebec.md) | BARNES Québec | luxe | actif | 336 | 81.5 % | 2026-08-18 02:35 | ✅ |
64 67 | [`kw_prestige`](kw_prestige.md) | Keller Williams Prestige | franchise | actif | 277 | 0.0 % | 2026-08-18 02:59 | ✅ |
65 −| [`si_ag_theagency`](si_ag_theagency.md) | The Agency Montréal | agence | actif | 245 | 88.6 % | 2026-08-18 02:27 | ✅ |
68 +| [`si_ag_theagency`](si_ag_theagency.md) | The Agency Montréal | agence | actif | 236 | 90.3 % | 2026-08-18 02:27 | ✅ |
66 69 | [`glmc_ag_qc`](glmc_ag_qc.md) | Les Immeubles GLMC | agence | actif | 176 | 36.4 % | 2026-08-18 02:40 | ✅ |
67 70 | [`kw_distinction`](kw_distinction.md) | Keller Williams Distinction | franchise | actif | 167 | 0.0 % | 2026-08-18 02:59 | ✅ |
68 71 | [`imcha_ag_qc`](imcha_ag_qc.md) | Les Immeubles Charlevoix | agence | actif | 107 | 0.0 % | 2026-08-18 02:40 | ✅ |
72 +| [`guidehabitation`](guidehabitation.md) | Guide Habitation (projets neufs) | répertoire | actif | 94 | 0.0 % | 2026-08-18 05:56 | ✅ |
69 73 | [`immodev`](immodev.md) | Immodev Agence Immobilière | agence | actif | 92 | 64.1 % | 2026-08-18 02:27 | ✅ |
70 74 | [`bhhs_ag_qc`](bhhs_ag_qc.md) | Berkshire Hathaway HomeServices Québec | franchise | actif | 91 | 86.8 % | 2026-08-18 02:35 | ✅ |
71 75 | [`realta`](realta.md) | Réalta Agence Immobilière | agence | actif | 82 | 80.5 % | 2026-08-18 02:27 | ✅ |
76 +| [`provad`](provad.md) | Proulx Vadnais & Associés | agence | actif | 80 | 41.2 % | 2026-08-18 05:56 | ✅ |
72 77 | [`image_ag_qc`](image_ag_qc.md) | Image, l'agence immobilière | agence | actif | 77 | 0.0 % | 2026-08-18 02:27 | ✅ |
73 78 | [`m_immobilier`](m_immobilier.md) | M Immobilier | luxe | actif | 67 | 85.1 % | 2026-08-18 03:13 | ✅ |
79 +| [`si_ag_jga`](si_ag_jga.md) | JGA Équipe Commerciale (Royal LePage) | équipe | actif | 59 | 28.8 % | 2026-08-18 05:56 | ✅ |
80 +| [`peladeau`](peladeau.md) | Péladeau Agence Immobilière | agence | actif | 47 | 83.0 % | 2026-08-18 05:56 | ✅ |
74 81 | [`contact_ag_qc`](contact_ag_qc.md) | Les Immeubles Contact | agence | actif | 43 | 83.7 % | 2026-08-18 02:40 | ✅ |
75 −| [`sothebys_quebec`](sothebys_quebec.md) | Sotheby's International Realty Québec | luxe | actif | 42 | 71.4 % | 2026-08-18 00:21 | ✅ |
76 −| [`via_ag_acces`](via_ag_acces.md) | Via Capitale Acces | franchise | actif | 31 | 96.8 % | 2026-08-18 00:27 | ✅ |
77 −| [`via_ag_select`](via_ag_select.md) | Via Capitale Select | franchise | actif | 17 | 100.0 % | 2026-08-18 00:28 | ✅ |
82 +| [`avenue`](avenue.md) | Avenue Immobilier | agence | actif | 42 | 95.2 % | 2026-08-18 05:56 | ✅ |
83 +| [`si_ag_katiasamson`](si_ag_katiasamson.md) | Katia Samson (RE/MAX L'Espace) | équipe | actif | 25 | 100.0 % | 2026-08-18 05:56 | ✅ |
84 +| [`ferri`](ferri.md) | Ferri Services Immobiliers | agence | actif | 22 | 95.5 % | 2026-08-18 05:56 | ✅ |
85 +| [`via_ag_select`](via_ag_select.md) | Via Capitale Select | franchise | actif | 13 | 100.0 % | 2026-08-18 00:28 | ✅ |
78 86 | [`gaillardetz`](gaillardetz.md) | Gaillardetz Agence Immobilière | agence | actif | 13 | 92.3 % | 2026-08-18 02:27 | ✅ |
79 −| [`via_ag_elite`](via_ag_elite.md) | Via Capitale Elite | franchise | actif | 11 | 81.8 % | 2026-08-18 00:28 | ✅ |
87 +| [`via_ag_elite`](via_ag_elite.md) | Via Capitale Elite | franchise | actif | 10 | 80.0 % | 2026-08-18 00:28 | ✅ |
80 88 | [`expert_immobilier_pm`](expert_immobilier_pm.md) | L'Expert Immobilier P.M. | agence | actif | 9 | 88.9 % | 2026-08-18 02:40 | ✅ |
89 +| [`via_ag_acces`](via_ag_acces.md) | Via Capitale Acces | franchise | actif | 7 | 100.0 % | 2026-08-18 00:27 | ✅ |
81 90 | [`century21`](century21.md) | Century 21 (Québec) | franchise | actif | 0 | — | — | — |
82 91 | [`via_ag_dumontroyal`](via_ag_dumontroyal.md) | Via Capitale Dumontroyal | franchise | inactif | 0 | — | 2026-08-18 00:27 | ✅ |
83 92 | [`c21_ag_vision`](c21_ag_vision.md) | Century 21 Vision (Outaouais) | — | actif | 0 | — | 2026-08-18 02:35 | ✅ |
added docs/connecteurs/avenue.md +59 −0
@@ -0,0 +1,59 @@
1 +# Avenue Immobilier (`avenue`)
2 +
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 +
5 +## Registre (`data/sources.json`)
6 +
7 +- **Site** : https://avenueimmo.com
8 +- **Recherche** : https://avenueimmo.com/proprietes/
9 +- **Couverture** : Agence indépendante (Brossard / Rive-Sud)
10 +- **Type** : agence
11 +- **Statut** : actif
12 +
13 +> Plateforme source.immo (API publique, config auto _configs.json). ~42 propriétés à vendre (2026-08-18). Généré par agences_source_immo.py.
14 +
15 +## Mécanique (introspection du code)
16 +
17 +- Module : `immoka/connectors/agences_source_immo.py` — classe `AgenceSIAvenue`
18 +- Délai entre requêtes : 0.25 s ; cache détail BD : non
19 +
20 +**En-tête du module :**
21 +
22 +> Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
23 +> Auteur : Simon-Pierre Boucher — contact@spboucher.ai
24 +> connectors/agences_source_immo.py : agences INDÉPENDANTES sur la plateforme
25 +> source.immo (plugin WordPress). Beaucoup de petites/moyennes agences QC
26 +> l'utilisent (liste sur source.immo). Chacune expose sa config publique à
27 +> /wp-content/uploads/_sourceimmo/_configs.json → on lit l'API publique
28 +> api-v1.source.immo (voir SourceImmoConnector). Ce sont des agences
29 +> autonomes : leurs inscriptions (leur propre n° Centris) sont ADDITIVES —
30 +> pas de sous-agence d'une bannière déjà couverte → source_id normal (pas _ag_).
31 +> EXCEPTION : les équipes/agences dont une partie des inscriptions est
32 +> co-listée avec une bannière couverte (co-inscription Centris) portent un id
33 +> « si_ag_<slug> » : la dédup Centris (db.refresh_dedup, sources %_ag_%)
34 +> masque leurs doublons tout en gardant leurs fiches uniques visibles.
35 +> Un connecteur par agence est généré depuis data/source_immo_agencies.json.
36 +
37 +## Volumétrie & complétude (BD live)
38 +
39 +| Indicateur | Valeur |
40 +|---|---|
41 +| Annonces en base (toutes) | 42 |
42 +| Actives | 42 |
43 +| Visibles (après dédup) | 42 |
44 +| Masquées par la dédup | 0 |
45 +| GPS (lat/lng) | 100.0 % |
46 +| Photos | 100.0 % |
47 +| Prix | 100.0 % |
48 +| CAC (chambres) | 88.1 % |
49 +| SDB (salles de bains) | 88.1 % |
50 +| Année de construction | 95.2 % (dont rôle : 0.0 %) |
51 +| Taxes / évaluation municipale | 90.5 % |
52 +| Estimation Vrai-Prix (rôle) | 0.0 % |
53 +
54 +## Synchronisation
55 +
56 +- **Dernier sync** : 2026-08-18 05:56 — trouvé 42, +42 / ~0 / -0 — OK
57 +- **Erreurs récentes** : 0 sur les 1 derniers syncs
58 +
59 +Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
modified docs/connecteurs/barnes_quebec.md +1 −1
@@ -1,6 +1,6 @@
1 1 # BARNES Québec (`barnes_quebec`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/bhhs_ag_qc.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Berkshire Hathaway HomeServices Québec (`bhhs_ag_qc`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/c21_ag_quebec.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Century 21 Québec (All Quebec) (`c21_ag_quebec`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/c21_ag_vision.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Century 21 Vision (Outaouais) (`c21_ag_vision`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/century21.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Century 21 (Québec) (`century21`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/charisma_ag_qc.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Les Immeubles Charisma (`charisma_ag_qc`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/cio_ag_outaouais.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Chambre immobilière de l'Outaouais (`cio_ag_outaouais`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/coldwell_banker.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Coldwell Banker Québec (`coldwell_banker`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/contact_ag_qc.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Les Immeubles Contact (`contact_ag_qc`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/domicilia.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Domicilia Agence Immobilière (`domicilia`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/duproprio.md +1 −1
@@ -1,6 +1,6 @@
1 1 # DuProprio (sans courtier) (`duproprio`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/engel_volkers.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Engel & Völkers Montréal / Québec (`engel_volkers`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/exp_ag_qc.md +1 −1
@@ -1,6 +1,6 @@
1 1 # eXp Agence immobilière (Québec) (`exp_ag_qc`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/expert_immobilier_pm.md +1 −1
@@ -1,6 +1,6 @@
1 1 # L'Expert Immobilier P.M. (`expert_immobilier_pm`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/famille-c21-ag.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Famille Century 21 (`c21_ag_*`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 Connecteurs par compte Century 21, générés depuis `data/century21_agencies.json` (plateforme source.immo).
6 6
modified docs/connecteurs/famille-remax-ag.md +55 −55
@@ -1,6 +1,6 @@
1 1 # Famille RE/MAX sous-agences (`remax_ag_*`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 Un connecteur par sous-agence RE/MAX (sites propres, indépendants du portail central), généré dynamiquement depuis `data/remax_agencies.json`.
6 6
@@ -36,56 +36,56 @@ Budgets env : `IMMOKA_AGENCE_DETAIL_LIMIT` (défaut 0)
36 36
37 37 | source_id | Domaine | Plateforme | Visibles | Actives | Masquées dédup | Dernier sync | OK |
38 38 |---|---|---|---|---|---|---|---|
39 −| `remax_ag_1erchoix` | www.remax1erchoix.com | nos-proprietes | 211 | 1 064 | 853 | 2026-08-18 00:15 | ✅ |
40 −| `remax_ag_2000` | www.remax-2000.com | centris-other | 72 | 735 | 663 | 2026-08-18 00:15 | ✅ |
41 −| `remax_ag_2001` | www.remax2001.com | nos-proprietes | 37 | 366 | 329 | 2026-08-18 00:15 | ✅ |
42 −| `remax_ag_3000` | remax3000.com | nos-proprietes | 52 | 782 | 730 | 2026-08-18 00:15 | ✅ |
43 −| `remax_ag_acces` | www.remaxacces.com | nos-proprietes | 140 | 622 | 482 | 2026-08-18 00:15 | ✅ |
44 −| `remax_ag_action` | remax-action.ca | nos-proprietes | 85 | 1 361 | 1 276 | 2026-08-18 00:15 | ✅ |
45 −| `remax_ag_alliance` | www.remax-alliance.ca | nos-proprietes | 183 | 1 258 | 1 075 | 2026-08-18 00:15 | ✅ |
46 −| `remax_ag_avantages` | www.remax-avantages.com | nos-proprietes | 177 | 772 | 595 | 2026-08-18 00:15 | ✅ |
47 −| `remax_ag_avanttout` | www.remaxavanttout.com | nos-proprietes | 37 | 404 | 367 | 2026-08-18 00:15 | ✅ |
48 −| `remax_ag_cite` | remax-cite.com | nos-proprietes | 12 | 116 | 104 | 2026-08-18 00:15 | ✅ |
49 −| `remax_ag_crystal` | remaxcrystal.com | nos-proprietes | 168 | 1 305 | 1 137 | 2026-08-18 00:15 | ✅ |
50 −| `remax_ag_d_ici` | remaxdici.com | nos-proprietes | 131 | 871 | 740 | 2026-08-18 00:15 | ✅ |
51 −| `remax_ag_dabord` | www.remax-dabord.com | centris-other | 126 | 796 | 670 | 2026-08-18 00:15 | ✅ |
52 −| `remax_ag_defi` | remax-defi1996.com | nos-proprietes | 27 | 348 | 321 | 2026-08-18 00:15 | ✅ |
53 −| `remax_ag_defrancheville` | remaxdefrancheville.com | nos-proprietes | 168 | 1 461 | 1 293 | 2026-08-18 00:15 | ✅ |
54 −| `remax_ag_direct` | remax-direct.com | nos-proprietes | 28 | 1 068 | 1 040 | 2026-08-18 00:15 | ✅ |
55 −| `remax_ag_distinction` | remaxdistinction.com | nos-proprietes | 27 | 149 | 122 | 2026-08-18 00:15 | ✅ |
56 −| `remax_ag_ducartier` | www.remaxducartier.com | centris-other | 237 | 1 860 | 1 623 | 2026-08-18 00:15 | ✅ |
57 −| `remax_ag_ducartieractif` | www.remaxactif.com | centris-other | 25 | 119 | 94 | 2026-08-18 00:15 | ✅ |
58 −| `remax_ag_ducartierbonjour` | remaxbonjour.com | centris-other | 120 | 1 548 | 1 428 | 2026-08-18 00:15 | ✅ |
59 −| `remax_ag_dynamique` | remaxdynamique.com | nos-proprietes | 3 | 151 | 148 | 2026-08-18 00:15 | ✅ |
60 −| `remax_ag_dynastie` | remax-dynastie.com | centris-other | 9 | 240 | 231 | 2026-08-18 00:15 | ✅ |
61 −| `remax_ag_elegance` | remax-elegance.ca | nos-proprietes | 13 | 87 | 74 | 2026-08-18 00:15 | ✅ |
62 −| `remax_ag_elite` | remax-elite.ca | nos-proprietes | 83 | 856 | 773 | 2026-08-18 00:15 | ✅ |
63 −| `remax_ag_energie` | remax-energie.com | nos-proprietes | 8 | 173 | 165 | 2026-08-18 00:15 | ✅ |
64 −| `remax_ag_evolution` | remax-evolution.com | centris-other | 39 | 494 | 455 | 2026-08-18 00:15 | ✅ |
65 −| `remax_ag_excellence` | remax-excellence.ca | nos-proprietes | 6 | 286 | 280 | 2026-08-18 00:15 | ✅ |
66 −| `remax_ag_extra` | remax-extra.ca | centris-other | 122 | 672 | 550 | 2026-08-18 00:15 | ✅ |
67 −| `remax_ag_fortindelage` | remaxfortindelage.com | nos-proprietes | 67 | 408 | 341 | 2026-08-18 00:15 | ✅ |
68 −| `remax_ag_futur` | remax-futur.ca | centris-other | 4 | 197 | 193 | 2026-08-18 00:15 | ✅ |
69 −| `remax_ag_harmonie` | remaxharmonie.com | nos-proprietes | 58 | 376 | 318 | 2026-08-18 00:15 | ✅ |
70 −| `remax_ag_harricana` | remax-harricana.com | nos-proprietes | 6 | 155 | 149 | 2026-08-18 00:16 | ✅ |
71 −| `remax_ag_horizon` | remax-horizon.ca | nos-proprietes | 94 | 466 | 372 | 2026-08-18 00:16 | ✅ |
72 −| `remax_ag_imagine` | remax-imagineprivilege.com | nos-proprietes | 64 | 457 | 393 | 2026-08-18 00:16 | ✅ |
73 −| `remax_ag_immobilia` | remaximmobilia.ca | nos-proprietes | 0 | 7 | 7 | 2026-08-18 00:16 | ✅ |
74 −| `remax_ag_immobilierplus` | remax-immobilierplus.com | nos-proprietes | 5 | 56 | 51 | 2026-08-18 00:16 | ✅ |
75 −| `remax_ag_infinite` | remax-infinite.com | nos-proprietes | 2 | 61 | 59 | 2026-08-18 00:16 | ✅ |
76 −| `remax_ag_invest` | remaxinvest.ca | nos-proprietes | 0 | 1 | 1 | 2026-08-18 00:16 | ✅ |
77 −| `remax_ag_lespace` | www.remaxlespace.com | nos-proprietes | 41 | 472 | 431 | 2026-08-18 00:16 | ✅ |
78 −| `remax_ag_lespace_commercial` | remaxlespace.com | nos-proprietes | 0 | 472 | 472 | 2026-08-18 00:16 | ✅ |
79 −| `remax_ag_performance` | remaxperformance.net | nos-proprietes | 20 | 204 | 184 | 2026-08-18 00:16 | ✅ |
80 −| `remax_ag_platine` | www.remax-platine.com | nos-proprietes | 107 | 1 313 | 1 206 | 2026-08-18 00:16 | ✅ |
81 −| `remax_ag_plus` | remaxplus.ca | nos-proprietes | 71 | 349 | 278 | 2026-08-18 00:16 | ✅ |
82 −| `remax_ag_prestige` | remaxprestige.ca | nos-proprietes | 94 | 482 | 388 | 2026-08-18 00:16 | ✅ |
83 −| `remax_ag_privilege` | remax-imagineprivilege.com | nos-proprietes | 0 | 457 | 457 | 2026-08-18 00:16 | ✅ |
84 −| `remax_ag_professionnel` | www.remax-professionnel.com | nos-proprietes | 81 | 729 | 648 | 2026-08-18 00:16 | ✅ |
85 −| `remax_ag_renaissance` | remax-renaissance.ca | nos-proprietes | 36 | 302 | 266 | 2026-08-18 00:16 | ✅ |
86 −| `remax_ag_royaljordan` | remax-royaljordan.com | nos-proprietes | 134 | 1 307 | 1 173 | 2026-08-18 00:16 | ✅ |
87 −| `remax_ag_signature` | remaxsignature.ca | nos-proprietes | 88 | 569 | 481 | 2026-08-18 00:16 | ✅ |
88 −| `remax_ag_vision` | remaxvision.ca | nos-proprietes | 31 | 1 074 | 1 043 | 2026-08-18 00:16 | ✅ |
39 +| `remax_ag_1erchoix` | www.remax1erchoix.com | nos-proprietes | 203 | 1 056 | 853 | 2026-08-18 03:37 | ✅ |
40 +| `remax_ag_2000` | www.remax-2000.com | centris-other | 65 | 728 | 663 | 2026-08-18 03:37 | ✅ |
41 +| `remax_ag_2001` | www.remax2001.com | nos-proprietes | 37 | 366 | 329 | 2026-08-18 03:37 | ✅ |
42 +| `remax_ag_3000` | remax3000.com | nos-proprietes | 46 | 775 | 729 | 2026-08-18 03:37 | ✅ |
43 +| `remax_ag_acces` | www.remaxacces.com | nos-proprietes | 135 | 617 | 482 | 2026-08-18 03:37 | ✅ |
44 +| `remax_ag_action` | remax-action.ca | nos-proprietes | 79 | 1 355 | 1 276 | 2026-08-18 03:37 | ✅ |
45 +| `remax_ag_alliance` | www.remax-alliance.ca | nos-proprietes | 170 | 1 243 | 1 073 | 2026-08-18 03:37 | ✅ |
46 +| `remax_ag_avantages` | www.remax-avantages.com | nos-proprietes | 169 | 765 | 596 | 2026-08-18 03:37 | ✅ |
47 +| `remax_ag_avanttout` | www.remaxavanttout.com | nos-proprietes | 35 | 402 | 367 | 2026-08-18 03:37 | ✅ |
48 +| `remax_ag_cite` | remax-cite.com | nos-proprietes | 12 | 116 | 104 | 2026-08-18 03:37 | ✅ |
49 +| `remax_ag_crystal` | remaxcrystal.com | nos-proprietes | 157 | 1 294 | 1 137 | 2026-08-18 03:37 | ✅ |
50 +| `remax_ag_d_ici` | remaxdici.com | nos-proprietes | 126 | 866 | 740 | 2026-08-18 03:37 | ✅ |
51 +| `remax_ag_dabord` | www.remax-dabord.com | centris-other | 116 | 786 | 670 | 2026-08-18 03:37 | ✅ |
52 +| `remax_ag_defi` | remax-defi1996.com | nos-proprietes | 26 | 347 | 321 | 2026-08-18 03:37 | ✅ |
53 +| `remax_ag_defrancheville` | remaxdefrancheville.com | nos-proprietes | 162 | 1 457 | 1 295 | 2026-08-18 03:37 | ✅ |
54 +| `remax_ag_direct` | remax-direct.com | nos-proprietes | 26 | 1 057 | 1 031 | 2026-08-18 03:37 | ✅ |
55 +| `remax_ag_distinction` | remaxdistinction.com | nos-proprietes | 26 | 148 | 122 | 2026-08-18 03:37 | ✅ |
56 +| `remax_ag_ducartier` | www.remaxducartier.com | centris-other | 215 | 1 838 | 1 623 | 2026-08-18 03:37 | ✅ |
57 +| `remax_ag_ducartieractif` | www.remaxactif.com | centris-other | 25 | 119 | 94 | 2026-08-18 03:37 | ✅ |
58 +| `remax_ag_ducartierbonjour` | remaxbonjour.com | centris-other | 110 | 1 538 | 1 428 | 2026-08-18 03:37 | ✅ |
59 +| `remax_ag_dynamique` | remaxdynamique.com | nos-proprietes | 2 | 150 | 148 | 2026-08-18 03:37 | ✅ |
60 +| `remax_ag_dynastie` | remax-dynastie.com | centris-other | 5 | 236 | 231 | 2026-08-18 03:37 | ✅ |
61 +| `remax_ag_elegance` | remax-elegance.ca | nos-proprietes | 12 | 86 | 74 | 2026-08-18 03:37 | ✅ |
62 +| `remax_ag_elite` | remax-elite.ca | nos-proprietes | 78 | 851 | 773 | 2026-08-18 03:37 | ✅ |
63 +| `remax_ag_energie` | remax-energie.com | nos-proprietes | 8 | 173 | 165 | 2026-08-18 03:37 | ✅ |
64 +| `remax_ag_evolution` | remax-evolution.com | centris-other | 39 | 494 | 455 | 2026-08-18 03:37 | ✅ |
65 +| `remax_ag_excellence` | remax-excellence.ca | nos-proprietes | 1 | 281 | 280 | 2026-08-18 03:37 | ✅ |
66 +| `remax_ag_extra` | remax-extra.ca | centris-other | 122 | 672 | 550 | 2026-08-18 03:37 | ✅ |
67 +| `remax_ag_fortindelage` | remaxfortindelage.com | nos-proprietes | 65 | 406 | 341 | 2026-08-18 03:37 | ✅ |
68 +| `remax_ag_futur` | remax-futur.ca | centris-other | 3 | 195 | 192 | 2026-08-18 03:37 | ✅ |
69 +| `remax_ag_harmonie` | remaxharmonie.com | nos-proprietes | 55 | 373 | 318 | 2026-08-18 03:37 | ✅ |
70 +| `remax_ag_harricana` | remax-harricana.com | nos-proprietes | 6 | 155 | 149 | 2026-08-18 03:37 | ✅ |
71 +| `remax_ag_horizon` | remax-horizon.ca | nos-proprietes | 93 | 463 | 370 | 2026-08-18 03:37 | ✅ |
72 +| `remax_ag_imagine` | remax-imagineprivilege.com | nos-proprietes | 59 | 452 | 393 | 2026-08-18 03:37 | ✅ |
73 +| `remax_ag_immobilia` | remaximmobilia.ca | nos-proprietes | 0 | 7 | 7 | 2026-08-18 03:38 | ✅ |
74 +| `remax_ag_immobilierplus` | remax-immobilierplus.com | nos-proprietes | 5 | 56 | 51 | 2026-08-18 03:38 | ✅ |
75 +| `remax_ag_infinite` | remax-infinite.com | nos-proprietes | 0 | 59 | 59 | 2026-08-18 03:38 | ✅ |
76 +| `remax_ag_invest` | remaxinvest.ca | nos-proprietes | 0 | 1 | 1 | 2026-08-18 03:38 | ✅ |
77 +| `remax_ag_lespace` | www.remaxlespace.com | nos-proprietes | 38 | 469 | 431 | 2026-08-18 03:38 | ✅ |
78 +| `remax_ag_lespace_commercial` | remaxlespace.com | nos-proprietes | 0 | 469 | 469 | 2026-08-18 03:38 | ✅ |
79 +| `remax_ag_performance` | remaxperformance.net | nos-proprietes | 19 | 203 | 184 | 2026-08-18 03:38 | ✅ |
80 +| `remax_ag_platine` | www.remax-platine.com | nos-proprietes | 95 | 1 303 | 1 208 | 2026-08-18 03:38 | ✅ |
81 +| `remax_ag_plus` | remaxplus.ca | nos-proprietes | 70 | 348 | 278 | 2026-08-18 03:38 | ✅ |
82 +| `remax_ag_prestige` | remaxprestige.ca | nos-proprietes | 88 | 476 | 388 | 2026-08-18 03:38 | ✅ |
83 +| `remax_ag_privilege` | remax-imagineprivilege.com | nos-proprietes | 0 | 452 | 452 | 2026-08-18 03:38 | ✅ |
84 +| `remax_ag_professionnel` | www.remax-professionnel.com | nos-proprietes | 74 | 722 | 648 | 2026-08-18 03:38 | ✅ |
85 +| `remax_ag_renaissance` | remax-renaissance.ca | nos-proprietes | 34 | 300 | 266 | 2026-08-18 03:38 | ✅ |
86 +| `remax_ag_royaljordan` | remax-royaljordan.com | nos-proprietes | 130 | 1 303 | 1 173 | 2026-08-18 03:38 | ✅ |
87 +| `remax_ag_signature` | remaxsignature.ca | nos-proprietes | 80 | 561 | 481 | 2026-08-18 03:38 | ✅ |
88 +| `remax_ag_vision` | remaxvision.ca | nos-proprietes | 29 | 1 067 | 1 038 | 2026-08-18 03:38 | ✅ |
89 89
90 90 Entrées du registre sans connecteur instancié (2) : `remax-pro-commercial.ca`, `nancyforlini.com`
91 91
@@ -94,10 +94,10 @@ Entrées du registre sans connecteur instancié (2) : `remax-pro-commercial.ca`,
94 94 | Indicateur | Valeur |
95 95 |---|---|
96 96 | Annonces en base (toutes) | 31 174 |
97 −| Actives | 29 878 |
98 −| Visibles (après dédup) | 3 349 |
99 −| Masquées par la dédup | 26 529 |
100 −| GPS (lat/lng) | 96.8 % |
97 +| Actives | 29 656 |
98 +| Visibles (après dédup) | 3 150 |
99 +| Masquées par la dédup | 26 506 |
100 +| GPS (lat/lng) | 97.1 % |
101 101 | Photos | 0.0 % |
102 102 | Prix | 0.0 % |
103 103 | CAC (chambres) | 7.9 % |
modified docs/connecteurs/famille-source-immo.md +21 −14
@@ -1,11 +1,11 @@
1 1 # Famille source.immo (agences indépendantes)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 Agences indépendantes servies par la plateforme source.immo (comptes/API dans `data/source_immo_agencies.json`).
6 6
7 −- Registre : `data/source_immo_agencies.json` — **6 entrées**
8 −- Connecteurs instanciés : **6**
7 +- Registre : `data/source_immo_agencies.json` — **13 entrées**
8 +- Connecteurs instanciés : **13**
9 9 - Module : `immoka/connectors/agences_source_immo.py`
10 10
11 11 **En-tête du module :**
@@ -29,29 +29,36 @@ Agences indépendantes servies par la plateforme source.immo (comptes/API dans `
29 29
30 30 | source_id | Domaine | Plateforme | Visibles | Actives | Masquées dédup | Dernier sync | OK |
31 31 |---|---|---|---|---|---|---|---|
32 +| [`avenue`](avenue.md) | — | source.immo | 42 | 42 | 0 | 2026-08-18 05:56 | ✅ |
32 33 | [`domicilia`](domicilia.md) | — | source.immo | 1 445 | 1 445 | 0 | 2026-08-18 02:27 | ✅ |
34 +| [`ferri`](ferri.md) | — | source.immo | 22 | 22 | 0 | 2026-08-18 05:56 | ✅ |
33 35 | [`gaillardetz`](gaillardetz.md) | — | source.immo | 13 | 13 | 0 | 2026-08-18 02:27 | ✅ |
34 36 | [`immodev`](immodev.md) | — | source.immo | 92 | 92 | 0 | 2026-08-18 02:27 | ✅ |
35 37 | [`niddamour`](niddamour.md) | — | source.immo | 0 | 0 | 0 | 2026-08-18 02:27 | ✅ |
38 +| [`peladeau`](peladeau.md) | — | source.immo | 47 | 47 | 0 | 2026-08-18 05:56 | ✅ |
39 +| [`provad`](provad.md) | — | source.immo | 80 | 80 | 0 | 2026-08-18 05:56 | ✅ |
36 40 | [`realta`](realta.md) | — | source.immo | 82 | 82 | 0 | 2026-08-18 02:27 | ✅ |
37 −| [`si_ag_theagency`](si_ag_theagency.md) | — | source.immo | 245 | 304 | 59 | 2026-08-18 02:27 | ✅ |
41 +| [`si_ag_ciemcq`](si_ag_ciemcq.md) | — | source.immo | 1 169 | 3 920 | 2 751 | 2026-08-18 05:56 | ✅ |
42 +| [`si_ag_jga`](si_ag_jga.md) | — | source.immo | 59 | 64 | 5 | 2026-08-18 05:56 | ✅ |
43 +| [`si_ag_katiasamson`](si_ag_katiasamson.md) | — | source.immo | 25 | 30 | 5 | 2026-08-18 05:56 | ✅ |
44 +| [`si_ag_theagency`](si_ag_theagency.md) | — | source.immo | 236 | 304 | 68 | 2026-08-18 02:27 | ✅ |
38 45
39 −Entrées du registre sans connecteur instancié (6) : `www.realta.ca`, `www.immodev.ca`, `www.gaillardetz.ca`, `www.domicilia.com`, `www.niddamour.ca`, `theagencymontreal.com`
46 +Entrées du registre sans connecteur instancié (13) : `www.realta.ca`, `www.immodev.ca`, `www.gaillardetz.ca`, `www.domicilia.com`, `www.niddamour.ca`, `theagencymontreal.com`, `www.mon-toit.net`, `avenueimmo.com`, `provad.ca`, `www.epeladeau.com`, `www.ferri.ca`, `jgacommercial.com`, `www.katiasamson.com`
40 47
41 48 ## Volumétrie & complétude agrégées (famille, BD live)
42 49
43 50 | Indicateur | Valeur |
44 51 |---|---|
45 −| Annonces en base (toutes) | 1 984 |
46 −| Actives | 1 936 |
47 −| Visibles (après dédup) | 1 877 |
48 −| Masquées par la dédup | 59 |
52 +| Annonces en base (toutes) | 6 189 |
53 +| Actives | 6 141 |
54 +| Visibles (après dédup) | 3 312 |
55 +| Masquées par la dédup | 2 829 |
49 56 | GPS (lat/lng) | 99.9 % |
50 57 | Photos | 100.0 % |
51 58 | Prix | 100.0 % |
52 −| CAC (chambres) | 66.3 % |
53 −| SDB (salles de bains) | 64.6 % |
54 −| Année de construction | 75.4 % (dont rôle : 6.6 %) |
55 −| Taxes / évaluation municipale | 89.3 % |
56 −| Estimation Vrai-Prix (rôle) | 100.0 % |
59 +| CAC (chambres) | 65.0 % |
60 +| SDB (salles de bains) | 61.6 % |
61 +| Année de construction | 70.0 % (dont rôle : 4.0 %) |
62 +| Taxes / évaluation municipale | 86.1 % |
63 +| Estimation Vrai-Prix (rôle) | 56.4 % |
57 64
modified docs/connecteurs/famille-via-ag.md +11 −11
@@ -1,6 +1,6 @@
1 1 # Famille Via Capitale agences (`via_ag_*`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 Connecteurs par bannière Via Capitale, générés depuis `data/via_capitale_agencies.json` (comptes API source.immo par agence).
6 6
@@ -28,10 +28,10 @@ Connecteurs par bannière Via Capitale, générés depuis `data/via_capitale_age
28 28
29 29 | source_id | Domaine | Plateforme | Visibles | Actives | Masquées dédup | Dernier sync | OK |
30 30 |---|---|---|---|---|---|---|---|
31 −| [`via_ag_acces`](via_ag_acces.md) | — | source.immo | 31 | 181 | 150 | 2026-08-18 00:27 | ✅ |
32 −| [`via_ag_elite`](via_ag_elite.md) | — | source.immo | 11 | 319 | 308 | 2026-08-18 00:28 | ✅ |
33 −| `via_ag_partenaires` | — | source.immo | 23 | 444 | 421 | 2026-08-18 00:28 | ✅ |
34 −| [`via_ag_select`](via_ag_select.md) | — | source.immo | 17 | 580 | 563 | 2026-08-18 00:28 | ✅ |
31 +| [`via_ag_acces`](via_ag_acces.md) | — | source.immo | 7 | 181 | 174 | 2026-08-18 00:27 | ✅ |
32 +| [`via_ag_elite`](via_ag_elite.md) | — | source.immo | 10 | 319 | 309 | 2026-08-18 00:28 | ✅ |
33 +| `via_ag_partenaires` | — | source.immo | 20 | 444 | 424 | 2026-08-18 00:28 | ✅ |
34 +| [`via_ag_select`](via_ag_select.md) | — | source.immo | 13 | 580 | 567 | 2026-08-18 00:28 | ✅ |
35 35
36 36 Entrées du registre sans connecteur instancié (5) : `viacapitaleacces.com`, `viacapitaledumontroyal.com`, `viacapitaleelite.immo`, `viacapitalepartenaires.com`, `viacapitaleselect.com`
37 37
@@ -41,14 +41,14 @@ Entrées du registre sans connecteur instancié (5) : `viacapitaleacces.com`, `v
41 41 |---|---|
42 42 | Annonces en base (toutes) | 1 580 |
43 43 | Actives | 1 524 |
44 −| Visibles (après dédup) | 82 |
45 −| Masquées par la dédup | 1 442 |
44 +| Visibles (après dédup) | 50 |
45 +| Masquées par la dédup | 1 474 |
46 46 | GPS (lat/lng) | 100.0 % |
47 47 | Photos | 100.0 % |
48 48 | Prix | 100.0 % |
49 −| CAC (chambres) | 67.1 % |
50 −| SDB (salles de bains) | 62.2 % |
51 −| Année de construction | 93.9 % (dont rôle : 10.4 %) |
52 −| Taxes / évaluation municipale | 89.0 % |
49 +| CAC (chambres) | 54.0 % |
50 +| SDB (salles de bains) | 50.0 % |
51 +| Année de construction | 92.0 % (dont rôle : 8.7 %) |
52 +| Taxes / évaluation municipale | 90.0 % |
53 53 | Estimation Vrai-Prix (rôle) | 100.0 % |
54 54
added docs/connecteurs/ferri.md +59 −0
@@ -0,0 +1,59 @@
1 +# Ferri Services Immobiliers (`ferri`)
2 +
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 +
5 +## Registre (`data/sources.json`)
6 +
7 +- **Site** : https://www.ferri.ca
8 +- **Recherche** : https://www.ferri.ca/proprietes/
9 +- **Couverture** : Agence indépendante (Laval / Montréal)
10 +- **Type** : agence
11 +- **Statut** : actif
12 +
13 +> Plateforme source.immo (API publique, config auto _configs.json). ~22 propriétés à vendre (2026-08-18). Généré par agences_source_immo.py.
14 +
15 +## Mécanique (introspection du code)
16 +
17 +- Module : `immoka/connectors/agences_source_immo.py` — classe `AgenceSIFerri`
18 +- Délai entre requêtes : 0.25 s ; cache détail BD : non
19 +
20 +**En-tête du module :**
21 +
22 +> Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
23 +> Auteur : Simon-Pierre Boucher — contact@spboucher.ai
24 +> connectors/agences_source_immo.py : agences INDÉPENDANTES sur la plateforme
25 +> source.immo (plugin WordPress). Beaucoup de petites/moyennes agences QC
26 +> l'utilisent (liste sur source.immo). Chacune expose sa config publique à
27 +> /wp-content/uploads/_sourceimmo/_configs.json → on lit l'API publique
28 +> api-v1.source.immo (voir SourceImmoConnector). Ce sont des agences
29 +> autonomes : leurs inscriptions (leur propre n° Centris) sont ADDITIVES —
30 +> pas de sous-agence d'une bannière déjà couverte → source_id normal (pas _ag_).
31 +> EXCEPTION : les équipes/agences dont une partie des inscriptions est
32 +> co-listée avec une bannière couverte (co-inscription Centris) portent un id
33 +> « si_ag_<slug> » : la dédup Centris (db.refresh_dedup, sources %_ag_%)
34 +> masque leurs doublons tout en gardant leurs fiches uniques visibles.
35 +> Un connecteur par agence est généré depuis data/source_immo_agencies.json.
36 +
37 +## Volumétrie & complétude (BD live)
38 +
39 +| Indicateur | Valeur |
40 +|---|---|
41 +| Annonces en base (toutes) | 22 |
42 +| Actives | 22 |
43 +| Visibles (après dédup) | 22 |
44 +| Masquées par la dédup | 0 |
45 +| GPS (lat/lng) | 100.0 % |
46 +| Photos | 100.0 % |
47 +| Prix | 100.0 % |
48 +| CAC (chambres) | 95.5 % |
49 +| SDB (salles de bains) | 95.5 % |
50 +| Année de construction | 95.5 % (dont rôle : 0.0 %) |
51 +| Taxes / évaluation municipale | 100.0 % |
52 +| Estimation Vrai-Prix (rôle) | 0.0 % |
53 +
54 +## Synchronisation
55 +
56 +- **Dernier sync** : 2026-08-18 05:56 — trouvé 22, +22 / ~0 / -0 — OK
57 +- **Erreurs récentes** : 0 sur les 1 derniers syncs
58 +
59 +Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
modified docs/connecteurs/gaillardetz.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Gaillardetz Agence Immobilière (`gaillardetz`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/glmc_ag_qc.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Les Immeubles GLMC (`glmc_ag_qc`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
added docs/connecteurs/guidehabitation.md +56 −0
@@ -0,0 +1,56 @@
1 +# Guide Habitation (projets neufs) (`guidehabitation`)
2 +
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 +
5 +## Registre (`data/sources.json`)
6 +
7 +- **Site** : https://www.guidehabitation.ca
8 +- **Recherche** : https://www.guidehabitation.ca/fr/projets-immobiliers/montreal/
9 +- **Couverture** : Québec habité (9 régions) — projets neufs des promoteurs (condos et maisons neuves à vendre)
10 +- **Type** : répertoire
11 +- **Statut** : actif
12 +
13 +> Répertoire de référence des projets neufs. Pages région /fr/projets-immobiliers/{region}/ rendues serveur avec microdonnées schema.org par carte : adresse, ville, GPS, prix « À partir de » (itemprop=price), type, description, chambres, photo. Aucune clé, aucun JS. Projets LOCATIFS écartés (prix mensuel < 50 000 $ ou « locatif » dans le texte). 1 fiche = 1 projet (prix plancher, details.price_from).
14 +
15 +## Mécanique (introspection du code)
16 +
17 +- Module : `immoka/connectors/guidehabitation.py` — classe `GuideHabitationConnector`
18 +- Délai entre requêtes : 1.0 s ; cache détail BD : oui
19 +
20 +**En-tête du module :**
21 +
22 +> Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
23 +> Auteur : Simon-Pierre Boucher — contact@spboucher.ai
24 +> connectors/guidehabitation.py : Guide Habitation (guidehabitation.ca)
25 +> Répertoire de référence des PROJETS NEUFS au Québec (condos et maisons
26 +> neuves des promoteurs). Pages région /fr/projets-immobiliers/{region}/
27 +> rendues serveur avec microdonnées schema.org complètes par carte projet :
28 +> adresse (streetAddress), ville, GPS, prix « À partir de » (itemprop=price),
29 +> type (SingleFamilyResidence → maison, ApartmentComplex → condo),
30 +> description, chambres offertes, photo. Aucune clé, aucun rendu JS.
31 +> On écarte les projets LOCATIFS (prix mensuel / « locatif » dans le texte) :
32 +> Immo-Ka couvre le neuf À VENDRE. external_id = data-id du projet.
33 +
34 +## Volumétrie & complétude (BD live)
35 +
36 +| Indicateur | Valeur |
37 +|---|---|
38 +| Annonces en base (toutes) | 95 |
39 +| Actives | 95 |
40 +| Visibles (après dédup) | 94 |
41 +| Masquées par la dédup | 1 |
42 +| GPS (lat/lng) | 100.0 % |
43 +| Photos | 100.0 % |
44 +| Prix | 100.0 % |
45 +| CAC (chambres) | 100.0 % |
46 +| SDB (salles de bains) | 0.0 % |
47 +| Année de construction | 0.0 % |
48 +| Taxes / évaluation municipale | 0.0 % |
49 +| Estimation Vrai-Prix (rôle) | 0.0 % |
50 +
51 +## Synchronisation
52 +
53 +- **Dernier sync** : 2026-08-18 05:56 — trouvé 95, +95 / ~0 / -0 — OK
54 +- **Erreurs récentes** : 0 sur les 1 derniers syncs
55 +
56 +Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
modified docs/connecteurs/image_ag_qc.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Image, l'agence immobilière (`image_ag_qc`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/imcha_ag_qc.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Les Immeubles Charlevoix (`imcha_ag_qc`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/immodev.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Immodev Agence Immobilière (`immodev`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/kijiji.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Kijiji Québec (`kijiji`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/kw_distinction.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Keller Williams Distinction (`kw_distinction`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/kw_prestige.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Keller Williams Prestige (`kw_prestige`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/kw_urbain.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Keller Williams Urbain (`kw_urbain`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/lespac.md +10 −10
@@ -1,6 +1,6 @@
1 1 # LesPAC Québec (`lespac`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
@@ -32,16 +32,16 @@
32 32 |---|---|
33 33 | Annonces en base (toutes) | 4 343 |
34 34 | Actives | 4 132 |
35 −| Visibles (après dédup) | 2 720 |
36 −| Masquées par la dédup | 1 412 |
37 −| GPS (lat/lng) | 46.3 % |
35 +| Visibles (après dédup) | 2 756 |
36 +| Masquées par la dédup | 1 376 |
37 +| GPS (lat/lng) | 46.8 % |
38 38 | Photos | 99.6 % |
39 −| Prix | 97.8 % |
40 −| CAC (chambres) | 54.3 % |
41 −| SDB (salles de bains) | 15.6 % |
42 −| Année de construction | 57.5 % (dont rôle : 0.0 %) |
43 −| Taxes / évaluation municipale | 8.3 % |
44 −| Estimation Vrai-Prix (rôle) | 69.7 % |
39 +| Prix | 97.9 % |
40 +| CAC (chambres) | 54.6 % |
41 +| SDB (salles de bains) | 15.7 % |
42 +| Année de construction | 57.9 % (dont rôle : 0.0 %) |
43 +| Taxes / évaluation municipale | 8.1 % |
44 +| Estimation Vrai-Prix (rôle) | 70.2 % |
45 45
46 46 ## Synchronisation
47 47
modified docs/connecteurs/m_immobilier.md +1 −1
@@ -1,6 +1,6 @@
1 1 # M Immobilier (`m_immobilier`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/niddamour.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Nid d'Amour Agence Immobilière (`niddamour`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
added docs/connecteurs/peladeau.md +59 −0
@@ -0,0 +1,59 @@
1 +# Péladeau Agence Immobilière (`peladeau`)
2 +
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 +
5 +## Registre (`data/sources.json`)
6 +
7 +- **Site** : https://www.epeladeau.com
8 +- **Recherche** : https://www.epeladeau.com/proprietes/
9 +- **Couverture** : Agence indépendante
10 +- **Type** : agence
11 +- **Statut** : actif
12 +
13 +> Plateforme source.immo (API publique, config auto _configs.json). ~47 propriétés à vendre (2026-08-18). Généré par agences_source_immo.py.
14 +
15 +## Mécanique (introspection du code)
16 +
17 +- Module : `immoka/connectors/agences_source_immo.py` — classe `AgenceSIPeladeau`
18 +- Délai entre requêtes : 0.25 s ; cache détail BD : non
19 +
20 +**En-tête du module :**
21 +
22 +> Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
23 +> Auteur : Simon-Pierre Boucher — contact@spboucher.ai
24 +> connectors/agences_source_immo.py : agences INDÉPENDANTES sur la plateforme
25 +> source.immo (plugin WordPress). Beaucoup de petites/moyennes agences QC
26 +> l'utilisent (liste sur source.immo). Chacune expose sa config publique à
27 +> /wp-content/uploads/_sourceimmo/_configs.json → on lit l'API publique
28 +> api-v1.source.immo (voir SourceImmoConnector). Ce sont des agences
29 +> autonomes : leurs inscriptions (leur propre n° Centris) sont ADDITIVES —
30 +> pas de sous-agence d'une bannière déjà couverte → source_id normal (pas _ag_).
31 +> EXCEPTION : les équipes/agences dont une partie des inscriptions est
32 +> co-listée avec une bannière couverte (co-inscription Centris) portent un id
33 +> « si_ag_<slug> » : la dédup Centris (db.refresh_dedup, sources %_ag_%)
34 +> masque leurs doublons tout en gardant leurs fiches uniques visibles.
35 +> Un connecteur par agence est généré depuis data/source_immo_agencies.json.
36 +
37 +## Volumétrie & complétude (BD live)
38 +
39 +| Indicateur | Valeur |
40 +|---|---|
41 +| Annonces en base (toutes) | 47 |
42 +| Actives | 47 |
43 +| Visibles (après dédup) | 47 |
44 +| Masquées par la dédup | 0 |
45 +| GPS (lat/lng) | 100.0 % |
46 +| Photos | 100.0 % |
47 +| Prix | 100.0 % |
48 +| CAC (chambres) | 93.6 % |
49 +| SDB (salles de bains) | 95.7 % |
50 +| Année de construction | 83.0 % (dont rôle : 0.0 %) |
51 +| Taxes / évaluation municipale | 78.7 % |
52 +| Estimation Vrai-Prix (rôle) | 0.0 % |
53 +
54 +## Synchronisation
55 +
56 +- **Dernier sync** : 2026-08-18 05:56 — trouvé 47, +47 / ~0 / -0 — OK
57 +- **Erreurs récentes** : 0 sur les 1 derniers syncs
58 +
59 +Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
modified docs/connecteurs/profusion.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Profusion Immobilier (Christie's) (`profusion`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/proprio_direct.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Proprio Direct (`proprio_direct`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
added docs/connecteurs/provad.md +59 −0
@@ -0,0 +1,59 @@
1 +# Proulx Vadnais & Associés (`provad`)
2 +
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 +
5 +## Registre (`data/sources.json`)
6 +
7 +- **Site** : https://provad.ca
8 +- **Recherche** : https://provad.ca/nos-proprietes/
9 +- **Couverture** : Agence indépendante commerciale/industrielle (Laval, Rive-Nord)
10 +- **Type** : agence
11 +- **Statut** : actif
12 +
13 +> Plateforme source.immo (API publique, config auto _configs.json). ~80 propriétés à vendre (2026-08-18). Généré par agences_source_immo.py.
14 +
15 +## Mécanique (introspection du code)
16 +
17 +- Module : `immoka/connectors/agences_source_immo.py` — classe `AgenceSIProvad`
18 +- Délai entre requêtes : 0.25 s ; cache détail BD : non
19 +
20 +**En-tête du module :**
21 +
22 +> Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
23 +> Auteur : Simon-Pierre Boucher — contact@spboucher.ai
24 +> connectors/agences_source_immo.py : agences INDÉPENDANTES sur la plateforme
25 +> source.immo (plugin WordPress). Beaucoup de petites/moyennes agences QC
26 +> l'utilisent (liste sur source.immo). Chacune expose sa config publique à
27 +> /wp-content/uploads/_sourceimmo/_configs.json → on lit l'API publique
28 +> api-v1.source.immo (voir SourceImmoConnector). Ce sont des agences
29 +> autonomes : leurs inscriptions (leur propre n° Centris) sont ADDITIVES —
30 +> pas de sous-agence d'une bannière déjà couverte → source_id normal (pas _ag_).
31 +> EXCEPTION : les équipes/agences dont une partie des inscriptions est
32 +> co-listée avec une bannière couverte (co-inscription Centris) portent un id
33 +> « si_ag_<slug> » : la dédup Centris (db.refresh_dedup, sources %_ag_%)
34 +> masque leurs doublons tout en gardant leurs fiches uniques visibles.
35 +> Un connecteur par agence est généré depuis data/source_immo_agencies.json.
36 +
37 +## Volumétrie & complétude (BD live)
38 +
39 +| Indicateur | Valeur |
40 +|---|---|
41 +| Annonces en base (toutes) | 80 |
42 +| Actives | 80 |
43 +| Visibles (après dédup) | 80 |
44 +| Masquées par la dédup | 0 |
45 +| GPS (lat/lng) | 100.0 % |
46 +| Photos | 100.0 % |
47 +| Prix | 100.0 % |
48 +| CAC (chambres) | 1.2 % |
49 +| SDB (salles de bains) | 0.0 % |
50 +| Année de construction | 41.2 % (dont rôle : 0.0 %) |
51 +| Taxes / évaluation municipale | 42.5 % |
52 +| Estimation Vrai-Prix (rôle) | 0.0 % |
53 +
54 +## Synchronisation
55 +
56 +- **Dernier sync** : 2026-08-18 05:56 — trouvé 80, +80 / ~0 / -0 — OK
57 +- **Erreurs récentes** : 0 sur les 1 derniers syncs
58 +
59 +Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
modified docs/connecteurs/realta.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Réalta Agence Immobilière (`realta`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
added docs/connecteurs/realtor_ag_ca.md +66 −0
@@ -0,0 +1,66 @@
1 +# Realtor.ca (MLS Québec) (`realtor_ag_ca`)
2 +
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 +
5 +## Registre (`data/sources.json`)
6 +
7 +- **Site** : https://www.realtor.ca
8 +- **Recherche** : https://www.realtor.ca/map#view=list&Province=QC
9 +- **Couverture** : Toute la province — agrégateur MLS pan-bannières (SCI/CREA)
10 +- **Type** : agrégateur
11 +- **Statut** : actif
12 +
13 +> API interne api2.realtor.ca/Listing.svc/PropertySearch_Post (POST form). Protégée DataDome/Incapsula : accès direct = 403, mais REJOUABLE via Scrapfly ASP SANS render_js (vérifié 2026-08-18) → JSON riche : MLS, GPS, prix, CAC/SDB, superficie, photos, courtier+agence. 200 fiches/page, plafond serveur 600/recherche → sharding par 14 boîtes lat/lng QC, tri plus récentes d'abord (Sort=6-D). Budget borné IMMOKA_REALTOR_MAX (défaut 2 000 fiches/sync ≈ 10 appels Scrapfly — les ~10 shards les plus denses ; augmenter pour couvrir les régions éloignées ; 0 = désactivé). external_id = n° MLS Centris + infixe _ag_ → la dédup masque tout recoupement avec les connecteurs directs ; seules les fiches des bannières non couvertes restent visibles. Fenêtre glissante : les fiches anciennes sortent du budget au fil des syncs (miss_count → inactif).
14 +
15 +## Mécanique (introspection du code)
16 +
17 +- Module : `immoka/connectors/realtor_ca.py` — classe `RealtorCaConnector`
18 +- Délai entre requêtes : 0.2 s ; cache détail BD : non
19 +- Budgets env (enrichissement détail plafonné/exécution) : `IMMOKA_REALTOR_MAX` (défaut 2000)
20 +
21 +**En-tête du module :**
22 +
23 +> Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
24 +> Auteur : Simon-Pierre Boucher — contact@spboucher.ai
25 +> connectors/realtor_ca.py : Realtor.ca (couverture MLS pan-bannières, QC)
26 +> API interne https://api2.realtor.ca/Listing.svc/PropertySearch_Post (POST
27 +> form). Protégée (DataDome/Incapsula) : l'accès direct renvoie 403, mais
28 +> l'API se REJOUE via Scrapfly ASP SANS render_js (1 crédit-appel ASP, pas de
29 +> navigateur) → JSON complet : n° MLS, GPS, prix, CAC/SDB, superficie, photos,
30 +> courtier + agence. Vérifié 2026-08-18 : 200 fiches/page, plafond serveur
31 +> 600 fiches (MaxRecords) par recherche → SHARDING par boîtes lat/lng
32 +> couvrant le Québec, tri « plus récentes d'abord » (Sort=6-D).
33 +> BUDGET BORNÉ : IMMOKA_REALTOR_MAX fiches max par sync (défaut 2 000, soit
34 +> ~10 appels Scrapfly), réparties en balayant la page 1 de chaque shard puis
35 +> les pages 2-3 si le budget le permet. Les fiches plus anciennes sortent de
36 +> la fenêtre au fil des syncs (miss_count → active=0) : le connecteur vaut
37 +> surtout pour les inscriptions récentes des bannières non couvertes.
38 +> Mettre IMMOKA_REALTOR_MAX=0 pour désactiver le connecteur.
39 +> source_id « realtor_ag_ca » : l'infixe _ag_ + external_id = n° MLS Centris
40 +> activent la dédup existante — toute fiche déjà couverte par un connecteur
41 +> direct (RE/MAX, Royal LePage, Sutton…) est masquée, seules les fiches
42 +> UNIQUES (petites bannières sans connecteur) restent visibles.
43 +
44 +## Volumétrie & complétude (BD live)
45 +
46 +| Indicateur | Valeur |
47 +|---|---|
48 +| Annonces en base (toutes) | 2 145 |
49 +| Actives | 2 145 |
50 +| Visibles (après dédup) | 343 |
51 +| Masquées par la dédup | 1 802 |
52 +| GPS (lat/lng) | 100.0 % |
53 +| Photos | 100.0 % |
54 +| Prix | 100.0 % |
55 +| CAC (chambres) | 85.7 % |
56 +| SDB (salles de bains) | 86.0 % |
57 +| Année de construction | 0.0 % |
58 +| Taxes / évaluation municipale | 0.0 % |
59 +| Estimation Vrai-Prix (rôle) | 0.0 % |
60 +
61 +## Synchronisation
62 +
63 +- **Dernier sync** : 2026-08-18 06:06 — trouvé 2 145, +2145 / ~0 / -0 — OK
64 +- **Erreurs récentes** : 0 sur les 1 derniers syncs
65 +
66 +Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
modified docs/connecteurs/remax_quebec.md +5 −5
@@ -1,6 +1,6 @@
1 1 # RE/MAX Québec (`remax_quebec`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
@@ -41,17 +41,17 @@
41 41 | Visibles (après dédup) | 25 348 |
42 42 | Masquées par la dédup | 138 |
43 43 | GPS (lat/lng) | 100.0 % |
44 −| Photos | 99.7 % |
44 +| Photos | 100.0 % |
45 45 | Prix | 83.9 % |
46 46 | CAC (chambres) | 79.1 % |
47 47 | SDB (salles de bains) | 59.9 % |
48 −| Année de construction | 77.0 % (dont rôle : 99.9 %) |
49 −| Taxes / évaluation municipale | 0.4 % |
48 +| Année de construction | 82.8 % (dont rôle : 0.0 %) |
49 +| Taxes / évaluation municipale | 77.2 % |
50 50 | Estimation Vrai-Prix (rôle) | 100.0 % |
51 51
52 52 ## Synchronisation
53 53
54 −- **Dernier sync** : 2026-08-18 01:45 — trouvé 25 486, +0 / ~60 / -177 — OK
54 +- **Dernier sync** : 2026-08-18 05:11 — trouvé 25 486, +0 / ~25426 / -0 — OK
55 55 - **Erreurs récentes** : 0 sur les 10 derniers syncs
56 56
57 57 Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
modified docs/connecteurs/royal_lepage.md +10 −10
@@ -1,6 +1,6 @@
1 1 # Royal LePage (Québec) (`royal_lepage`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
@@ -37,21 +37,21 @@
37 37 | Indicateur | Valeur |
38 38 |---|---|
39 39 | Annonces en base (toutes) | 1 461 |
40 −| Actives | 1 012 |
41 −| Visibles (après dédup) | 1 009 |
40 +| Actives | 1 011 |
41 +| Visibles (après dédup) | 1 008 |
42 42 | Masquées par la dédup | 3 |
43 43 | GPS (lat/lng) | 100.0 % |
44 −| Photos | 99.9 % |
45 −| Prix | 80.4 % |
46 −| CAC (chambres) | 81.8 % |
47 −| SDB (salles de bains) | 81.4 % |
48 −| Année de construction | 85.7 % (dont rôle : 99.4 %) |
49 −| Taxes / évaluation municipale | 0.4 % |
44 +| Photos | 100.0 % |
45 +| Prix | 80.5 % |
46 +| CAC (chambres) | 85.6 % |
47 +| SDB (salles de bains) | 84.5 % |
48 +| Année de construction | 89.0 % (dont rôle : 47.6 %) |
49 +| Taxes / évaluation municipale | 38.0 % |
50 50 | Estimation Vrai-Prix (rôle) | 100.0 % |
51 51
52 52 ## Synchronisation
53 53
54 −- **Dernier sync** : 2026-08-18 02:20 — trouvé 1 010, +0 / ~7 / -18 — OK
54 +- **Dernier sync** : 2026-08-18 05:19 — trouvé 1 010, +0 / ~498 / -1 — OK
55 55 - **Erreurs récentes** : 0 sur les 10 derniers syncs
56 56
57 57 Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
added docs/connecteurs/si_ag_ciemcq.md +59 −0
@@ -0,0 +1,59 @@
1 +# Chambre immobilière Estrie–Mauricie–Centre-du-Québec (Mon-Toit) (`si_ag_ciemcq`)
2 +
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 +
5 +## Registre (`data/sources.json`)
6 +
7 +- **Site** : https://www.mon-toit.net
8 +- **Recherche** : https://www.mon-toit.net/proprietes/
9 +- **Couverture** : Estrie, Mauricie, Centre-du-Québec — ~600 courtiers (chambre régionale)
10 +- **Type** : chambre
11 +- **Statut** : actif
12 +
13 +> Plateforme source.immo (config publique _configs.json sur mon-toit.net et ciemcq.com). ~3 900 fiches à vendre (2026-08-18). Flux co-listé avec les bannières → si_ag_ (dédup Centris). Généré par agences_source_immo.py.
14 +
15 +## Mécanique (introspection du code)
16 +
17 +- Module : `immoka/connectors/agences_source_immo.py` — classe `AgenceSISiAgCiemcq`
18 +- Délai entre requêtes : 0.25 s ; cache détail BD : non
19 +
20 +**En-tête du module :**
21 +
22 +> Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
23 +> Auteur : Simon-Pierre Boucher — contact@spboucher.ai
24 +> connectors/agences_source_immo.py : agences INDÉPENDANTES sur la plateforme
25 +> source.immo (plugin WordPress). Beaucoup de petites/moyennes agences QC
26 +> l'utilisent (liste sur source.immo). Chacune expose sa config publique à
27 +> /wp-content/uploads/_sourceimmo/_configs.json → on lit l'API publique
28 +> api-v1.source.immo (voir SourceImmoConnector). Ce sont des agences
29 +> autonomes : leurs inscriptions (leur propre n° Centris) sont ADDITIVES —
30 +> pas de sous-agence d'une bannière déjà couverte → source_id normal (pas _ag_).
31 +> EXCEPTION : les équipes/agences dont une partie des inscriptions est
32 +> co-listée avec une bannière couverte (co-inscription Centris) portent un id
33 +> « si_ag_<slug> » : la dédup Centris (db.refresh_dedup, sources %_ag_%)
34 +> masque leurs doublons tout en gardant leurs fiches uniques visibles.
35 +> Un connecteur par agence est généré depuis data/source_immo_agencies.json.
36 +
37 +## Volumétrie & complétude (BD live)
38 +
39 +| Indicateur | Valeur |
40 +|---|---|
41 +| Annonces en base (toutes) | 3 920 |
42 +| Actives | 3 920 |
43 +| Visibles (après dédup) | 1 169 |
44 +| Masquées par la dédup | 2 751 |
45 +| GPS (lat/lng) | 100.0 % |
46 +| Photos | 100.0 % |
47 +| Prix | 100.0 % |
48 +| CAC (chambres) | 66.7 % |
49 +| SDB (salles de bains) | 60.1 % |
50 +| Année de construction | 62.8 % (dont rôle : 0.0 %) |
51 +| Taxes / évaluation municipale | 83.7 % |
52 +| Estimation Vrai-Prix (rôle) | 0.0 % |
53 +
54 +## Synchronisation
55 +
56 +- **Dernier sync** : 2026-08-18 05:56 — trouvé 3 920, +3920 / ~0 / -0 — OK
57 +- **Erreurs récentes** : 0 sur les 1 derniers syncs
58 +
59 +Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
added docs/connecteurs/si_ag_jga.md +59 −0
@@ -0,0 +1,59 @@
1 +# JGA Équipe Commerciale (Royal LePage) (`si_ag_jga`)
2 +
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 +
5 +## Registre (`data/sources.json`)
6 +
7 +- **Site** : https://jgacommercial.com
8 +- **Recherche** : https://jgacommercial.com/proprietes/
9 +- **Couverture** : Équipe commerciale/industrielle Royal LePage
10 +- **Type** : équipe
11 +- **Statut** : actif
12 +
13 +> Plateforme source.immo. ~64 fiches à vendre (2026-08-18). Équipe co-listée → si_ag_ (dédup Centris). Généré par agences_source_immo.py.
14 +
15 +## Mécanique (introspection du code)
16 +
17 +- Module : `immoka/connectors/agences_source_immo.py` — classe `AgenceSISiAgJga`
18 +- Délai entre requêtes : 0.25 s ; cache détail BD : non
19 +
20 +**En-tête du module :**
21 +
22 +> Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
23 +> Auteur : Simon-Pierre Boucher — contact@spboucher.ai
24 +> connectors/agences_source_immo.py : agences INDÉPENDANTES sur la plateforme
25 +> source.immo (plugin WordPress). Beaucoup de petites/moyennes agences QC
26 +> l'utilisent (liste sur source.immo). Chacune expose sa config publique à
27 +> /wp-content/uploads/_sourceimmo/_configs.json → on lit l'API publique
28 +> api-v1.source.immo (voir SourceImmoConnector). Ce sont des agences
29 +> autonomes : leurs inscriptions (leur propre n° Centris) sont ADDITIVES —
30 +> pas de sous-agence d'une bannière déjà couverte → source_id normal (pas _ag_).
31 +> EXCEPTION : les équipes/agences dont une partie des inscriptions est
32 +> co-listée avec une bannière couverte (co-inscription Centris) portent un id
33 +> « si_ag_<slug> » : la dédup Centris (db.refresh_dedup, sources %_ag_%)
34 +> masque leurs doublons tout en gardant leurs fiches uniques visibles.
35 +> Un connecteur par agence est généré depuis data/source_immo_agencies.json.
36 +
37 +## Volumétrie & complétude (BD live)
38 +
39 +| Indicateur | Valeur |
40 +|---|---|
41 +| Annonces en base (toutes) | 64 |
42 +| Actives | 64 |
43 +| Visibles (après dédup) | 59 |
44 +| Masquées par la dédup | 5 |
45 +| GPS (lat/lng) | 100.0 % |
46 +| Photos | 100.0 % |
47 +| Prix | 100.0 % |
48 +| CAC (chambres) | 8.5 % |
49 +| SDB (salles de bains) | 5.1 % |
50 +| Année de construction | 28.8 % (dont rôle : 0.0 %) |
51 +| Taxes / évaluation municipale | 91.5 % |
52 +| Estimation Vrai-Prix (rôle) | 0.0 % |
53 +
54 +## Synchronisation
55 +
56 +- **Dernier sync** : 2026-08-18 05:56 — trouvé 64, +64 / ~0 / -0 — OK
57 +- **Erreurs récentes** : 0 sur les 1 derniers syncs
58 +
59 +Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
added docs/connecteurs/si_ag_katiasamson.md +59 −0
@@ -0,0 +1,59 @@
1 +# Katia Samson (RE/MAX L'Espace) (`si_ag_katiasamson`)
2 +
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 +
5 +## Registre (`data/sources.json`)
6 +
7 +- **Site** : https://www.katiasamson.com
8 +- **Recherche** : https://www.katiasamson.com/proprietes/
9 +- **Couverture** : Équipe RE/MAX L'Espace (Montréal)
10 +- **Type** : équipe
11 +- **Statut** : actif
12 +
13 +> Plateforme source.immo. ~30 fiches à vendre (2026-08-18). Équipe co-listée (remax_ag_lespace couvert) → si_ag_ (dédup Centris). Généré par agences_source_immo.py.
14 +
15 +## Mécanique (introspection du code)
16 +
17 +- Module : `immoka/connectors/agences_source_immo.py` — classe `AgenceSISiAgKatiasamson`
18 +- Délai entre requêtes : 0.25 s ; cache détail BD : non
19 +
20 +**En-tête du module :**
21 +
22 +> Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
23 +> Auteur : Simon-Pierre Boucher — contact@spboucher.ai
24 +> connectors/agences_source_immo.py : agences INDÉPENDANTES sur la plateforme
25 +> source.immo (plugin WordPress). Beaucoup de petites/moyennes agences QC
26 +> l'utilisent (liste sur source.immo). Chacune expose sa config publique à
27 +> /wp-content/uploads/_sourceimmo/_configs.json → on lit l'API publique
28 +> api-v1.source.immo (voir SourceImmoConnector). Ce sont des agences
29 +> autonomes : leurs inscriptions (leur propre n° Centris) sont ADDITIVES —
30 +> pas de sous-agence d'une bannière déjà couverte → source_id normal (pas _ag_).
31 +> EXCEPTION : les équipes/agences dont une partie des inscriptions est
32 +> co-listée avec une bannière couverte (co-inscription Centris) portent un id
33 +> « si_ag_<slug> » : la dédup Centris (db.refresh_dedup, sources %_ag_%)
34 +> masque leurs doublons tout en gardant leurs fiches uniques visibles.
35 +> Un connecteur par agence est généré depuis data/source_immo_agencies.json.
36 +
37 +## Volumétrie & complétude (BD live)
38 +
39 +| Indicateur | Valeur |
40 +|---|---|
41 +| Annonces en base (toutes) | 30 |
42 +| Actives | 30 |
43 +| Visibles (après dédup) | 25 |
44 +| Masquées par la dédup | 5 |
45 +| GPS (lat/lng) | 100.0 % |
46 +| Photos | 100.0 % |
47 +| Prix | 100.0 % |
48 +| CAC (chambres) | 96.0 % |
49 +| SDB (salles de bains) | 96.0 % |
50 +| Année de construction | 100.0 % (dont rôle : 0.0 %) |
51 +| Taxes / évaluation municipale | 64.0 % |
52 +| Estimation Vrai-Prix (rôle) | 0.0 % |
53 +
54 +## Synchronisation
55 +
56 +- **Dernier sync** : 2026-08-18 05:56 — trouvé 30, +30 / ~0 / -0 — OK
57 +- **Erreurs récentes** : 0 sur les 1 derniers syncs
58 +
59 +Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
modified docs/connecteurs/si_ag_theagency.md +7 −7
@@ -1,6 +1,6 @@
1 1 # The Agency Montréal (`si_ag_theagency`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
@@ -40,15 +40,15 @@
40 40 |---|---|
41 41 | Annonces en base (toutes) | 308 |
42 42 | Actives | 304 |
43 −| Visibles (après dédup) | 245 |
44 −| Masquées par la dédup | 59 |
43 +| Visibles (après dédup) | 236 |
44 +| Masquées par la dédup | 68 |
45 45 | GPS (lat/lng) | 100.0 % |
46 46 | Photos | 100.0 % |
47 47 | Prix | 100.0 % |
48 −| CAC (chambres) | 77.6 % |
49 −| SDB (salles de bains) | 75.5 % |
50 −| Année de construction | 88.6 % (dont rôle : 6.5 %) |
51 −| Taxes / évaluation municipale | 83.7 % |
48 +| CAC (chambres) | 78.8 % |
49 +| SDB (salles de bains) | 76.7 % |
50 +| Année de construction | 90.3 % (dont rôle : 6.6 %) |
51 +| Taxes / évaluation municipale | 84.7 % |
52 52 | Estimation Vrai-Prix (rôle) | 100.0 % |
53 53
54 54 ## Synchronisation
modified docs/connecteurs/sothebys_quebec.md +25 −17
@@ -1,6 +1,6 @@
1 1 # Sotheby's International Realty Québec (`sothebys_quebec`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
@@ -10,45 +10,53 @@
10 10 - **Type** : luxe
11 11 - **Statut** : actif
12 12
13 −> Recherche rendue côté client. Fiches enumérées via pages de résultats (grid public plafonné ~40 fiches province-wide ; pagination AJAX non exposée en URL). Chaque fiche enrichie via son JSON-LD Product : prix, galerie S3 complète (35-75 photos), description, MLS (sku), type. Limite : couverture = set public courant (~40) ; coverage complète nécessiterait l'endpoint AJAX de pagination.
13 +> Inventaire COMPLET via l'API AJAX interne /include/ajax_results.php (dowhat=getgridresults, jeton ajaxtoken de la page province, p_territories[]=4 = Québec, 64 fiches/page). Particularité : les valeurs du filtre statut de l'UI (1=For Sale, 3=For Rent) sont remappées côté serveur — on passe p_status[]=2 (neutre → aucun filtre → tout l'inventaire actif) et on écarte les locations («…/mo») au parsing. ~1 100 fiches QC dont ~965 à vendre (2026-08-18) contre ~40-60 avant (grid public plafonné). Enrichissement JSON-LD Product par fiche : prix, galerie S3 complète, description, MLS (sku). Repli : ancien parcours des pages région.
14 14
15 15 ## Mécanique (introspection du code)
16 16
17 17 - Module : `immoka/connectors/sothebys_quebec.py` — classe `SothebysQuebecConnector`
18 18 - Délai entre requêtes : 1.0 s ; cache détail BD : oui
19 −- Budgets env (enrichissement détail plafonné/exécution) : `IMMOKA_SOTHEBYS_DETAIL_LIMIT` (défaut 400)
19 +- Budgets env (enrichissement détail plafonné/exécution) : `IMMOKA_SOTHEBYS_DETAIL_LIMIT` (défaut 400), `IMMOKA_SOTHEBYS_MAX_PAGES` (défaut 30)
20 20
21 21 **En-tête du module :**
22 22
23 23 > Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
24 24 > Auteur : Simon-Pierre Boucher — contact@spboucher.ai
25 25 > connectors/sothebys_quebec.py : Sotheby's International Realty Québec
26 −> Recherche rendue côté client : le grid public est plafonné (~40/page) et la
27 −> pagination passe par du JS (pas d'URL). On SHARD donc par région
28 −> administrative du Québec (chaque page « region-{slug}-real-estate » renvoie
29 −> son lot), on dédoublonne par id, puis on enrichit chaque fiche via son
30 −> JSON-LD `Product` (prix, galerie S3 complète, description, n° MLS = sku).
26 +> Inventaire COMPLET via l'API AJAX interne du site :
27 +> GET /include/ajax_results.php?dowhat=getgridresults&token=…&p_territories[]=4
28 +> (territoire 4 = province de Québec ; jeton `ajaxtoken` exposé dans la page
29 +> /en/search-results/province-quebec-real-estate/). Pagination 64 fiches/page.
30 +> Particularité serveur : les valeurs du filtre statut de l'interface
31 +> (1 = For Sale, 3 = For Rent) sont REMAPPÉES côté serveur — `p_status[]=1`
32 +> renvoie 0 résultat et `p_status[]=3` seulement les locations. On passe donc
33 +> une valeur neutre (2) qui désactive le filtre et renvoie TOUT l'inventaire
34 +> actif (vente + location), puis on écarte les locations (« …/mo ») au parsing.
35 +> Chaque carte porte data-lat/lng/img/price + adresse/ville + CAC/SDB.
36 +> Enrichissement fiche détail (JSON-LD Product) : prix, galerie S3 complète,
37 +> description, n° MLS = sku. Repli : ancien parcours des pages région si
38 +> l'AJAX venait à changer.
31 39
32 40 ## Volumétrie & complétude (BD live)
33 41
34 42 | Indicateur | Valeur |
35 43 |---|---|
36 −| Annonces en base (toutes) | 58 |
37 −| Actives | 42 |
38 −| Visibles (après dédup) | 42 |
44 +| Annonces en base (toutes) | 869 |
45 +| Actives | 869 |
46 +| Visibles (après dédup) | 869 |
39 47 | Masquées par la dédup | 0 |
40 −| GPS (lat/lng) | 88.1 % |
48 +| GPS (lat/lng) | 99.8 % |
41 49 | Photos | 100.0 % |
42 50 | Prix | 100.0 % |
43 −| CAC (chambres) | 45.2 % |
44 −| SDB (salles de bains) | 14.3 % |
45 −| Année de construction | 71.4 % (dont rôle : 100.0 %) |
51 +| CAC (chambres) | 76.9 % |
52 +| SDB (salles de bains) | 74.5 % |
53 +| Année de construction | 3.5 % (dont rôle : 0.0 %) |
46 54 | Taxes / évaluation municipale | 0.0 % |
47 −| Estimation Vrai-Prix (rôle) | 100.0 % |
55 +| Estimation Vrai-Prix (rôle) | 6.7 % |
48 56
49 57 ## Synchronisation
50 58
51 −- **Dernier sync** : 2026-08-18 00:21 — trouvé 40, +2 / ~0 / -0 — OK
59 +- **Dernier sync** : 2026-08-18 06:05 — trouvé 869, +809 / ~60 / -0 — OK
52 60 - **Erreurs récentes** : 0 sur les 10 derniers syncs
53 61
54 62 Voir aussi les [mécanismes transverses](INDEX.md#mécanismes-transverses-tous-connecteurs) (budgets détail, dédup Centris+adresse, jointure rôle vraiprix.db).
modified docs/connecteurs/sutton.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Groupe Sutton Québec (`sutton`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/ubee.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Ubee (`ubee`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/vendirect.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Vendirect (`vendirect`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/via_ag_acces.md +7 −7
@@ -1,6 +1,6 @@
1 1 # Via Capitale Acces (`via_ag_acces`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
@@ -38,15 +38,15 @@
38 38 |---|---|
39 39 | Annonces en base (toutes) | 186 |
40 40 | Actives | 181 |
41 −| Visibles (après dédup) | 31 |
42 −| Masquées par la dédup | 150 |
41 +| Visibles (après dédup) | 7 |
42 +| Masquées par la dédup | 174 |
43 43 | GPS (lat/lng) | 100.0 % |
44 44 | Photos | 100.0 % |
45 45 | Prix | 100.0 % |
46 −| CAC (chambres) | 77.4 % |
47 −| SDB (salles de bains) | 74.2 % |
48 −| Année de construction | 96.8 % (dont rôle : 10.0 %) |
49 −| Taxes / évaluation municipale | 93.5 % |
46 +| CAC (chambres) | 57.1 % |
47 +| SDB (salles de bains) | 57.1 % |
48 +| Année de construction | 100.0 % (dont rôle : 0.0 %) |
49 +| Taxes / évaluation municipale | 100.0 % |
50 50 | Estimation Vrai-Prix (rôle) | 100.0 % |
51 51
52 52 ## Synchronisation
modified docs/connecteurs/via_ag_dumontroyal.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Via Capitale Dumontroyal (`via_ag_dumontroyal`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
modified docs/connecteurs/via_ag_elite.md +7 −7
@@ -1,6 +1,6 @@
1 1 # Via Capitale Elite (`via_ag_elite`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
@@ -38,15 +38,15 @@
38 38 |---|---|
39 39 | Annonces en base (toutes) | 327 |
40 40 | Actives | 319 |
41 −| Visibles (après dédup) | 11 |
42 −| Masquées par la dédup | 308 |
41 +| Visibles (après dédup) | 10 |
42 +| Masquées par la dédup | 309 |
43 43 | GPS (lat/lng) | 100.0 % |
44 44 | Photos | 100.0 % |
45 45 | Prix | 100.0 % |
46 −| CAC (chambres) | 63.6 % |
47 −| SDB (salles de bains) | 54.5 % |
48 −| Année de construction | 81.8 % (dont rôle : 22.2 %) |
49 −| Taxes / évaluation municipale | 81.8 % |
46 +| CAC (chambres) | 60.0 % |
47 +| SDB (salles de bains) | 60.0 % |
48 +| Année de construction | 80.0 % (dont rôle : 12.5 %) |
49 +| Taxes / évaluation municipale | 90.0 % |
50 50 | Estimation Vrai-Prix (rôle) | 100.0 % |
51 51
52 52 ## Synchronisation
modified docs/connecteurs/via_ag_select.md +6 −6
@@ -1,6 +1,6 @@
1 1 # Via Capitale Select (`via_ag_select`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
@@ -38,15 +38,15 @@
38 38 |---|---|
39 39 | Annonces en base (toutes) | 611 |
40 40 | Actives | 580 |
41 −| Visibles (après dédup) | 17 |
42 −| Masquées par la dédup | 563 |
41 +| Visibles (après dédup) | 13 |
42 +| Masquées par la dédup | 567 |
43 43 | GPS (lat/lng) | 100.0 % |
44 44 | Photos | 100.0 % |
45 45 | Prix | 100.0 % |
46 −| CAC (chambres) | 70.6 % |
47 −| SDB (salles de bains) | 70.6 % |
46 +| CAC (chambres) | 61.5 % |
47 +| SDB (salles de bains) | 61.5 % |
48 48 | Année de construction | 100.0 % (dont rôle : 0.0 %) |
49 −| Taxes / évaluation municipale | 94.1 % |
49 +| Taxes / évaluation municipale | 92.3 % |
50 50 | Estimation Vrai-Prix (rôle) | 100.0 % |
51 51
52 52 ## Synchronisation
modified docs/connecteurs/via_capitale.md +1 −1
@@ -1,6 +1,6 @@
1 1 # Via Capitale (`via_capitale`)
2 2
3 −*Généré le 2026-08-18 03:27 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
3 +*Généré le 2026-08-18 06:06 par `scripts/gen_connector_docs.py` — fichier produit automatiquement, ne pas éditer à la main.*
4 4
5 5 ## Registre (`data/sources.json`)
6 6
added immoka/connectors/guidehabitation.py +150 −0
@@ -0,0 +1,150 @@
1 +# -----------------------------------------------------------------------------
2 +# Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
3 +# Auteur : Simon-Pierre Boucher — contact@spboucher.ai
4 +# connectors/guidehabitation.py : Guide Habitation (guidehabitation.ca)
5 +# Répertoire de référence des PROJETS NEUFS au Québec (condos et maisons
6 +# neuves des promoteurs). Pages région /fr/projets-immobiliers/{region}/
7 +# rendues serveur avec microdonnées schema.org complètes par carte projet :
8 +# adresse (streetAddress), ville, GPS, prix « À partir de » (itemprop=price),
9 +# type (SingleFamilyResidence → maison, ApartmentComplex → condo),
10 +# description, chambres offertes, photo. Aucune clé, aucun rendu JS.
11 +# On écarte les projets LOCATIFS (prix mensuel / « locatif » dans le texte) :
12 +# Immo-Ka couvre le neuf À VENDRE. external_id = data-id du projet.
13 +# -----------------------------------------------------------------------------
14 +from __future__ import annotations
15 +
16 +import html as _html
17 +import re
18 +
19 +from .base import BaseConnector
20 +from ..schema import PropertyListing
21 +
22 +SITE = "https://www.guidehabitation.ca"
23 +
24 +# Régions du répertoire (repli si le sitemap est indisponible).
25 +REGIONS = ["montreal", "monteregie", "laval", "laurentides", "lanaudiere",
26 + "quebec", "estrie", "outaouais", "mauricie"]
27 +
28 +_SITEMAP_REGION_RE = re.compile(r'/fr/projets-immobiliers/([a-z-]+)/')
29 +_CARD_SPLIT_RE = re.compile(r'(?=<article class="project-card )')
30 +_ID_RE = re.compile(r'data-id="(\d+)"')
31 +_URL_RE = re.compile(r'href="(https://www\.guidehabitation\.ca/fr/\d+/[^"]+)"')
32 +_IMG_RE = re.compile(r'<img[^>]+src="([^"]+)"')
33 +_META_RE = re.compile(r'itemprop="(name|streetAddress|addressLocality|latitude|'
34 + r'longitude|price)"[^>]*content="([^"]*)"')
35 +_LOCALITY_RE = re.compile(r'itemprop="addressLocality">([^<]*)<')
36 +_NAME_H3_RE = re.compile(r'<h3 itemprop="name">([^<]*)</h3>')
37 +_DESC_RE = re.compile(r'itemprop="description">([^<]*)<')
38 +_TYPE_RE = re.compile(r'itemtype="https://schema\.org/(SingleFamilyResidence|'
39 + r'ApartmentComplex|Residence)"')
40 +_BEDROOMS_RE = re.compile(r'class="card-bedrooms">([^<]*)<')
41 +_PRICE_TXT_RE = re.compile(r'À partir de\s*([\d\s ,.]+)\s*\$')
42 +_RENTAL_RE = re.compile(r'locati|à louer|for rent', re.I)
43 +
44 +# En deçà de ce prix « à partir de », c'est un loyer mensuel (projet locatif).
45 +MIN_SALE_PRICE = 50_000
46 +
47 +
48 +class GuideHabitationConnector(BaseConnector):
49 + source_id = "guidehabitation"
50 + request_delay = 1.0
51 +
52 + def _regions(self) -> list[str]:
53 + try:
54 + xml = self.get(f"{SITE}/sitemap.xml").text
55 + found = sorted({m.group(1) for m in _SITEMAP_REGION_RE.finditer(xml)})
56 + if found:
57 + return found
58 + except Exception:
59 + pass
60 + return REGIONS
61 +
62 + def fetch(self) -> list[PropertyListing]:
63 + by_id: dict[str, PropertyListing] = {}
64 + for region in self._regions():
65 + try:
66 + html = self.get(f"{SITE}/fr/projets-immobiliers/{region}/").text
67 + except Exception:
68 + continue
69 + for card in _CARD_SPLIT_RE.split(html):
70 + if 'data-id="' not in card:
71 + continue
72 + lst = self._to_listing(card, region)
73 + if lst and lst.external_id not in by_id:
74 + by_id[lst.external_id] = lst
75 + return list(by_id.values())
76 +
77 + def _to_listing(self, card: str, region: str) -> PropertyListing | None:
78 + mid = _ID_RE.search(card)
79 + murl = _URL_RE.search(card)
80 + if not mid or not murl:
81 + return None
82 + meta = {k: _html.unescape(v).strip() for k, v in _META_RE.findall(card)}
83 + name = meta.get("name") or ""
84 + mh3 = _NAME_H3_RE.search(card)
85 + if mh3:
86 + name = _html.unescape(mh3.group(1)).strip() or name
87 + desc = ""
88 + mdesc = _DESC_RE.search(card)
89 + if mdesc:
90 + desc = _html.unescape(mdesc.group(1)).strip()
91 + # prix « À partir de » — absent ou mensuel (locatif) → hors périmètre
92 + price = None
93 + try:
94 + price = float(meta.get("price"))
95 + except (TypeError, ValueError):
96 + mtxt = _PRICE_TXT_RE.search(card)
97 + if mtxt:
98 + try:
99 + price = float(re.sub(r"[\s ,]", "", mtxt.group(1)))
100 + except ValueError:
101 + price = None
102 + if price is None or price < MIN_SALE_PRICE:
103 + return None
104 + if _RENTAL_RE.search(name) or _RENTAL_RE.search(desc):
105 + return None
106 + mtype = _TYPE_RE.search(card)
107 + ptype = {"SingleFamilyResidence": "Maison",
108 + "ApartmentComplex": "Condo"}.get(
109 + mtype.group(1) if mtype else "", "")
110 + city = meta.get("addressLocality") or ""
111 + if not city:
112 + mloc = _LOCALITY_RE.search(card)
113 + if mloc:
114 + city = _html.unescape(mloc.group(1)).strip()
115 + address = meta.get("streetAddress") or ""
116 + # « Chemin du Golf, Sainte-Julie, QC, Canada » → rue seulement
117 + address = re.sub(r",\s*(QC|Québec|Quebec)\b.*$", "", address).strip()
118 + if city and address.lower().endswith(", " + city.lower()):
119 + address = address[: -(len(city) + 2)].strip().rstrip(",")
120 + lst = PropertyListing(
121 + source=self.source_id,
122 + external_id=mid.group(1),
123 + url=murl.group(1),
124 + title=name,
125 + address=address or name,
126 + city=city,
127 + property_type=ptype,
128 + price=price,
129 + price_label=f"À partir de {price:,.0f} $".replace(",", " "),
130 + description=desc,
131 + broker_name="Guide Habitation — projet neuf",
132 + agency="Guide Habitation (projets neufs)",
133 + )
134 + mimg = _IMG_RE.search(card)
135 + if mimg:
136 + lst.images = [mimg.group(1)]
137 + try:
138 + lst.lat = float(meta.get("latitude"))
139 + lst.lng = float(meta.get("longitude"))
140 + except (TypeError, ValueError):
141 + pass
142 + mbeds = _BEDROOMS_RE.search(card)
143 + if mbeds:
144 + beds = re.findall(r"(\d+)\s*ch", mbeds.group(1))
145 + if beds:
146 + lst.bedrooms = int(beds[0]) # minimum offert
147 + lst.details["Chambres offertes"] = _html.unescape(
148 + mbeds.group(1)).strip()
149 + lst.details["Projet neuf"] = True
150 + return lst
added immoka/connectors/realtor_ca.py +191 −0
@@ -0,0 +1,191 @@
1 +# -----------------------------------------------------------------------------
2 +# Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
3 +# Auteur : Simon-Pierre Boucher — contact@spboucher.ai
4 +# connectors/realtor_ca.py : Realtor.ca (couverture MLS pan-bannières, QC)
5 +# API interne https://api2.realtor.ca/Listing.svc/PropertySearch_Post (POST
6 +# form). Protégée (DataDome/Incapsula) : l'accès direct renvoie 403, mais
7 +# l'API se REJOUE via Scrapfly ASP SANS render_js (1 crédit-appel ASP, pas de
8 +# navigateur) → JSON complet : n° MLS, GPS, prix, CAC/SDB, superficie, photos,
9 +# courtier + agence. Vérifié 2026-08-18 : 200 fiches/page, plafond serveur
10 +# 600 fiches (MaxRecords) par recherche → SHARDING par boîtes lat/lng
11 +# couvrant le Québec, tri « plus récentes d'abord » (Sort=6-D).
12 +#
13 +# BUDGET BORNÉ : IMMOKA_REALTOR_MAX fiches max par sync (défaut 2 000, soit
14 +# ~10 appels Scrapfly), réparties en balayant la page 1 de chaque shard puis
15 +# les pages 2-3 si le budget le permet. Les fiches plus anciennes sortent de
16 +# la fenêtre au fil des syncs (miss_count → active=0) : le connecteur vaut
17 +# surtout pour les inscriptions récentes des bannières non couvertes.
18 +# Mettre IMMOKA_REALTOR_MAX=0 pour désactiver le connecteur.
19 +#
20 +# source_id « realtor_ag_ca » : l'infixe _ag_ + external_id = n° MLS Centris
21 +# activent la dédup existante — toute fiche déjà couverte par un connecteur
22 +# direct (RE/MAX, Royal LePage, Sutton…) est masquée, seules les fiches
23 +# UNIQUES (petites bannières sans connecteur) restent visibles.
24 +# -----------------------------------------------------------------------------
25 +from __future__ import annotations
26 +
27 +import json
28 +import os
29 +
30 +from .base import BaseConnector
31 +from ..schema import PropertyListing
32 +
33 +SEARCH_URL = "https://api2.realtor.ca/Listing.svc/PropertySearch_Post"
34 +SITE = "https://www.realtor.ca"
35 +
36 +MAX_RECORDS = int(os.environ.get("IMMOKA_REALTOR_MAX", "2000"))
37 +PER_PAGE = 200 # maximum accepté par l'API
38 +MAX_PAGES_PER_SHARD = 3 # plafond serveur : MaxRecords=600 par recherche
39 +
40 +# Boîtes (sud, ouest, nord, est) couvrant le Québec habité, par densité
41 +# décroissante — le budget est d'abord dépensé sur les marchés actifs.
42 +SHARDS: list[tuple[str, float, float, float, float]] = [
43 + ("montreal-laval", 45.35, -74.05, 45.75, -73.30),
44 + ("monteregie", 45.00, -74.40, 45.35, -72.80),
45 + ("rive-sud-est", 45.35, -73.30, 45.75, -72.80),
46 + ("laurentides-lanaudiere", 45.75, -74.80, 46.40, -73.20),
47 + ("quebec-metro", 46.55, -71.65, 47.10, -70.90),
48 + ("chaudiere-appalaches", 46.00, -71.80, 46.85, -70.00),
49 + ("estrie", 45.00, -72.80, 45.90, -71.50),
50 + ("mauricie-cdq", 45.90, -73.20, 46.90, -71.80),
51 + ("outaouais", 45.30, -77.60, 46.50, -74.80),
52 + ("saguenay-lac-st-jean", 48.00, -72.60, 48.80, -70.70),
53 + ("bas-st-laurent-gaspesie", 47.20, -70.60, 49.40, -64.00),
54 + ("charlevoix-cote-nord", 47.00, -71.00, 50.40, -65.90),
55 + ("abitibi-temiscamingue", 47.20, -79.60, 48.90, -77.40),
56 + ("hautes-laurentides", 46.40, -76.00, 47.20, -74.20),
57 +]
58 +
59 +
60 +class RealtorCaConnector(BaseConnector):
61 + source_id = "realtor_ag_ca"
62 + request_delay = 0.2 # Scrapfly gère la politesse côté cible
63 + use_detail_cache = False # tout est déjà dans la réponse liste
64 +
65 + def _search(self, shard: tuple, page: int) -> dict:
66 + _, south, west, north, east = shard
67 + body = "&".join(f"{k}={v}" for k, v in {
68 + "ZoomLevel": 10,
69 + "LatitudeMax": north, "LongitudeMax": east,
70 + "LatitudeMin": south, "LongitudeMin": west,
71 + "Sort": "6-D", # inscription la plus récente d'abord
72 + "PropertyTypeGroupID": 1, # résidentiel
73 + "TransactionTypeId": 2, # à vendre
74 + "PropertySearchTypeId": 0,
75 + "Currency": "CAD",
76 + "RecordsPerPage": PER_PAGE,
77 + "CurrentPage": page,
78 + "CultureId": 1,
79 + "ApplicationId": 1,
80 + "PropertyStatusId": 1,
81 + "Version": "7.0",
82 + }.items())
83 + result = self.scrapfly(
84 + SEARCH_URL, render_js=False, asp=True, method="POST", body=body,
85 + headers={
86 + "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
87 + "Referer": "https://www.realtor.ca/",
88 + "Origin": "https://www.realtor.ca",
89 + })
90 + try:
91 + return json.loads(result.get("content") or "")
92 + except ValueError:
93 + return {}
94 +
95 + def fetch(self) -> list[PropertyListing]:
96 + if MAX_RECORDS <= 0:
97 + return []
98 + by_id: dict[str, PropertyListing] = {}
99 + exhausted: set[str] = set()
100 + for page in range(1, MAX_PAGES_PER_SHARD + 1):
101 + for shard in SHARDS:
102 + name = shard[0]
103 + if name in exhausted or len(by_id) >= MAX_RECORDS:
104 + continue
105 + data = self._search(shard, page)
106 + results = data.get("Results") or []
107 + if len(results) < PER_PAGE:
108 + exhausted.add(name)
109 + if not results:
110 + continue
111 + for item in results:
112 + lst = self._to_listing(item)
113 + if lst and lst.external_id not in by_id:
114 + by_id[lst.external_id] = lst
115 + if len(by_id) >= MAX_RECORDS:
116 + break
117 + return list(by_id.values())
118 +
119 + def _to_listing(self, item: dict) -> PropertyListing | None:
120 + prop = item.get("Property") or {}
121 + addr = prop.get("Address") or {}
122 + text = addr.get("AddressText") or ""
123 + # « 680 Rue De Courcelle|#613|Montréal (Le Sud-Ouest), Quebec H4C0B8 »
124 + if ", Quebec" not in text and ", Québec" not in text:
125 + return None # les shards frontaliers débordent (Ottawa, N.-B.)
126 + parts = [p.strip() for p in text.split("|")]
127 + locality = parts[-1] if parts else ""
128 + street = ", ".join(parts[:-1]) if len(parts) > 1 else ""
129 + city = sector = ""
130 + loc = locality.split(", Quebec")[0].split(", Québec")[0]
131 + if "(" in loc:
132 + city, _, rest = loc.partition("(")
133 + city, sector = city.strip(), rest.rstrip(")").strip()
134 + else:
135 + city = loc.strip()
136 + mls = str(item.get("MlsNumber") or "").strip()
137 + rid = str(item.get("Id") or "").strip()
138 + if not (mls or rid) or not street:
139 + return None
140 + try:
141 + price = float(prop.get("PriceUnformattedValue"))
142 + except (TypeError, ValueError):
143 + price = None
144 + building = item.get("Building") or {}
145 + lst = PropertyListing(
146 + source=self.source_id,
147 + external_id=mls or rid,
148 + url=f"{SITE}{item.get('RelativeDetailsURL') or ''}",
149 + title=f"{building.get('Type') or prop.get('Type') or ''} — {city}".strip(" —"),
150 + address=street,
151 + sector=sector,
152 + city=city,
153 + property_type=building.get("Type") or prop.get("Type") or "",
154 + price=price,
155 + price_label=prop.get("Price") or "",
156 + mls=mls,
157 + description=(item.get("PublicRemarks") or "").strip(),
158 + )
159 + try:
160 + lst.lat = float(addr.get("Latitude"))
161 + lst.lng = float(addr.get("Longitude"))
162 + except (TypeError, ValueError):
163 + pass
164 + beds = str(building.get("Bedrooms") or "")
165 + if beds:
166 + try: # « 3 + 1 » → 4
167 + lst.bedrooms = sum(int(x) for x in beds.replace(" ", "").split("+") if x)
168 + except ValueError:
169 + pass
170 + try:
171 + lst.bathrooms = int(building.get("BathroomTotal"))
172 + except (TypeError, ValueError):
173 + pass
174 + size = building.get("SizeInterior") or ""
175 + if size:
176 + lst.details["Superficie habitable"] = size
177 + land = (item.get("Land") or {}).get("SizeTotal") or ""
178 + if land:
179 + lst.details["Superficie du terrain"] = land
180 + lst.images = [p.get("HighResPath") or p.get("MedResPath")
181 + for p in (prop.get("Photo") or []) if isinstance(p, dict)]
182 + lst.images = [u for u in lst.images if u]
183 + ind = (item.get("Individual") or [{}])[0]
184 + lst.broker_name = ind.get("Name") or ""
185 + org = ind.get("Organization") or {}
186 + lst.agency = org.get("Name") or ""
187 + phones = ind.get("Phones") or []
188 + if phones:
189 + p0 = phones[0]
190 + lst.broker_phone = f"{p0.get('AreaCode', '')} {p0.get('PhoneNumber', '')}".strip()
191 + return lst
modified immoka/connectors/sothebys_quebec.py +148 −19
@@ -2,11 +2,19 @@
2 2 # Immo-Ka — Agrégateur de maisons à vendre (province de Québec)
3 3 # Auteur : Simon-Pierre Boucher — contact@spboucher.ai
4 4 # connectors/sothebys_quebec.py : Sotheby's International Realty Québec
5 −# Recherche rendue côté client : le grid public est plafonné (~40/page) et la
6 −# pagination passe par du JS (pas d'URL). On SHARD donc par région
7 −# administrative du Québec (chaque page « region-{slug}-real-estate » renvoie
8 −# son lot), on dédoublonne par id, puis on enrichit chaque fiche via son
9 −# JSON-LD `Product` (prix, galerie S3 complète, description, n° MLS = sku).
5 +# Inventaire COMPLET via l'API AJAX interne du site :
6 +# GET /include/ajax_results.php?dowhat=getgridresults&token=…&p_territories[]=4
7 +# (territoire 4 = province de Québec ; jeton `ajaxtoken` exposé dans la page
8 +# /en/search-results/province-quebec-real-estate/). Pagination 64 fiches/page.
9 +# Particularité serveur : les valeurs du filtre statut de l'interface
10 +# (1 = For Sale, 3 = For Rent) sont REMAPPÉES côté serveur — `p_status[]=1`
11 +# renvoie 0 résultat et `p_status[]=3` seulement les locations. On passe donc
12 +# une valeur neutre (2) qui désactive le filtre et renvoie TOUT l'inventaire
13 +# actif (vente + location), puis on écarte les locations (« …/mo ») au parsing.
14 +# Chaque carte porte data-lat/lng/img/price + adresse/ville + CAC/SDB.
15 +# Enrichissement fiche détail (JSON-LD Product) : prix, galerie S3 complète,
16 +# description, n° MLS = sku. Repli : ancien parcours des pages région si
17 +# l'AJAX venait à changer.
10 18 # -----------------------------------------------------------------------------
11 19 from __future__ import annotations
12 20
@@ -21,20 +29,29 @@ from ..schema import PropertyListing
21 29
22 30 SITE = "https://sothebysrealty.ca"
23 31 DETAIL_LIMIT = int(os.environ.get("IMMOKA_SOTHEBYS_DETAIL_LIMIT", "400"))
32 +# ~18 pages × 64 = tout l'inventaire QC (~1 100 fiches) ; borne de sécurité.
33 +MAX_PAGES = int(os.environ.get("IMMOKA_SOTHEBYS_MAX_PAGES", "30"))
34 +QC_TERRITORY = 4 # p_territories[] = province de Québec
24 35
25 −# Régions administratives du Québec (slugs de recherche Sotheby's).
36 +# Régions administratives du Québec (repli si l'AJAX casse).
26 37 QC_REGIONS = [
27 38 "region-montreal", "region-laval", "region-monteregie", "region-laurentides",
28 39 "region-lanaudiere", "region-eastern-townships", "region-outaouais",
29 40 "region-capitale-nationale", "region-mauricie", "region-centre-du-quebec",
30 41 "region-chaudiere-appalaches", "region-bas-saint-laurent",
31 42 "region-saguenay-lac-saint-jean", "region-cote-nord", "region-charlevoix",
32 − "region-gaspesie", "region-abitibi-temiscamingue",
43 + "region-gaspesie-iles-de-la-madeleine", "region-abitibi-temiscamingue",
33 44 ]
34 45
35 46 _PROP_RE = re.compile(
36 47 r'/(?:fr|en)/property/quebec/region-([a-z-]+)/([a-z0-9-]+?)-real-estate/(\d{5,})/([a-z0-9-]+)/',
37 48 re.I)
49 +_TOKEN_RE = re.compile(r"var ajaxtoken = '([a-f0-9]+)'")
50 +_CARD_SPLIT_RE = re.compile(r'(?=<div class="mprop )')
51 +_ATTR_RE = re.compile(r'data-(lat|lng|img|price|id)="([^"]*)"')
52 +_LOC_RE = re.compile(r'<p class="location">([^<]*)</p>')
53 +_BED_RE = re.compile(r'(\d{1,2})\s*BEDS?', re.I)
54 +_BATH_RE = re.compile(r'(\d{1,2})\s*BATHS?', re.I)
38 55
39 56
40 57 class SothebysQuebecConnector(BaseConnector):
@@ -42,8 +59,8 @@ class SothebysQuebecConnector(BaseConnector):
42 59 request_delay = 1.0
43 60
44 61 def _get_tolerant(self, url: str) -> str:
45 − """GET qui ignore le statut HTTP : les pages de résultats Sotheby's
46 − renvoient un 404 tout en servant le contenu complet."""
62 + """GET qui ignore le statut HTTP : certaines pages Sotheby's renvoient
63 + un 404 tout en servant le contenu complet."""
47 64 import time
48 65 wait = self.request_delay - (time.time() - self._last_request)
49 66 if wait > 0:
@@ -52,23 +69,135 @@ class SothebysQuebecConnector(BaseConnector):
52 69 self._last_request = time.time()
53 70 return resp.text
54 71
72 + # -- API AJAX interne -------------------------------------------------------
73 + def _ajax_token(self) -> str:
74 + html = self._get_tolerant(
75 + f"{SITE}/en/search-results/province-quebec-real-estate/")
76 + m = _TOKEN_RE.search(html)
77 + return m.group(1) if m else ""
78 +
79 + def _ajax_page(self, token: str, page: int) -> dict:
80 + params = {
81 + "dowhat": "getgridresults", "token": token, "agent_slug": "",
82 + "aid": 0, "team_id": 0, "view": "grid", "sort": 1,
83 + "p_bed": 0, "p_bath": 0, "p_mls": 1, "p_minprice": 0,
84 + "p_maxprice": 0, "p_status[]": 2, "p_territories[]": QC_TERRITORY,
85 + "search_type_init": 2, "per_page": 64, "per_page_init": 64,
86 + "page": page, "map_data": 0, "device": "desktop",
87 + "device_width": 1440, "start": "", "crawler": 0, "office": 0,
88 + "development": 0, "igallery": 0, "boundary_trap": 0,
89 + "pagetype": "", "do_int": 0, "extrasearch": "", "results_qty": 0,
90 + }
91 + resp = self.get(f"{SITE}/include/ajax_results.php", params=params,
92 + headers={"X-Requested-With": "XMLHttpRequest",
93 + "Referer": f"{SITE}/en/search-results/"})
94 + try:
95 + return resp.json()
96 + except ValueError:
97 + return {}
98 +
55 99 def fetch(self) -> list[PropertyListing]:
56 100 by_id: dict[str, PropertyListing] = {}
57 − for region in QC_REGIONS:
58 − url = f"{SITE}/en/search-results/{region}-real-estate/"
59 − try:
60 − html = self._get_tolerant(url)
61 − except Exception:
62 − continue
63 − for m in _PROP_RE.finditer(html):
64 − lst = self._to_listing(m)
65 − if lst and lst.external_id not in by_id:
66 − by_id[lst.external_id] = lst
101 + try:
102 + token = self._ajax_token()
103 + if token:
104 + total = None
105 + for page in range(1, MAX_PAGES + 1):
106 + data = self._ajax_page(token, page)
107 + cards_html = (data or {}).get("properties") or ""
108 + if total is None:
109 + try:
110 + total = int(data.get("results") or 0)
111 + except (TypeError, ValueError):
112 + total = 0
113 + found = False
114 + for card in _CARD_SPLIT_RE.split(cards_html):
115 + if 'data-id="' not in card:
116 + continue
117 + found = True
118 + lst = self._card_to_listing(card)
119 + if lst and lst.external_id not in by_id:
120 + by_id[lst.external_id] = lst
121 + if not found or (total and len(by_id) >= total):
122 + break
123 + except Exception:
124 + pass
125 + if not by_id: # repli : parcours des pages région (ancienne méthode)
126 + for region in QC_REGIONS:
127 + url = f"{SITE}/en/search-results/{region}-province-quebec-real-estate/"
128 + try:
129 + html = self._get_tolerant(url)
130 + except Exception:
131 + continue
132 + for m in _PROP_RE.finditer(html):
133 + lst = self._to_listing(m)
134 + if lst and lst.external_id not in by_id:
135 + by_id[lst.external_id] = lst
67 136 listings = list(by_id.values())
68 137 # fiche détail : JSON-LD Product (prix, galerie complète, description, MLS)
69 138 du.enrich(self, listings, DETAIL_LIMIT, parse_sothebys_detail, key="v1")
70 139 return listings
71 140
141 + def _card_to_listing(self, card: str) -> PropertyListing | None:
142 + attrs = dict(_ATTR_RE.findall(card))
143 + pid = attrs.get("id")
144 + if not pid:
145 + return None
146 + price_label = _html.unescape(attrs.get("price") or "").strip()
147 + # hors périmètre « à vendre » : locations («…/mo») et fiches sans prix
148 + # affiché (« Sold », « Price upon request »…) — p_status neutre renvoie
149 + # tout l'inventaire, on filtre ici.
150 + if "/mo" in price_label or not re.search(r"\d", price_label):
151 + return None
152 + m = _PROP_RE.search(card)
153 + if m:
154 + region_slug, city_slug, _, addr_slug = m.groups()
155 + url = (f"{SITE}/fr/property/quebec/region-{region_slug}/"
156 + f"{city_slug}-real-estate/{pid}/{addr_slug}/")
157 + region = _deslug(region_slug)
158 + else:
159 + url = f"{SITE}/en/property/{pid}/"
160 + region = ""
161 + loc = _LOC_RE.search(card)
162 + address = city = ""
163 + title = ""
164 + if loc:
165 + title = _html.unescape(loc.group(1)).strip()
166 + parts = [p.strip() for p in title.split(",")]
167 + address = parts[0] if parts else ""
168 + # "28 Av. de la Gare, Saint-Sauveur, Quebec" → ville = avant-dernier
169 + if len(parts) >= 2:
170 + city = parts[-2] if parts[-1].lower() in ("quebec", "québec") \
171 + else parts[-1]
172 + if not title and m:
173 + title = _deslug(m.group(4))
174 + lst = PropertyListing(
175 + source=self.source_id,
176 + external_id=str(pid),
177 + url=url,
178 + title=title,
179 + address=address,
180 + city=city,
181 + region=region,
182 + price_label=price_label,
183 + broker_name="Sotheby's International Realty Québec",
184 + )
185 + mb = _BED_RE.search(card)
186 + if mb and int(mb.group(1)) <= 20:
187 + lst.bedrooms = int(mb.group(1))
188 + ms = _BATH_RE.search(card)
189 + if ms and int(ms.group(1)) <= 20:
190 + lst.bathrooms = int(ms.group(1))
191 + try:
192 + lst.lat = float(attrs.get("lat") or "")
193 + lst.lng = float(attrs.get("lng") or "")
194 + except ValueError:
195 + lst.lat = lst.lng = None
196 + img = attrs.get("img") or ""
197 + if img:
198 + lst.images = [re.sub(r'(?:nr|m)?\.jpg$', 'r.jpg', img)]
199 + return lst
200 +
72 201 def _to_listing(self, m: re.Match) -> PropertyListing | None:
73 202 region_slug, city_slug, pid, addr_slug = m.group(1), m.group(2), m.group(3), m.group(4)
74 203 url = f"{SITE}/fr/property/quebec/region-{region_slug}/{city_slug}-real-estate/{pid}/{addr_slug}/"
75 204