feat(ontario): monstres RealtyPress — revelrealty (~110k) + codygroup (~58k)
Champ registre `archive` (défaut "listing" ; revel: /listings/ — ⚠ /listing/ = carousel ; cody: /all-regional-listings/) et _LINK_RE généralisé (fiches cody hors /listing/). Ingestion : revel 84 091 + cody 57 925 ; dédup par external_id ddf<id> vérifiée (0 doublon visible, les sites régionaux priment). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3 changed files +45 −2
modified
data/ontario_agencies.json
+16 −0
@@ -1,4 +1,20 @@ | ||
| 1 | 1 | [ |
| 2 | + { | |
| 3 | + "id": "rp_ag_revelrealty", | |
| 4 | + "name": "Revel Realty (Niagara & provincial)", | |
| 5 | + "site": "https://revelrealty.ca", | |
| 6 | + "archive": "listings", | |
| 7 | + "max_pages": 1300, | |
| 8 | + "note": "Recensement ON 2026-08-27 : ~110 145 fiches — pool DDF quasi provincial. Archive /listings/ (⚠ /listing/ = carousel 8 cartes), 108 cartes/page avec posts_per_page=100. RealtyPress/DDF." | |
| 9 | + }, | |
| 10 | + { | |
| 11 | + "id": "rp_ag_codygroup", | |
| 12 | + "name": "The Cody Group (London/ITSO)", | |
| 13 | + "site": "https://codygroup.ca", | |
| 14 | + "archive": "all-regional-listings", | |
| 15 | + "max_pages": 700, | |
| 16 | + "note": "Recensement ON 2026-08-27 : ~58 062 fiches (London + ITSO élargi). Archive /all-regional-listings/, fiches sous le même chemin. RealtyPress/DDF." | |
| 17 | + }, | |
| 2 | 18 | { |
| 3 | 19 | "id": "rp_ag_suttonottawa", |
| 4 | 20 | "name": "Sutton Group — Ottawa Realty", |
modified
data/sources.json
+22 −0
@@ -868,6 +868,28 @@ | ||
| 868 | 868 | "type": "agence", |
| 869 | 869 | "note": "Site web « classique » server-rendered, connecteur générique agences_web.py (registre data/web_agencies.json). Découverte via recensement OACIQ 2026-08-24. Fiches Next.js rendues via Scrapfly. OACIQ 2026-08 : 9 courtiers (Montréal). Next.js : fiches rendues via Scrapfly." |
| 870 | 870 | }, |
| 871 | + { | |
| 872 | + "id": "rp_ag_revelrealty", | |
| 873 | + "name": "Revel Realty (Niagara & provincial)", | |
| 874 | + "url": "https://revelrealty.ca", | |
| 875 | + "listing_url": "https://revelrealty.ca/listings/", | |
| 876 | + "coverage": "Niagara + pool DDF quasi provincial — ~110 000 fiches", | |
| 877 | + "connector": "realtypress", | |
| 878 | + "status": "actif", | |
| 879 | + "type": "agence", | |
| 880 | + "note": "Extension ONTARIO 2026-08 — connecteur générique realtypress.py (registre data/ontario_agencies.json). Plugin WordPress RealtyPress branché sur le flux CREA DDF. Site MONSTRE : expose ~110 145 fiches (pool DDF quasi complet de la province). Archive /listings/ (⚠ /listing/ = carousel), 108 cartes/page. Infixe _ag_ : dédup inter-sites par external_id ddf<id> (les fiches des 13 sites régionaux priment via MIN(uid))." | |
| 881 | + }, | |
| 882 | + { | |
| 883 | + "id": "rp_ag_codygroup", | |
| 884 | + "name": "The Cody Group (London/ITSO)", | |
| 885 | + "url": "https://codygroup.ca", | |
| 886 | + "listing_url": "https://codygroup.ca/all-regional-listings/", | |
| 887 | + "coverage": "London + ITSO élargi — ~58 000 fiches DDF", | |
| 888 | + "connector": "realtypress", | |
| 889 | + "status": "actif", | |
| 890 | + "type": "agence", | |
| 891 | + "note": "Extension ONTARIO 2026-08 — connecteur générique realtypress.py (registre data/ontario_agencies.json). Plugin WordPress RealtyPress branché sur le flux CREA DDF. Site MONSTRE : ~58 062 fiches. Archive et fiches sous /all-regional-listings/. Infixe _ag_ : dédup inter-sites par external_id ddf<id>." | |
| 892 | + }, | |
| 871 | 893 | { |
| 872 | 894 | "id": "rp_ag_suttonottawa", |
| 873 | 895 | "name": "Sutton Group — Ottawa Realty", |
modified
immoka/connectors/realtypress.py
+7 −2
@@ -39,7 +39,9 @@ DETAIL_LIMIT = int(os.environ.get("IMMOKA_RP_DETAIL_LIMIT", | ||
| 39 | 39 | os.environ.get("IMMOKA_DETAIL_LIMIT", "150"))) |
| 40 | 40 | |
| 41 | 41 | _CARD_RE = re.compile(r'<div class="rps-property-result">') |
| 42 | −_LINK_RE = re.compile(r'href="(https?://[^"]+/listings?/[^"]+?-(\d{6,10})/?)"') | |
| 42 | +# fiche = 1er lien de la carte finissant par -<id DDF>/ ; le chemin varie selon | |
| 43 | +# le site (/listing/, /listings/, /all-regional-listings/…) | |
| 44 | +_LINK_RE = re.compile(r'href="(https?://[^"]+?-(\d{6,10})/?)"') | |
| 43 | 45 | _RIBBON_RE = re.compile(r'rps-ribbon[^>]*>\s*([^<]+?)\s*<') |
| 44 | 46 | _PRICE_RE = re.compile(r'rps-price[^>]*>\s*\$\s*([\d,]+)') |
| 45 | 47 | _H4_RE = re.compile(r"<h4>\s*(.*?)\s*</h4>", re.S) |
@@ -78,6 +80,8 @@ class _RealtyPress(BaseConnector): | ||
| 78 | 80 | |
| 79 | 81 | agency_name = "" |
| 80 | 82 | site_url = "" |
| 83 | + archive = "listing" # chemin de l'archive (revelrealty: "listings", | |
| 84 | + # codygroup: "all-regional-listings") | |
| 81 | 85 | max_pages = 150 # 100 cartes/page → jusqu'à 15 000 fiches par site |
| 82 | 86 | request_delay = 0.6 |
| 83 | 87 | |
@@ -89,7 +93,7 @@ class _RealtyPress(BaseConnector): | ||
| 89 | 93 | base = self.site_url.rstrip("/") |
| 90 | 94 | dry = 0 |
| 91 | 95 | for page in range(1, self.max_pages + 1): |
| 92 | − url = f"{base}/listing/page/{page}/?posts_per_page=100" | |
| 96 | + url = f"{base}/{self.archive}/page/{page}/?posts_per_page=100" | |
| 93 | 97 | try: |
| 94 | 98 | body = self.get(url).text |
| 95 | 99 | except Exception: |
@@ -287,6 +291,7 @@ for _ag in _load(): | ||
| 287 | 291 | "source_id": _sid, |
| 288 | 292 | "site_url": _ag["site"], |
| 289 | 293 | "agency_name": _ag.get("name", _sid), |
| 294 | + "archive": _ag.get("archive", "listing"), | |
| 290 | 295 | "max_pages": int(_ag.get("max_pages", 150)), |
| 291 | 296 | }, |
| 292 | 297 | ) |
| 293 | 298 | |