Scraping

Cómo construir un dataset con web scraping

Una guía práctica para construir datasets web limpios y completos: etapas del pipeline, frescura, deduplicación, y por qué los bloqueos y los huecos geográficos sesgan tus datos en silencio.

Chris Collins

Chris Collins

23 de junio de 2026 · 13 min de lectura

La mayoría de las guías sobre construir un dataset mediante web scraping se quedan en “escribe un scraper, guarda los resultados”. Ese es el 20% fácil. El 80% difícil, la parte que decide si tu dataset es realmente usable, es todo lo que rodea al fetch: asegurarte de que recogiste las filas correctas, que están completas, que están actualizadas, y que los huecos en tus datos son aleatorios en lugar de sistemáticos.

Ese último punto es el que arruina datasets en silencio, y es el que casi nadie escribe. Cuando un scrape falla en el 30% de las páginas, no pierdes un 30% aleatorio de tus datos. Pierdes un 30% específico, la porción más difícil de alcanzar, más defendida, más geo-restringida, y lo que queda es una muestra sesgada que parece completa. Un modelo entrenado con ella, o una decisión tomada a partir de ella, hereda ese sesgo sin que nadie lo note.

Esta es una guía práctica para construir un dataset de web scraping que aguante: las etapas del pipeline, las dimensiones de calidad que importan, y dónde la capa de proxy es la diferencia entre un dataset representativo y uno sesgado.

Qué significa realmente “un buen dataset”

Antes de cualquier código, ten claro para qué optimizas. Un dataset construido a partir de scraping se juzga por cinco cosas:

Completitud. ¿Recogiste todo lo que estaba en el alcance, o solo las partes que no se resistieron? Las filas que faltan son malas; las que faltan sistemáticamente son peores.

Representatividad. ¿Coincide la muestra con la población real? Si scrapeas precios de productos pero tu scraper se bloquea en los grandes retailers de alto tráfico y pasa sin problema en los pequeños, tu “precio medio” está mal en una dirección que no puedes ver.

Frescura. Los datos web caducan. Un dataset de precios del mes pasado es un dataset distinto al de hoy. Necesitas saber cuán obsoleta es cada fila, y tener un plan para refrescarla.

Consistencia. Cada fila debería seguir el mismo esquema, con las mismas unidades, formatos y codificaciones. El scraping tira de HTML desordenado, así que la normalización es la mitad del trabajo.

Procedencia. Para cada fila: de dónde vino (URL de origen), cuándo la trajiste, y desde dónde (geo). Sin procedencia no puedes depurar, deduplicar, refrescar ni defender el dataset después.

Ten estas cinco en mente, porque cada decisión del pipeline de abajo está al servicio de una de ellas.

El pipeline, etapa por etapa

Un pipeline de scraping-a-dataset son seis etapas. Trátalas como pasos distintos con su propia validación, no como un único script gigante.

1. Descubrir. Enumera las URLs dentro del alcance, desde un sitemap, un crawl de búsqueda/listado, un índice de API, o un rango de IDs conocido. Esta etapa define tu población prevista. Anótala explícitamente; es tu vara de medir la completitud más tarde.

2. Fetch. Recupera cada URL. Aquí es donde ocurren los bloqueos, las geo-redirecciones, los rate limits y los timeouts, y donde nace el sesgo del dataset. Más sobre esto abajo, porque es la etapa que más importa para la calidad.

3. Extraer. Parsea la respuesta en campos estructurados. Sé defensivo: los layouts cambian, los campos desaparecen, y un selector frágil se convierte en silencio en nulls a lo largo de miles de filas.

4. Normalizar. Convierte los valores extraídos crudos en tipos y unidades consistentes, monedas a una sola denominación, fechas a ISO, espacios eliminados, codificaciones arregladas, categóricos mapeados a un vocabulario controlado.

5. Deduplicar. La misma entidad aparece a menudo en múltiples URLs (canónica + variantes, duplicados paginados, ítems re-listados). Deduplica por una clave estable, no por la URL.

6. Almacenar y refrescar. Persiste con procedencia completa, luego decide una cadencia de re-crawl para que el dataset se mantenga fresco en lugar de degradarse en una instantánea de una sola vez.

La etapa que decide la calidad: el fetch

Aquí está el argumento central de toda esta pieza. La calidad de tu dataset está limitada por la etapa de fetch, porque una petición que se bloquea no solo pierde datos, pierde datos no aleatorios.

Tres mecanismos convierten los fallos de fetch en sesgo del dataset:

Sesgo de bloqueo. Los sistemas anti-bot (Cloudflare, Akamai, DataDome) protegen los objetivos de alto valor y alto tráfico de forma más agresiva. Si tu scraper corre desde una IP de datacenter y se bloquea en esos, tu dataset está sistemáticamente perdiendo las filas más importantes mientras conserva las fáciles. El resultado se inclina hacia fuentes más pequeñas y menos defendidas, y parece completo porque aun así obtuviste miles de filas. (Ve por qué se bloquean los scrapers para la mecánica.)

Sesgo geográfico. Muchos sitios sirven contenido, precios o disponibilidad distintos según la ubicación del visitante, y redirigen o localizan en silencio según la IP. Si todas tus peticiones se originan desde una región, cada campo que varía por geo en tu dataset refleja ese único punto de observación, no la realidad global que crees haber capturado. Scrapea “disponibilidad global de producto” desde un país y en realidad capturaste la vista de un país, mal etiquetada como global.

Sesgo de rate-limit. Cuando un objetivo te limita, la respuesta ingenua es ir más despacio o rendirte con las páginas que responden lento, que a menudo son las pesadas y ricas en datos. Acabas sobre-muestreando las páginas rápidas y ligeras.

El arreglo para los tres es el mismo: hacer fetch a través de un pool de IPs que parecen usuarios reales, en las ubicaciones correctas, para que la cobertura sea completa y pareja en lugar de inclinada hacia lo que fue fácil de alcanzar.

Por qué la capa de proxy es una decisión de calidad de datos, no solo fontanería

Por esto una red de proxies residenciales importa específicamente para construir datasets, más allá de “no ser bloqueado”:

Cobertura completa. Las IPs residenciales llevan el perfil de confianza de conexiones de consumo reales, así que pasan en los objetivos defendidos que una IP de datacenter no puede alcanzar. Eso cierra el hueco del sesgo de bloqueo, recoges las filas difíciles, no solo las fáciles.

Cobertura geográfica a propósito. Con targeting por país, estado y ciudad, puedes muestrear deliberadamente cada mercado y etiquetar cada fila con el punto de observación del que vino. En lugar de un punto de vista accidental, obtienes un dataset multi-geo controlado donde la geo es una columna, no un confusor oculto. Esta es la diferencia entre “scrapeé precios” y “scrapeé precios vistos desde 12 mercados específicos, registrado por fila”.

Muestreo parejo a escala. Rotar por un pool grande reparte las peticiones para que ninguna IP individual active los rate limits, lo que evita que sobre-muestrees las páginas rápidas y sub-muestrees las lentas y pesadas en datos.

Dicho claro: la capa de proxy es donde decides si tu dataset es una muestra representativa o una muestra de conveniencia. Para el trabajo de datasets eso no es un detalle de fontanería, es una elección de metodología. (Para la vista de infra más amplia, ve infraestructura de proxy para machine learning.)

Frescura: un dataset es un verbo, no un sustantivo

Un scrape de una sola vez es una instantánea, y las instantáneas se pudren. Decide de entrada si estás construyendo un dataset estático (vale para un estudio puntual) o uno vivo (necesario para precios, inventario, listados, cualquier cosa que cambie).

Para datasets vivos:

  • Fija una cadencia de re-crawl acorde a lo rápido que cambian los datos, cada hora para precios volátiles, semanal para metadatos de catálogo, mensual para datos de referencia que se mueven despacio.
  • Haz refrescos incrementales, no re-scrapes completos. Detecta qué cambió (ETags, last-modified, hashes de contenido, diffs de listados) y vuelve a traer solo eso. Más barato, más rápido, y más ligero para el objetivo.
  • Sella cada fila con un timestamp de fetch para que los consumidores downstream puedan filtrar por recencia y tú puedas medir la obsolescencia.

La frescura también es un problema de cobertura: si tu crawl de refresco se bloquea en las mismas páginas defendidas cada vez, esas filas se quedan obsoletas mientras las fáciles se mantienen actuales, reintroduciendo sesgo con el tiempo. El mismo arreglo.

Deduplicación y normalización, donde los datasets se ganan o se pierden

Los datos crudos scrapeados están sucios. Dos etapas los limpian:

Normaliza a un esquema. Decide primero el esquema objetivo, luego mapea cada fuente a él. Monedas a una denominación, fechas a ISO 8601, números parseados de cadenas como “1.299 unidades”, texto recortado y normalizado en unicode, categóricos ajustados a un vocabulario controlado. La normalización inconsistente es la razón más común de que un dataset scrapeado esté técnicamente completo pero sea analíticamente inútil.

Deduplica por una clave estable, no por la URL. El mismo producto, persona o registro vive rutinariamente en varias URLs. Construye una clave de dedup desde la identidad estable (SKU, ISBN, nombre + ubicación normalizados, URL canónica) y colapsa los duplicados, quedándote con la versión más fresca o más completa. Deduplicar solo por URL cruda te dejará con conteos inflados y filas con doble peso que distorsionan en silencio cualquier agregado.

Almacenar con procedencia

Para cada fila, almacena como mínimo:

  • La URL de origen de la que vino
  • El timestamp de fetch (UTC)
  • El punto de observación geográfico que usó la petición (país/ciudad), si la geo importa para los datos
  • Un hash de contenido o versión, para poder detectar cambios en el re-crawl
  • El payload crudo (o una referencia a él), separado de los campos parseados, para poder re-parsear sin re-scrapear cuando tu extractor mejore

La procedencia parece sobrecarga hasta la primera vez que alguien pregunta “¿de dónde salió este número?” o tu extractor tiene un bug y necesitas re-parsear 500k filas sin volver a tocar la red. Almacénala desde el día uno.

Validar el dataset antes de confiar en él

Antes de que nadie construya sobre el dataset, corre comprobaciones de cobertura y calidad, así es como cazas el sesgo que la etapa de fetch puede introducir:

  • Auditoría de cobertura. Compara las filas recogidas contra la población prevista de la etapa de descubrimiento. Una tasa de completitud del 92% está bien; la pregunta es si el 8% que falta es aleatorio. Revisa a mano los fallos, si se agrupan en una fuente, una geo o un tipo de sitio, tienes sesgo sistemático que arreglar, no solo datos que faltan.
  • Comprobación de tasa de nulls por campo. Un campo que de repente es 40% null normalmente significa un selector roto, no datos ausentes.
  • Comprobaciones de cordura de distribución. ¿Coincide la distribución de precios, la mezcla de categorías o la dispersión geo con lo que esperarías? Un sesgo a menudo revela un problema de muestreo aguas arriba.
  • Comprobación de frescura. ¿Cuál es la distribución de edad de las filas? Si un trozo está siempre obsoleto, tu crawl de refresco se está bloqueando ahí.

Estas comprobaciones son baratas y son la diferencia entre lanzar un dataset y lanzar uno confiadamente erróneo.

Una nota sobre hacerlo de forma responsable

Construir datasets desde la web viene con obligaciones reales. Recoge solo datos públicos, honra robots.txt donde sea relevante, respeta los rate limits y no degrades los sitios de los que tiras, mantente lejos de datos personales salvo que tengas una base legal, y sigue los términos de cada objetivo. Un proxy cambia desde qué IP viene una petición, no si deberías estar haciéndola. Nuestra política de uso aceptable es la fuente de la verdad para lo que está permitido en Shifter, y vale la pena leer sobre recolección ética de datos antes de escalar.

Preguntas frecuentes

¿Cuál es la parte más difícil de construir un dataset por web scraping? No el scraping, la cobertura. Conseguir una muestra completa y sin sesgo es mucho más difícil que traer páginas, porque las peticiones fallidas eliminan porciones no aleatorias de datos y el dataset resultante todavía parece completo. La mayoría de los problemas de calidad de datasets se remontan a la etapa de fetch.

¿Cómo sesgan los bloqueos un dataset scrapeado? Los sistemas anti-bot protegen los objetivos de alto valor de forma más agresiva, así que un scraper que se bloquea pierde las filas importantes y bien defendidas mientras conserva las fáciles. El dataset se inclina hacia fuentes menos defendidas, lo que corrompe cualquier agregado o modelo construido sobre él.

¿Necesito proxies residenciales para construir un dataset? Solo si tus objetivos bloquean IPs de datacenter o varían el contenido por geografía, que es lo que hacen la mayoría de los objetivos valiosos. Para fuentes sin protección y neutrales en geo, las IPs de datacenter valen. Para cobertura completa y representativa de sitios defendidos o localizados, los proxies residenciales cierran el hueco de sesgo.

¿Cómo mantengo fresco un dataset scrapeado? Fija una cadencia de re-crawl acorde a lo rápido que cambian los datos, haz refrescos incrementales (detecta cambios vía ETags/hashes/diffs en lugar de re-scrapes completos), y sella cada fila con un timestamp de fetch para poder medir y filtrar por obsolescencia.

¿Cómo debería deduplicar datos scrapeados? Por una clave de identidad estable (SKU, ISBN, URL canónica, nombre+ubicación normalizados), nunca por la URL cruda, porque la misma entidad aparece en muchas URLs. Colapsa los duplicados a la versión más fresca o más completa.

¿Qué debería almacenar además de los campos extraídos? Procedencia: URL de origen, timestamp de fetch, punto de observación geográfico, un hash de contenido para detección de cambios, e idealmente el payload crudo para poder re-parsear sin re-scrapear cuando tu extractor mejore.

En resumen

Construir un dataset con web scraping es un problema de calidad de datos disfrazado de scraping. Cualquiera puede traer páginas; el trabajo es asegurarte de que trajiste las páginas correctas, completamente, actualmente, y sin un hueco sistemático donde deberían estar los objetivos difíciles. El pipeline, descubrir, fetch, extraer, normalizar, deduplicar, almacenar, refrescar, es sencillo. La única etapa que limita en silencio tu calidad es el fetch, porque ahí es donde los bloqueos y la geo convierten datos que faltan en datos sesgados.

Haz bien la capa de fetch y el resto es ingeniería. Si tus fuentes están defendidas o varían por geo, una red de proxies residenciales es lo que convierte una muestra de conveniencia en una representativa, cobertura completa de los objetivos difíciles, muestreo multi-geo deliberado, y rotación pareja a escala. Cuando estés listo para conectarlo, la guía de Python muestra el código de la etapa de fetch, y la página de precios tiene los planes por GB. Construye primero la cobertura, y el dataset se cuida solo.

Etiquetas: web scraping datasets data collection residential proxies data engineering

¿Listo para empezar?

Prueba los proxies residenciales de Shifter, más de 205M IPs, más de 195 países, desde 1,00 $/GB.

Comenzar