Scrape car listings from AutoScout24 in Germany, Italy, France, Spain, the Netherlands, Belgium, Austria and Luxembourg, or all Europe at once. Filter by make, model, price, year, mileage, fuel, gearbox, seller and location, or paste a search URL.
Retrocompatible: mismas claves canónicas, mismos defaults efectivos (maxItems 100, maxPages 20), mismo orden de items. Solo se añaden claves ext_* y se rellenan claves canónicas que antes salían siempre a null.
Fixes
Bélgica devolvía 0 items: la ruta /auto/{make} da 404. Ahora /fr/lst/{make} (HTML) y ruta JSON sin locale.
Suiza (ch, plataforma distinta, 403) y Portugal (pt, dominio sin respuesta) fallan al arrancar con mensaje claro, en vez de timeouts.
429 ya no puede entrar en bucle infinito: reintentos acotados (4) con backoff exponencial y rotación de sesión de proxy en 403/429/5xx/red/página de bloqueo.
power_hp solo leía "hp"; ahora PS/CV/CH/PK/KM → power_source pasa de kw_derived a field (valor más exacto).
maxItems: null ya no rompe el run (se trata como 100).
Vista Overview del dataset referenciaba campos inexistentes (ad_id, title, price_clean) → tabla vacía en Console. Corregida.
Mejoras
Ruta JSON de Next.js (/_next/data/{buildId}/lst/...json): ~4,5x menos transferencia por página; fallback a HTML si rota el buildId.
Páginas de una búsqueda en paralelo (maxConcurrency, defecto 3), emitidas en orden. No descarga páginas que maxItems no va a usar.
splitLargeSearches (opt-in): divide por rangos de precio las búsquedas con más de 4.000 resultados. Probado: 13.411 de 13.442 Fiat en DE (99,8 %; el resto, sin precio o rotación durante el run).
Paginación hasta 200 páginas (maxPages máx. 200; antes el límite real documentado era 20).
ALL_MAKES (cuando makes está vacío): +31 marcas verificadas al final de la lista (Citroën, Dacia, Mazda, Cupra, MINI, Suzuki, MG, BYD…). El orden de las 32 originales no cambia.
Parada temprana si el usuario alcanza su límite de coste PPE.
Campos
Canónicos antes siempre null: first_registration (YYYY-MM), co2_g_km, consumption_l_100km, seller_url.
Modo URL (urls): pegar búsquedas /lst/... de cualquier mercado; acepta strings o {"url": ...}; parámetros repetidos → listas con coma; .ch/.pt/URLs no válidas avisan con status message.
stripSellerPII (RGPD, por defecto off como en el resto del portfolio): anula teléfono, nombre, ids y URL de perfil de particulares y vendedores sin clasificar.
splitLargeSearches se desactiva solo si el orden pedido no es por relevancia/precio y maxItems ≤ 4.000 (una búsqueda ya da el top-N correcto).
Docs
README: precio real PPE ($3/1K + $0,05/start) en lugar de "CU pricing"; límite de 4.000 por búsqueda (antes decía 400 e "ilimitado"); datacenter proxy suficiente (antes recomendaba residencial); mercados soportados.
requirements.txt: fuera requests, beautifulsoup4, lxml (sin uso); dentro httpx.
No tocado
src/astara_schema.py (mapper canónico).
.actor/output_schema.json (no referenciado en actor.json; contenido desalineado, heredado).
seller_phone de particulares sigue saliendo por defecto (heredado); se anula con stripSellerPII.