← Todos los artículos

El Tope de 10.000 Resultados: Cómo Extraer Datos Más Allá de los Límites de Paginación

Construyes un scraper para una página de resultados de búsqueda. Funciona. Paginas: página 1, página 2, página 10, página 40. Los elementos nuevos siguen apareciendo. Y de repente, hacia la página 65, los resultados se agotan. La página sigue cargando. El diseño está intacto. No hay CAPTCHA ni mensaje de bloqueo. Simplemente no hay más anuncios, aunque la propia cabecera del sitio diga “más de 48.000 resultados”.

No te han baneado. Has chocado con un tope de resultados. Casi todas las interfaces de búsqueda grandes tienen uno, y si no lo tienes en cuenta, tu conjunto de datos termina en silencio en una fracción de lo que realmente hay. Este artículo explica qué es ese tope, por qué existe, cómo distinguirlo de un bloqueo y la única técnica fiable para recopilar el conjunto completo de todas formas: particionar el espacio de consulta.

Cómo se Ve el Tope de Resultados

El síntoma es concreto. Las páginas superficiales devuelven datos nuevos. Las páginas profundas devuelven una cuadrícula vacía, o repiten la misma última página, o redirigen a la página 1. Y lo importante: la respuesta es una página válida. Código de estado 200. Título correcto. Navegación correcta. Simplemente sin elementos.

Normalmente hay dos números que definen el tope:

  • Un desplazamiento (offset) máximo, a menudo 10.000. Muchos sitios paginan con un offset o un número de página que se traduce en página * tamaño_de_página. En cuanto el offset supera los ~10.000, el backend se niega a ir más profundo.
  • Un máximo de resultados por consulta, que es el mismo límite visto desde el otro lado. Si el tamaño de página es 240, obtienes unas 10.000 / 240 = 41 páginas útiles. Si es 50, obtienes 200 páginas. En cualquier caso, te quedas cerca de los 10.000 elementos.

Verás esto en grandes marketplaces de comercio electrónico, portales de empleo, portales inmobiliarios y motores de búsqueda generales. No es un fallo. Es un techo deliberado.

Por Qué los Sitios Limitan la Paginación Profunda

Aquí no hay conspiración. El tope es una decisión de rendimiento, y entenderlo te dice cómo superarlo.

La mayoría de los backends de búsqueda usan paginación por desplazamiento (offset). Para servir la página 400, la base de datos tiene que recorrer las primeras 399 páginas de resultados y luego devolver el siguiente fragmento. Ese trabajo de “recorrer” crece de forma lineal con la profundidad. La página 1 es barata. La página 4.000 es cara. Para devolver páginas profundas, el motor debe ordenar y escanear un conjunto de candidatos enorme, y debe hacerlo para cada crawler que recorre la cola. Así que los operadores trazan una raya. Más allá del offset 10.000, la petición simplemente se rechaza o devuelve vacío.

Motores de búsqueda como Elasticsearch lo hacen explícito. Su index.max_result_window tiene un valor por defecto de exactamente 10.000, y la documentación te dice que uses search_after o la API de scroll en lugar de la paginación profunda con from/size. Cuando un sitio está construido sobre esa pila, el techo de 10.000 se hereda directamente del motor.

La conclusión importante: el tope se aplica a una sola consulta, no a todo el catálogo. El catálogo tiene millones de elementos. Cualquier consulta individual solo puede exponer los primeros 10.000. Así que la solución no es paginar con más fuerza. La solución es hacer más preguntas, y más pequeñas.

Primero, Confirma que es un Tope y no un Bloqueo

Antes de rediseñar tu crawler, descarta un bloqueo suave. Las páginas profundas vacías y los bloqueos sigilosos pueden verse idénticos desde fuera, así que comprueba tres cosas:

  1. ¿Es la página estructuralmente válida? Una página realmente limitada tiene la cabecera, el pie y los mensajes de “sin resultados” normales del sitio. Un bloqueo suele devolver una página recortada, un desafío o un interstitial. Si no sabes cómo distinguirlos, nuestro artículo sobre detectar bloqueos suaves cubre las señales.
  2. ¿Se reproduce el límite? Pide la misma página profunda tres veces. Un tope es determinista: la página 70 siempre está vacía. Un bloqueo suele ser intermitente y desaparece tras una pausa o una nueva sesión.
  3. ¿Sigue funcionando una página menos profunda en la misma sesión? Si la página 5 devuelve datos pero la 70 no, usando las mismas cookies y cabeceras, estás ante un tope, no ante un baneo de IP.

Una vez confirmado que es un tope, deja de intentar pasarlo. Ninguna cantidad de proxies ni de reintentos mueve un límite de offset fijo.

La Solución: Particionar el Espacio de Consulta

Toda la técnica es una sola idea. Divide el catálogo en fragmentos lo bastante pequeños para que cada uno contenga menos de 10.000 resultados, extrae cada fragmento por completo, y luego fusiona y deduplica. Toda interfaz de búsqueda grande te ofrece filtros, y cada filtro es un cuchillo con el que puedes cortar.

Dividir por Categoría

El corte más natural. En lugar de buscar “portátiles” (500.000 resultados, limitados a 10.000), busca cada subcategoría: “portátiles gaming”, “portátiles de oficina”, “chromebooks”, etc. Los filtros de categoría casi siempre se exponen como parámetros de URL, lo que hace que iterarlos sea trivial.

Dividir por Franja de Precio

El precio es un eje numérico limpio. La mayoría de las interfaces de búsqueda aceptan un precio mínimo y máximo. Recorre el rango en franjas:

def franjas_precio(lo, hi, paso):
    borde = lo
    while borde < hi:
        yield (borde, min(borde + paso, hi))
        borde += paso

# 0-25, 25-50, 50-75, ...
for bajo, alto in franjas_precio(0, 1000, 25):
    scrape_consulta(precio_min=bajo, precio_max=alto)

Si una sola franja sigue devolviendo más de 10.000 resultados, divídela más. Franjas estrechas en la parte baja, donde se acumula el inventario, y franjas más anchas en la parte alta.

Dividir por Ventana de Fechas

Para todo lo que esté ordenado por novedad, como ofertas de empleo, noticias o artículos recién publicados, divide por tiempo. Consulta “publicado en las últimas 24 horas”, retrocede un día, repite. Dividir por fecha tiene una ventaja: convierte un rastreo puntual en uno incremental y mantenible. Tras el primer barrido completo, solo extraes la ventana más reciente.

Dividir por Ubicación

Región, país, ciudad o código postal. Este eje funciona bien para marketplaces y directorios donde la misma consulta en distintas localizaciones devuelve un inventario en gran parte diferente. Pero no des por hecho que los fragmentos son disjuntos. El mismo vendedor o anuncio puede aparecer en varias regiones, que es exactamente por lo que importa el paso de deduplicación de abajo.

Combina Ejes Cuando uno no Basta

Si la categoría por sí sola sigue reventando el tope, combina ejes: categoría por franja de precio, o ubicación por ventana de fecha. Cada eje adicional multiplica tu número de fragmentos pero encoge cada uno por debajo del techo. El objetivo es simple: ninguna consulta individual debe devolver más de ~10.000 resultados.

Deduplica Entre Fragmentos

Los fragmentos que se solapan volverán a mostrar los mismos elementos. Necesitas una clave de identidad estable y un conjunto de “ya vistos”. Prefiere el identificador permanente del propio sitio, normalmente incrustado en la URL del elemento, antes que cualquier cosa cosmética como un título o un nombre visible que pueda cambiar entre peticiones.

vistos = set()
resultados = []

for consulta in construir_fragmentos():
    for item in scrape_todas_las_paginas(consulta):
        item_id = extraer_id(item["url"])   # estable, desde la URL
        if item_id in vistos:
            continue
        vistos.add(item_id)
        resultados.append(item)

Mantén el conjunto de “ya vistos” persistente entre ejecuciones si extraes con una periodicidad. Así un barrido incremental se salta lo que ya tienes, y tu presupuesto de peticiones se dedica a elementos genuinamente nuevos.

Vigila el Retorno Marginal

Particionar es potente pero no gratis. Cada fragmento cuesta peticiones, y los fragmentos se solapan, así que pagas por duplicados. Lleva la cuenta de cuántos elementos nuevos aporta cada fragmento. Cuando un fragmento devuelve casi nada que no hayas visto ya, estás cerca de la saturación y puedes parar. Esta regla de “parar cuando se seca” evita que muelas miles de consultas casi vacías persiguiendo el último puñado de elementos de cola larga. Para la mayoría de los proyectos, capturar el grueso del catálogo cuesta una fracción de lo que costaría la cobertura completa de cada entrada única.

Sé también suave. Las páginas de búsqueda profundas están entre las más pesadas que renderiza un sitio, y martillearlas en paralelo es la forma más rápida de convertir un rastreo limpio en una ola de errores 503. Mantén la concurrencia moderada en esos endpoints y deja que sean los fragmentos, no el paralelismo bruto, los que escalen.

Preguntas Frecuentes

¿El tope es siempre 10.000? No, pero es el valor más común porque es el valor por defecto de Elasticsearch. Algunos sitios limitan a 1.000, otros a 25.000. Mídelo: haz una búsqueda binaria de la profundidad a la que los resultados se vacían, y diseña los fragmentos para quedar cómodamente por debajo de ese número.

¿Puedo usar una API para evitar el tope? A veces. Las APIs basadas en cursor (search_after, tokens de scroll, cursores de “página siguiente”) no sufren el problema del offset, así que si una API documentada ofrece paginación por cursor, prefiérela. Pero la mayoría de las APIs públicas aplican el mismo techo de resultados por consulta, así que a menudo aún tendrás que particionar. Comprueba siempre los términos de servicio antes de usar una API para recopilación masiva.

¿Por qué no aumento simplemente el tamaño de página? Porque el tope es sobre el total de resultados por consulta, no sobre el número de páginas. Un tamaño de página mayor te lleva al techo en menos peticiones, pero el techo no se mueve. Las páginas más grandes siguen mereciendo la pena para reducir el volumen de peticiones, pero no esperes que desbloqueen más datos.

¿Cómo sé que lo tengo todo? No lo sabes con certeza. Usa la señal de retorno marginal: cuando los fragmentos nuevos dejan de añadir elementos, y ejes independientes (por ejemplo, dividir por categoría y dividir por precio) convergen en el mismo total, tienes fuertes indicios de una cobertura casi completa.

Poniéndolo Todo Junto

Los topes de resultados son un hecho de la vida cuando extraes datos a escala. El instinto de paginar con más fuerza o lanzar más proxies a una página profunda es esfuerzo desperdiciado, porque el límite es estructural, no defensivo. La jugada fiable es particionar: corta el catálogo por categoría, precio, fecha y ubicación hasta que cada consulta quepa por debajo del techo, y luego fusiona y deduplica con una clave estable.

Lo único que particionar no resuelve es conseguir cada página individual en primer lugar. Las páginas de búsqueda profundas son justo donde se concentran los sistemas antibot, y un crawler que dispara cientos de peticiones de render pesadas llamará la atención por muy limpiamente que dividas. Si prefieres no mantener la rotación de proxies y el fingerprinting de navegador que requiere una obtención fiable de páginas, ScrapeUnblocker se encarga de esa capa y te devuelve el HTML renderizado, para que puedas centrarte en la lógica de división. En cualquier caso, la estrategia es la misma: deja de pelear contra el tope y empieza a dividir el problema.

Prueba ScrapeUnblocker gratis

Tasa de éxito del 95%+ · desde 0,55 € por cada 1000 llamadas · 500 solicitudes gratis al registrarte.

Pruébalo gratis → Ver precios