Portafolio / Ingeniería de datos
Sin interfaz, sin marca, sin una sola pantalla.
Un negocio de logística y procurement necesitaba con quién hablar: fabricantes y distribuidores industriales de nicho, los que no aparecen en un directorio general. Esa lista existe repartida en un blue book industrial, pero armarla a mano es abrir resultados, entrar a cada ficha, copiar los datos, visitar el sitio de la empresa y buscar un correo. Construimos el pipeline que hace esos cinco pasos solo y entrega un CSV: 720 empresas únicas, 12 campos cada una, 0 duplicados.

01El encargo
La lista existía. Armarla, no.
Vender servicios de logística y procurement a la industria empieza por saber a quién llamar, y ahí el problema no es la falta de información: es que está desperdigada. Un blue book industrial tiene miles de fabricantes clasificados por lo que producen, pero navegarlo es abrir una búsqueda, entrar a una categoría, pasar de página en página, abrir cada ficha y copiar a mano lo que sirve.
El encargo fue automatizar ese recorrido completo para un equipo comercial que necesitaba prospectar por categoría de producto, no por nombre de empresa. No querían un software: querían la lista, con teléfono, sitio y —si se podía— correo, en un archivo que pudieran abrir y repartir el lunes.
Lo que el pipeline tenía que resolver
- 01Buscar por categoría de producto, no por empresa
- 02Recorrer resultados repartidos en muchas páginas
- 03Descartar el perfil que aparece en dos categorías
- 04Extraer datos que viven en la ficha del directorio
- 05Completar el correo, que casi nunca está en la ficha
- 06Poder correr otra vez sin repetir lo ya hecho
Nuestro rol
Diseño del pipeline por etapas, desarrollo en Python, integración con el servicio de extracción, parseo y normalización de los campos, control de duplicados, procesamiento incremental por lotes, concurrencia con escritura segura y entrega del dataset en CSV.
02El punto de partida
Cinco pasos a mano, por cada empresa.
El proceso que se reemplazó no era complicado: era largo. Cada empresa costaba unos minutos, y unos minutos por setecientas empresas es una persona ocupada dos semanas en copiar y pegar.
La búsqueda no da empresas: da categorías.
El directorio devuelve páginas de producto, y detrás de cada una hay un listado propio de fabricantes, también paginado. Son dos niveles de navegación antes de ver la primera ficha útil.
Doce campos, uno por uno.
Razón social, dirección completa y desglosada, actividad, teléfono, fax y sitio. Copiar eso a mano es donde aparecen los errores silenciosos: la celda corrida, el estado que quedó en la columna del código postal.
El correo casi nunca está en la ficha.
El directorio publica el sitio web, no el correo. Conseguirlo implica abrir cada sitio y buscarlo — el paso que más tiempo consume y el primero que se abandona cuando la lista es larga.
03La regla
Lo que separa un script de un pipeline.
Un scraper se juzga la segunda vez.
La primera corrida siempre funciona. El problema aparece cuando hay que ampliar la lista con otra consulta, o retomar después de que el proceso se cayó a mitad de camino: si el script vuelve a empezar de cero, cada ejecución cuesta lo mismo que la primera y el dataset se llena de repetidos.
Por eso el diseño arranca al revés. Antes de pedir nada, el pipeline lee lo que ya tiene: compara los perfiles del listado contra los que ya están en el CSV y procesa solo la diferencia, en lotes de tamaño configurable. Los enlaces se desduplican con conjuntos en cada etapa. En el dataset entregado eso se mide: 720 registros, 720 enlaces únicos, 0 duplicados.
LeerCompararProcesar la diferencia
04El sistema
De una palabra escrita a un archivo repartible.
Cuatro etapas, cada una con su archivo de salida. Que el estado intermedio viva en disco no es un detalle de implementación: es lo que permite parar, revisar qué encontró y retomar sin volver a pedir nada.
query.txt
La consulta de productoZyte API
Capa de extracción remotaParseo por expresiones
Campos y enlacesWorkers en paralelo
Fichas y sitios a la vezEscritura con lock
Un CSV, muchos hilosbusinessDetails.csv
El entregable
- 01
Leer la consulta y contar
El pipeline lee la búsqueda de query.txt, normaliza los espacios, la codifica y pide la primera página. De ahí saca el total de resultados y calcula cuántas páginas hay que recorrer: no está atado a un número fijo.
- 02
Descubrir las categorías
Recorre las páginas de resultado y extrae los enlaces de categoría de producto, quitando los repetidos con un conjunto. Quedan guardados en searchLinks.txt para poder revisarlos antes de seguir.
- 03
Descubrir las empresas
Cada categoría tiene su propio listado paginado de fabricantes. El pipeline detecta cuántos hay, los recorre todos y acumula los perfiles en businessLinks.txt. Una empresa que aparece en tres categorías entra una sola vez.
- 04
Extraer la ficha
De cada perfil salen los 12 campos: razón social, dirección completa y desglosada en calle, ciudad, estado y código postal, actividad, teléfono, fax y sitio. Los perfiles ya presentes en el CSV se saltan.
- 05
Buscar el correo en el sitio
La segunda pasada visita los sitios encontrados, les añade el protocolo si les falta y busca direcciones de correo en el contenido. Se normalizan a minúsculas, se descartan dominios de terceros y extensiones de archivo que parecen correo, y se admiten varias por empresa.
- 06
Actualizar el archivo
El enriquecimiento no genera un archivo nuevo: actualiza el existente. Separar extracción de enriquecimiento permite volver a correr solo la parte que falló, que en scraping es casi siempre la de los sitios ajenos.
4 etapas · 12 campos por empresa · lotes de tamaño configurable
05El entregable
Lo que salió del primer encargo.
Cifras del dataset entregado, contadas sobre el archivo: una sola consulta de producto produjo este volumen. La cobertura por campo se publica completa, incluida la del correo, que es la más baja y la más honesta de mostrar.
- 720
- Empresas únicas en el dataset
- 667
- Registros con sitio web
- 158
- Registros con correo tras el enriquecimiento
- 0
- Enlaces de perfil duplicados
06Ingeniería
Tres decisiones que se notan a las setecientas.
A veinte empresas cualquier implementación sirve. Las decisiones de abajo no cambian nada en una prueba pequeña y son la diferencia entre terminar y no terminar cuando el listado crece.
Los sitios ajenos se esperan en paralelo.
Tanto las fichas como los sitios de empresa se procesan con varios workers a la vez. El cuello de botella de un scraper no es el procesador: es el tiempo que tarda en contestar el servidor del otro, y eso se resuelve esperando a varios a la vez.
Un solo archivo, muchos hilos.
Todos los workers escriben en el mismo CSV, así que la escritura pasa por un lock. Sin él, dos hilos guardando a la vez producen filas partidas — y un archivo corrupto en la fila cuatrocientos se descubre tarde y cuesta la corrida entera.
Lo que falla se reporta, no se traga.
Petición fallida, HTML vacío, ficha sin código, sitio inalcanzable, correo inexistente: cada caso se informa en consola en vez de contarse como éxito. Un dataset que no dice qué se le escapó no se puede auditar.
07Las piezas
El proceso que no se puede fotografiar.
| Empresa | Actividad | Contacto | Estado |
|---|---|---|---|
| Ridgeline Fabrication Co. | Metal estampado | ventas@***.example | Capturado |
| Cobalt Valve & Fitting | Válvulas industriales | info@***.example | Enriquecido |
| Harrow Industrial Supply | Suministro MRO | sin sitio publicado | Sin correo |
| Cobalt Valve & Fitting | Válvulas industriales | perfil ya procesado | Descartado |
| Westbrook Polymer Works | Moldeo por inyección | contacto@***.example | Enriquecido |
Reconstrucción de una corrida: las etapas se recorren, las empresas caen con su estado, el perfil repetido se descarta y el contador llega al lote antes de escribir el archivo. Las empresas y los correos son inventados — los reales son datos de contacto de terceros y no se publican.
| Empresa | Estado del registro | Campos | Correo |
|---|---|---|---|
| Ridgeline Fabrication Co. | Completo | Dirección · teléfono · fax · sitio | 1 correo |
| Cobalt Valve & Fitting | Completo | Dirección · teléfono · sitio | 3 correos |
| Harrow Industrial Supply | Sin sitio | Dirección · teléfono · fax | — |
| Westbrook Polymer Works | Completo | Dirección · teléfono · sitio | 1 correo |
| Pinehurst Gear & Drive | Sitio sin correo | Dirección · teléfono · fax · sitio | — |
Las empresas y los correos son inventados; la estructura y la cobertura son las del entregable real. 35 registros del dataset tienen más de un correo, y el campo se guarda como lista, no como texto suelto.
La forma real del entregable: cobertura por campo arriba y una fila por empresa abajo, con el estado del enriquecimiento. Es lo que el equipo comercial abre el lunes — un CSV, no un tablero.
08El límite
Hasta dónde llega un scraper.
Un proyecto de extracción se define tanto por lo que recoge como por lo que decide no recoger. Estas tres reglas se acordaron antes de escribir la primera línea, no después del primer problema.
Nada detrás de un login.
El pipeline lee lo que el directorio y los sitios de empresa publican abiertamente: el correo comercial que una empresa pone en su web está ahí para que la contacten. No hay credenciales, ni sesiones, ni acceso a nada que exija identificarse.
La extracción pasa por una capa de servicio.
Las páginas del directorio se piden a través de un servicio de extracción en vez de martillar el origen desde una sola dirección. El objetivo es completar el recorrido sin degradar el sitio del que se lee.
Ni siquiera en este caso.
Las empresas y los correos que aparecen en las maquetas de esta página son inventados. El dataset real son datos de contacto de terceros: se entrega al cliente que encargó la búsqueda y no se reproduce en un portafolio.
09El estado
Entregado, y con la lista de lo que sigue.
El pipeline está entregado y funcionando: corre por etapas, se puede parar y retomar, y produce el CSV con los 12 campos por empresa. La cobertura del enriquecimiento es la que es —158 de 720 registros con correo— y así se reporta, porque un sitio que no publica su dirección no la publica por más veces que se le pida.
Lo que sigue está identificado: cambiar el parseo por expresiones regulares a un analizador de HTML de verdad, añadir reintentos con espera creciente, registrar la ejecución en un log estructurado en vez de en consola, mover el dataset a una base de datos cuando el volumen lo pida, y añadir validación de correo a nivel de dominio. Ninguno de esos cambios altera el diseño por etapas: entran dentro de él.
Cómo está construido
- 01Python 3.11
- 02Peticiones con requests
- 03Extracción vía Zyte API
- 04Expresiones regulares
- 05ThreadPoolExecutor · locks
- 06Entorno de ejecución en Replit
- 07Estado intermedio en archivos de texto
- 08Entrega final en CSV
Qué no afirma este caso
No hay cifras de respuesta, reuniones ni contratos cerrados. El pipeline entrega la lista; la prospección la hace el equipo comercial del cliente, y ese resultado no es nuestro para publicarlo. Tampoco es un producto con interfaz: es una herramienta de línea de comandos, y se presenta como tal.
Sigue el trabajo
El software que nadie ve es el que decide cuántas horas cuesta el lunes.
Prospección, migraciones, catálogos, conciliaciones: hay trabajo que no necesita una pantalla, necesita que deje de hacerse a mano. Y esos proyectos se juzgan por si aguantan la segunda corrida.
Cuéntanos tu proyecto