SPB Git

spb/lou-ka

Public

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

page 1
  1. Sun, Sep 13, 2026 2

    1. [ka2] fix connecteur boreal_abitibi: contournement du challenge sgcaptcha SiteGround via proxy résidentiel Oxylabs. Le sync du 2026-09-13 01:07 échouait honnêtement (« ajax_object introuvable sur /locations/ », ok=0) : SiteGround sert désormais son anti-bot sgcaptcha (HTTP 202 + meta refresh vers /.well-known/sgcaptcha/, en-tête sg-captcha: challenge) à l'IP datacenter du nœud — un 2xx qui ne lève pas d'HTTPError, donc invisible du wrapper résilient (même angle mort que brio/Sucuri 195f19a). Vérifié live : le challenge frappe tout UA depuis notre IP (76.70.60.50 flaguée « ipr/ipc »), mais une IP résidentielle Oxylabs CA passe (200, 52 Ko, ajax_object présent) et le POST admin-ajax get_rents fonctionne sur la même session collante (nonce af45b697e0 → 1 rent). Fix minimal dans le connecteur : _get_html() détecte le challenge (en-tête sg-captcha ou marqueur /.well-known/sgcaptcha/) et bascule la session sur pr.oxylabs.io:7777 en session collante -cc-CA (nonce + POST admin-ajax + fiches détail partagent l'IP, pattern fb_marketplace/_resilient), erreur franche si le challenge persiste ; _fetch_detail() lève aussi sur challenge pour ne pas empoisonner detail_cache avec un payload vide (clé figée jamais invalidée). Le chemin direct reste tenté d'abord (gratuit si SiteGround déflague l'IP). Testé : fetch() venv → 1 annonce (App. 205 Esplanade Val-d'Or, 3½, 1 465 $, dispo octobre, 11 photos — médiane 1.0), pytest fixtures 2 passed, run.py sync boreal_abitibi → found=1 ok, pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher · 1 file +42 −2
  2. Fri, Sep 11, 2026 2

    1. Revert "[ka2] fix connecteur vision_immo: échec honnête au lieu d'un « 0 trouvé ok » qui a déjà dépublié les 6 annonces. Le sync du 2026-09-11 10:43 a rapporté found=0 ok=1 missed=6 (médiane 6, stale) : fetch() avalait toute exception sur la page liste (`except Exception: return []`) — un échec réseau transitoire devenait un succès à 0, invisible du disjoncteur. L'historique montre le coût réel : pendant la panne DNS systémique du 2026-09-10 (14:17 et 15:22), deux « 0 ok » silencieux ont abouti à removed=6 — les 6 annonces dépubliées puis re-publiées au sync suivant. Reproduit en live : la source est SAINE (page 200, 177 Ko, 6 liens /logements/), seul le silence sur erreur était fautif — même situation que thrace e5379b0 et novelo 6bf26bd, distinct du cas lienard (rollback d1571fc, source en panne). Fix : (1) fetch() laisse remonter les exceptions réseau (ingest journalise ok=0) et lève RuntimeError si 0 lien parsé ET formulaire de filtres Search & Filter absent (rendu partiel/refonte) — un vrai zéro (0 lien mais squelette présent) reste possible car la page ne liste que les unités offertes ; (2) _parse_detail() ne retourne plus {} sur exception : detail() aurait mis ce {} en cache PERMANENT (clé figée « v1 », jamais invalidée) et l'unité aurait disparu pour toujours — vérifié : cache actuel sain, 7 payloads complets. Testé : fetch() venv → 6 annonces (4½ Terrebonne 1 720 $, 4½ Lachine 1 995 $, 3½ St-Henri 1 395 $, 4½ J180 2 195 $, 5½ 2 395 $, 6½ 2 695 $), run.py sync vision_immo → found=6 ok, pm2 restart lou-ka-sync, site :8095 → 200."
      …
      This reverts commit 602ff085f8e5b57320fc15852598d73d6a057a76.
      Simon-Pierre Boucher · 1 file +8 −15
    2. [ka2] fix connecteur vision_immo: échec honnête au lieu d'un « 0 trouvé ok » qui a déjà dépublié les 6 annonces. Le sync du 2026-09-11 10:43 a rapporté found=0 ok=1 missed=6 (médiane 6, stale) : fetch() avalait toute exception sur la page liste (`except Exception: return []`) — un échec réseau transitoire devenait un succès à 0, invisible du disjoncteur. L'historique montre le coût réel : pendant la panne DNS systémique du 2026-09-10 (14:17 et 15:22), deux « 0 ok » silencieux ont abouti à removed=6 — les 6 annonces dépubliées puis re-publiées au sync suivant. Reproduit en live : la source est SAINE (page 200, 177 Ko, 6 liens /logements/), seul le silence sur erreur était fautif — même situation que thrace e5379b0 et novelo 6bf26bd, distinct du cas lienard (rollback d1571fc, source en panne). Fix : (1) fetch() laisse remonter les exceptions réseau (ingest journalise ok=0) et lève RuntimeError si 0 lien parsé ET formulaire de filtres Search & Filter absent (rendu partiel/refonte) — un vrai zéro (0 lien mais squelette présent) reste possible car la page ne liste que les unités offertes ; (2) _parse_detail() ne retourne plus {} sur exception : detail() aurait mis ce {} en cache PERMANENT (clé figée « v1 », jamais invalidée) et l'unité aurait disparu pour toujours — vérifié : cache actuel sain, 7 payloads complets. Testé : fetch() venv → 6 annonces (4½ Terrebonne 1 720 $, 4½ Lachine 1 995 $, 3½ St-Henri 1 395 $, 4½ J180 2 195 $, 5½ 2 395 $, 6½ 2 695 $), run.py sync vision_immo → found=6 ok, pm2 restart lou-ka-sync, site :8095 → 200.
      Simon-Pierre Boucher · 1 file +15 −8
  3. Thu, Sep 10, 2026 1

  4. Wed, Sep 9, 2026 1

    1. [ka2] fix connecteur groupe_theoret: réécriture pour la refonte du site (GoDaddy Website Builder → GoDaddy Airo, ~2026-09-09) — le widget « menu » n'existe plus. Le sync de 15:40 a rapporté found=0 ok=1 (médiane 23, retraits suspendus) : reproduit en live, l'URL accentuée /appartements-%C3%A0-louer redirige 301 vers /appartements-a-louer et la nouvelle page (React Router, 88 Ko) ne contient plus aucun marqueur data-aid MENU_SECTION_*. Le nouveau site embarque TOUT le catalogue dans le payload d'hydratation window.__staticRouterHydrationData (données créées le 2026-09-01, unités ajoutées encore aujourd'hui) : 40 immeubles avec adresse + ville + code postal + slug /proprietes/<slug> + services + photos (/airo-assets/images/<slotKey>, vérifiées 200 image/jpeg) + contact, et par unité DISPONIBLE un id stable, le type, le loyer et la date de dispo ISO. Nouveau fetch() : une seule requête (plus de pages immeuble ni de cache détail), extraction du littéral JS par regex tolérante aux guillemets échappés puis double json.loads, external_id=u<id> (clé BD du site), RuntimeError si le payload est absent ou sans immeuble (une page saine embarque toujours les ~40 immeubles même à 0 dispo — même pattern que c3r/brio). Gain net vs l'ancien site : photos 25/25 (avant 0 %), inclusions 25/25, contact 24/25, code postal systématique. Testé : run.py sync groupe_theoret → found=25 ok (médiane 23, added=25 — nouveaux ids, les 23 anciennes annonces seront dépubliées par les retraits), fixtures ré-enregistrées (record → 1 requête, 25 annonces ; pytest 2 passed), pm2 restart lou-ka-sync, site :8095 → 200. sources.json : listing_url → /appartements-a-louer.
      …
      Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
      Simon-Pierre Boucher · 18 files +364 −8,785
  5. Tue, Sep 8, 2026 4

    1. [ka2] fix connecteur c3r: réécriture pour la refonte du site (Wix → Astro, 2026-09-08) — l'API wix-data n'existe plus. Le sync de 12:32 a rapporté found=0 ok=1 (médiane 8, retraits suspendus) : reproduit en live, les collections Wix Import1/Import2 renvoient 404 WDE0025 « collection does not exist » et les anciennes URLs d'unités (/terrasses-st-maurice/…) répondent 302 → /logements. Gestion C3R a lancé aujourd'hui (sitemap lastmod 2026-09-08) un nouveau site statique Astro servi par Express : catalogue /logements?page=N paginé côté serveur (5 pages, 73 unités, 4 projets — Chemin du Lac, Terrasses St-Maurice, Rue des Tournesols, Maisons St-Bo), chaque unité en <article data-rental-unit> avec data-city/project/bedrooms/price/status + type, adresse, sdb, superficie, photo. Nouveau fetch() : pagination avec dédup par slug (au-delà de la dernière page le serveur re-sert la même page), décodage UTF-8 forcé (pas de charset dans les en-têtes → requests décodait « Loué » en « Loué »), filtre statut Disponible conservé, RuntimeError si 0 carte parsée (garde contre rendu partiel/structure changée, même pattern que brio/le_fjord). Testé : parsing 73/73 unités (prix 73, adresses 73, sdb 73, superficie 73, photos 65), found=0 en prod — VRAI zéro : les 73 unités du nouveau site sont toutes « Loué », y compris les 8 qui étaient « Disponible » ce matin sur l'ancien CMS. Le garde-fou lèvera la suspension des retraits après le 3e sync à 0 (DRIFT_HISTORY=5) et les 8 annonces périmées seront dépubliées naturellement. pm2 restart lou-ka-sync, site :8095 → 200. sources.json : listing_url → /logements, + Shawinigan.
      …
      Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
      Simon-Pierre Boucher · 2 files +112 −124
  6. Mon, Sep 7, 2026 2

  7. Sun, Sep 6, 2026 3

  8. Sat, Sep 5, 2026 1

    1. Simon-Pierre Boucher · 2 files +7 −7
  9. Fri, Sep 4, 2026 8

    1. feat(fiche): refonte premium mobile-first de la fiche logement (2026-09-04)
      …
      Frontend (frontend/src/fiche/, nouvelle arborescence) : héro prix → adresse →
      résumé → galerie → actions ; Lou-Ka Score (60 % KA Score emplacement + 40 %
      prix vs juste valeur, partiel si une composante manque) ; « En bref »
      déterministe (prix, accessibilité, air, inondation, coûts, TAL, chaleur,
      baisse de prix) ; navigation sticky par sections (scroll-spy) ; Prix et marché
      (juste valeur + histogramme) ; Le logement (grille icône/valeur) ; description
      tronquée + texte original ; inclusions dédoublonnées FR/EN ; grande carte 3D
      Ka Maps avec filtres de lieux (transport, épiceries, pharmacies, commerces,
      écoles, parcs, essence) ; À proximité / Transport en carrousels + bottom sheet ;
      Quartier en KPI compacts + accessibilité en lignes ; KA Scores compacts ;
      Registre des loyers orienté décision (jauge p10–p90, médianes par chambres,
      3 comparables + sheet filtrable) ; coût réel + Hydro ; risque d'inondation
      (statut clair, juridique en accordéon) ; qualité de l'air en tuiles ; essence
      (3 stats, 3 stations, sheet) ; Dossier de l'immeuble en accordéons (historique,
      passeport, gestionnaire, TAL, hiver) ; Sources et méthodologie + fin de fiche.
      Primitives : SectionCard, Accordion, BottomSheet (modale ≥ 900 px), StatTile,
      StatusBadge, Skeleton, états vides/erreur, toast. Données : useFicheData
      (groupe critique au montage, groupe différé à l'approche de la carte).
      Tokens --lk-* scopés (.lk-fiche) : fond #F7F7F5, cartes blanches bord 1 px,
      ombres légères, rayons 10/14/18/22, orange réservé CTA/prix/score. Desktop
      ≥ 1024 : aside sticky (prix, CTA, score, constats, Demander à Ka). CTA sticky
      compact affiché seulement après le héro ; bouton « ✦ Demander à Ka » discret
      branché sur le widget KA Agent existant (contexte de la fiche transmis).
      Header compact sur la fiche (56 px, ticker masqué, favoris + partage,
      connexion en icône sur mobile). Aucun `order` CSS ; scrollIntoView banni de la
      barre de sections (faisait ouvrir la page à 434 px). Anciennes classes
      .fiche/.f-* intactes pour la fiche court terme. 16 anciens composants de fiche
      supprimés (remplacés). check-order.mjs mis à jour + shots.mjs / interactions.mjs.
      
      Backend (additif, rétrocompatible) : poi.py conserve lat/lng des POI (carte) ;
      gaz.py expose lat/lng des stations ; /api/gaz et /api/rdl acceptent `limit`
      (sheets « Voir les N »). vite.config : proxy /api paramétrable (LOUKA_API).
      
      Validé : tsc + vite build, check-order OK (scrollY 0, ordre croissant, sans
      overflow 375→1440), captures Playwright 6 largeurs, sheets/carte/Ka/404,
      fiche sans KA Score. node_modules frontend réinstallés (typescript/esbuild
      tronqués par ka2 le 2026-08-31 pour ENOSPC).
      Simon-Pierre Boucher · 54 files +4,182 −2,266
    2. Simon-Pierre Boucher · 32 files +2,862
    3. Simon-Pierre Boucher · 4 files +187 −38
  10. Sun, Aug 30, 2026 5

  11. Sat, Aug 29, 2026 4

  12. Fri, Aug 28, 2026 2

    1. Simon-Pierre Boucher · 11 files +40 −9
  13. Thu, Aug 27, 2026 5

    1. feat(scraping): migration Firecrawl -> Scrapfly des 6 connecteurs a rendu JS
      …
      - base.get_rendered : rendu via Scrapfly (render_js+ASP), wait_ms = ancien
        waitFor Firecrawl, retry x3 sur contenu vide puis echec honnete ;
        FIRECRAWL_API retire du socle
      - aalto/osgoode/brigil/realstar : _rendered delegue au socle (retry centralise)
      - realstar/osgoode/brigil : selecteur li[class*=property-box] — le rendu
        Scrapfly capture le DOM avant que le JS RentCafe ne revele les cartes
        (property-box-hidden), qui sont completes ; filtre QC en aval inchange
      - via_capitale : CARD_SPLIT accepte les hrefs relatifs (serialisation
        Scrapfly) en plus des absolus (fixtures Firecrawl historiques)
      - fixtures record/replay : get_rendered accepte wait_ms (cle de rejeu = URL)
      - fixtures re-enregistrees via Scrapfly : aalto 24, osgoode 4, brigil 12,
        realstar 9 ; rejeu test_connectors 10/10
      - gen_connector_docs : backend get_rendered documente Scrapfly (ex-Firecrawl)
      
      Valide en live : aalto 24, lynk_olymbec 4, via_capitale page 1 = 34 cartes.
      Lou-Ka ne depend plus de FIRECRAWL_API_KEY.
      Simon-Pierre Boucher · 133 files +230,045 −602
    2. pause(ontario): expansion ON suspendue temporairement — rien d'effacé
      …
      - .env : LOUKA_ONTARIO=1 commenté (les 56 connecteurs gatés sortent du registre)
      - sources.json : 65 sources ON -> status pause + note_pause
      - quality.evaluate : quarantaine pause-ontario (published=0) pour province=ON
        tant que le flag n'est pas reposé ; province ajoutée au backfill et à
        l'évaluation à l'ingestion (db.py)
      - docs/ONTARIO-PAUSE.md : quoi/pourquoi/comment réactiver
      
      5 851 annonces ON conservées en base, dépubliées. QC intact (62 412 publiées).
      Simon-Pierre Boucher · 4 files +228 −133
    3. Simon-Pierre Boucher · 1 file
Menu

Theme