BookinglyTech News
Software

PigData convierte 500 proyectos de scraping a medida en una API autoservicio

La empresa japonesa pasa de vender extracción de datos gestionada a ofrecer un SDK en PyPI, con Django, Celery y RabbitMQ detrás y un pipeline de cuatro etapas orquestado por máquina de estados.

3 min de lecturaDev.to0 vistas

PigData lleva años vendiendo extracción de datos como servicio gestionado en Japón: más de 500 proyectos a medida para clientes de automoción de primer nivel, comercio electrónico y banca. El problema era que cada encargo empezaba de cero. Cuando dos clientes necesitaban listados de producto, el equipo reescribía la misma lógica de parseo, las mismas rutinas de navegador y los mismos bucles de reintento contra sistemas antibot.

Han tardado seis meses en convertir ese catálogo en una API autoservicio, Scraping AI, con SDK publicado en PyPI. La promesa es que un equipo pase de tres líneas de código a datos estructurados sin un ciclo de ventas de tres semanas de por medio.

La pila y el pipeline

Django REST Framework en la capa de API, Celery y RabbitMQ para el trabajo asíncrono distribuido, PostgreSQL como almacén de estado y S3 o MinIO para las exportaciones. La empresa justifica seguir en Python en 2026 por dos razones poco glamurosas: httpx, BeautifulSoup, pydantic, openai y google-genai se usan sin serialización entre lenguajes, y el admin de Django da visibilidad inmediata sobre tareas atascadas y pipelines fallidos sin tener que construir herramientas internas.

El recorrido de cada trabajo es una máquina de estados. Arranca con palabras clave o una consulta y pasa por cuatro etapas: un buscador de URLs que explora el grafo de enlaces hasta una profundidad máxima, un crawler que descarga HTML con httpx o navegador headless, un ranker que ordena las páginas combinando BM25 con embeddings vectoriales, y un extractor que aplica un JSON Schema con GPT-4o o Gemini. La salida es JSON o CSV.

Todo el estado vive en un único modelo, InputState, con un campo por etapa (keyword_generator_status, url_crawler_status, url_ranker_status y así hasta seis). Eso permite consultar en cualquier momento por dónde va un trabajo y montar la misma infraestructura para 10 tareas o para 10.000 concurrentes, que era el requisito de partida.

Dos choques con la concurrencia

Con decenas de workers de Celery tocando los mismos registros, varios intentaban actualizar el mismo InputState a la vez y se perdían escrituras. La solución fue bloqueo optimista: un campo version en un modelo base VersionedModel; el save() hace un UPDATE condicionado a la versión que leyó el worker y lanza ConcurrencyError si otro llegó antes. Barato y sin locks de base de datos. La documentación del servicio recoge el resto del flujo.

El segundo choque fue el rendimiento de escritura: llamar a save() del ORM dentro de bucles no aguanta según qué volúmenes, y lo atacaron con un gestor de concurrencia que agrupa inserciones y actualizaciones. De esta parte queda menos detalle del que uno querría, porque el texto se corta justo al entrar en el ConcurrencyManager.

Qué se puede sacar

El material es a la vez retrospectiva de ingeniería y folleto: ofrece 200 tokens gratis sin tarjeta y la cifra de los 500 proyectos es suya, no de un tercero auditando. Lo aprovechable está en el patrón, no en el producto. Una máquina de estados versionada en base de datos es una forma razonable de coordinar pipelines largos con muchos workers, y el bloqueo optimista que describen es el mismo truco que usan media docena de colas de trabajo para no pelearse por la misma fila.