SPB Git forge

spb/house-ka

Public
18commits 1branches 0releases
1.9 MBsize
maindefault branch
20 days agolast push
Python 67% TypeScript 18.2% CSS 14.4%
3.8 KB

# Providers de taux hypothécaires

Un connecteur indépendant par institution. Auto-découverte : tout module du dossier définissant une sous-classe de RateProvider avec un provider_id non vide est enregistré dans PROVIDERS automatiquement (aucun registre à éditer). La panne d'un provider n'affecte jamais les autres.

Règle absolue : aucun taux inventé. Un produit non confirmé sur la page officielle est simplement omis — jamais deviné, jamais de valeur par défaut.

# Ajouter une institution (8 étapes)

  1. Créer <slug>.py dans ce dossier, avec une sous-classe de RateProvider :

    python
    from .base import RateProvider
    
    class MaBanque(RateProvider):
        provider_id = "ma_banque"           # slug stable (clé BD)
        institution = "Ma Banque"           # nom d'affichage fr-CA
        source_url = "https://mabanque.ca/taux-hypothecaires"
    
        def fetch(self) -> list[dict]:
            html = self.get(self.source_url).text   # ou .json()
            return self.parse(html)
    
        def parse(self, html: str) -> list[dict]:
            ...  # → [self.make_product(...), ...]

    Séparer fetch() (réseau) de parse() (pur) : les tests appellent parse() sur des fixtures, sans réseau.

  2. Backend réseau : self.get(url) (requests + politesse request_delay) d'abord ; self.get_scrapfly(url, render_js=True) en dernier recours seulement si le site bloque (403/JS requis).

  3. Normaliser chaque produit via self.make_product(...) :

    • rate_type : fixed / variable — ou other pour tout taux préférentiel/prime/référence (avec purpose="unknown"), afin qu'il ne tombe jamais dans un classement « meilleur taux d'achat » ;
    • kind : posted (affiché) ou special (offre spéciale) — ne jamais confondre ;
    • insured_status : insured / insurable / uninsured, ou unknown si la page ne le précise pas — ne pas deviner ;
    • product_name en français, explicite (ex. « Fixe fermé 5 ans ») ;
    • apr (TAP) seulement s'il est publié.
  4. Aucune écriture BD dans le provider : le scheduler valide (validate_batch) puis enregistre (store.record_observations). Ne pas filtrer soi-même les aberrations — la validation s'en charge et journalise.

  5. Fixture : sauvegarder la réponse réelle (HTML/JSON) dans tests/fixtures/mortgage/<slug>.<ext> (anonymisée si besoin, taille raisonnable — garder le bloc utile).

  6. Test : ajouter le slug dans EXPECTED de tests/test_mortgage_providers.py (fixture + nombre exact de produits) ; le test générique vérifie déjà validation propre, source_url, institution et la règle « préférentiel → other/unknown ». Ajouter un test ciblé sur 1–2 valeurs connues de la fixture.

  7. Exécuter :

    bash
    PYTHONPATH=. .venv/bin/python -P -m unittest tests.test_mortgage_providers
    .venv/bin/python run.py mortgage-sync ma_banque   # collecte réelle
    .venv/bin/python run.py mortgage-status           # santé
  8. Vérifier en BD/API : GET /api/mortgage/rates?provider=ma_banque — provenance (source_url), fraîcheur et nature correctes. C'est tout : ni web.py, ni le scheduler, ni le frontend n'ont besoin d'être modifiés.

# Pièges connus

  • 4.19 % → 419 : toujours vérifier l'échelle ; la validation rejette

    24 %, mais un « 41,9 » passerait — parser au bon endroit.

  • Pages avec plusieurs onglets (assuré/non assuré) : étiqueter insured_status correctement plutôt que de tout mélanger.
  • Taux « ouverts » vs « fermés » : les distinguer dans product_name (ex. BNC publie « Fixe ouvert 1 an » à 9,65 % — ce n'est pas une erreur).
  • Ne jamais soumettre de formulaire ni simuler une demande de prêt : pages publiques de taux uniquement.