spb/auto-ka Public
Python 82.8%
TypeScript 11.9%
CSS 5.1%
1# -----------------------------------------------------------------------------2# Auto-Ka — Agrégateur de voitures usagées à vendre (province de Québec)3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# connectors/convertus_fc.py : concessionnaires WordPress « Convertus »5# (thème achilles) protégés par Cloudflare — accès via Firecrawl.6#7# Même API VMS que clubautozone.py (proxy officiel du site8# ajax-vehicles.php -> vms.prod.convertus.rocks), mais chaque appel passe9# par Firecrawl pour franchir Cloudflare. Le JSON revient enveloppé dans10# un <body> HTML — on l'extrait puis on réutilise le parseur VMS.11# -----------------------------------------------------------------------------12from __future__ import annotations1314import json15import re16import urllib.parse1718from ..schema import Vehicle19from .clubautozone import ClubAutoZone2021_VMS_API = "https://vms.prod.convertus.rocks/api/"22_PROXY = "/wp-content/plugins/convertus-vms/include/php/ajax-vehicles.php"232425class ConvertusFirecrawlConnector(ClubAutoZone):26 """Hérite du parseur VMS de ClubAutoZone ; fetch via Firecrawl."""2728 source_id = "" # base abstraite : non enregistrée29 inventory_id = 03031 def _page(self, pg: int) -> dict:32 endpoint = (f"{_VMS_API}filtering/?cp={self.inventory_id}"33 f"&ln=fr&sc=used&pg={pg}&pc=100")34 url = (f"{self.base_url}{_PROXY}"35 f"?endpoint={urllib.parse.quote(endpoint, safe='')}"36 f"&action=vms_data")37 html = self.get_rendered(url)38 # le JSON est enveloppé dans <body>…</body> par le rendu Firecrawl39 m = re.search(r"<body[^>]*>(.*)</body>", html, re.S)40 payload = (m.group(1) if m else html).strip()41 try:42 return json.loads(payload)43 except ValueError:44 return {}4546 def _resolve_inventory_id(self) -> None:47 """Lit globalVars.inventoryId sur la page inventaire si inconnu."""48 if self.inventory_id:49 return50 html = self.get_rendered(f"{self.base_url}/vehicles/used/")51 m = re.search(r'inventoryId"\s*:\s*"?(\d+)', html)52 if not m:53 raise RuntimeError("inventoryId introuvable")54 self.inventory_id = int(m.group(1))5556 def fetch(self) -> list[Vehicle]:57 if not self.source_id:58 return []59 self._resolve_inventory_id()60 return super().fetch()616263class BernieresAuto(ConvertusFirecrawlConnector):64 source_id = "bernieresauto"65 base_url = "https://www.bernieresauto.com"66 dealer_name = "Bernières Auto"67 city = "Saint-Nicolas"68 inventory_id = 1305697071class AutoFlash(ConvertusFirecrawlConnector):72 source_id = "autoflash"73 base_url = "https://www.autoflash.net"74 dealer_name = "AutoFlash"75 city = "Saint-Hubert"76 inventory_id = 1306777879class ComplexeAutoPlus(ConvertusFirecrawlConnector):80 source_id = "complexeautoplus"81 base_url = "https://www.complexeautoplus.com"82 dealer_name = "Complexe Auto Plus"83 city = "Saint-Jérôme"84 inventory_id = 85585