Scrape vehicle listings from PolovniAutomobili.com, Serbia's largest car marketplace. Extract price, make, model, year, mileage, fuel type, dealer/private seller info, and photos. Essential for Serbian and Balkan automotive market research.
Changelog — Polovni Automobili Scraper — Serbia Vehicle Listings
Unreleased — convención tiempo_uso
Formato intacto (tiempo_uso/hours = "890,000 km"). Nuevas ext_tiempo_uso_unidad (km|null) y ext_tiempo_uso_calidad (unidad_sin_confirmar|null) en live y preloaded (_apply_uso, idempotente, snapshots english y ftp28). Preloaded ftp28 rellena tiempo_uso desde ext_km si faltara. Declaradas en dataset_schema.
2026-10-03 — checkpoint por mes/categoría + escritura incremental
scrape_category es ahora un generador por página (start_page, PageFetchError). Un 403/429 o fallo de red persistente en una página ya no se interpreta como fin de categoría: la categoría queda incompleta y NO se marca done.
Escritura incremental: cada página se empuja (dataset nombrado en admin, Actor.push_data en cliente) en cuanto se parsea, en lotes; antes se acumulaba la categoría entera en memoria.
Checkpoint (solo admin): store nombrado polovni-checkpoints, clave CHECKPOINT_{YYYY-MM}_{categoria}, last_page/done, flush cada 3 páginas y en MIGRATING/ABORTING/PERSIST_STATE. Relanzar en el mismo mes salta las categorías done y reanuda desde la última página; la dedup por item_id del dataset evita duplicados. Los runs no admin no usan checkpoint.
Carga de IDs existentes con load_existing_ids (solo campos de ID).
Nuevo input oculto _snapshot_dataset_name (admin): dataset de prueba, claves de checkpoint propias ({dataset}__{categoria}) y no publica puntero.
Log [ckpt] RESUMEN con las categorías incompletas y incomplete_categories en SUMMARY. Formato de salida FTP-28 y puntero sin cambios.
Revisión (ronda 2): 200 sin __NEXT_DATA__ (challenge) y 404 persistente en p1 => categoría incompleta, no done; 404 se reintenta 1 vez y en p>1 es fin natural (H1). load_existing_ids con 3 intentos y abort (RuntimeError) antes de escribir si falla (H2). finally robusto: gen.close() tolera ValueError y la sesión siempre se cierra (H4).
_snapshot_dataset_name con patrón de producción polovni-YYYY-MM => RuntimeError (H5). La clave de checkpoint incluye el sort si no es basic ({categoria}__{sort}); apify>=2.3.1 (H6).
Revisión 2 (N1): p1 con __NEXT_DATA__ pero 0 anuncios extraíbles, o anuncios sin id en cualquier página => PageFetchError (incompleta), no done con 0 items. Residual documentado: p>1 con __NEXT_DATA__ y 0 anuncios = fin natural; si una categoría grande sale done con pocos items, borrar su clave CHECKPOINT.
Ronda 3 (reanudar donde murió): checkpoint en cada página (every=1, ~770 escrituras KV por run completo). Una página p>1 vacía (200 sin anuncios o 404 persistente) ya no marca done: si page > total_pages (de pagination en __NEXT_DATA__ o del checkpoint) es fin natural; si no, 1 reintento y queda last_page=k-1, pending_end=k, incompleta. El relanzamiento pide k: con datos sigue paginando; vacía otra vez => fin confirmado. Sustituye al residual N2 sin reset manual. rastriq_ckpt: state() y set_meta() (compatible).
Medición pendiente: prueba de corte, ver claude/polovni-ckpt-resultado.
2026-09-18 — build FTP-28: P1
Formato: que cambio, por que, y la medicion que lo respalda. Un cambio sin numero detras es
una opinion; en este repo no cuenta como entrada de changelog.
Las versiones son las de Apify (mayor.menor). La plataforma no admite numero de parche.
[0.5] — estado a 21 de agosto de 2026
Version activa en Apify, con tag latest. Exportada a este repo el 21 de agosto de 2026.
No se reconstruye aqui el historial anterior: inventarlo seria peor que no tenerlo. Lo que hay documentado de ciclos previos vive en el runbook de la fuente, en rastriq-docs/interno/runbooks/. A partir de esta entrada, todo cambio se anota aqui con su medicion.