Gestión de la paginación y el contenido dinámico
Siga los enlaces a la página siguiente y use Playwright para páginas renderizadas con JavaScript.
Gestión de la paginación y el contenido dinámico es una lección gratuita de AI Agents en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Agents, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Agents incluye 4 lecciones en total.
El problema de la paginación
La mayoría de los sitios web reales no sirven todos sus datos en una sola página. Los resultados se dividen entre varias páginas para reducir la carga. Un agente debe detectar y seguir la paginación para recopilar conjuntos de datos completos.
Hay dos patrones de paginación habituales: enlaces a la página siguiente y patrones de URL con números de página.
Detección de enlaces a la página siguiente
Muchos sitios tienen un botón «Siguiente» o un enlace con una flecha. Busque la etiqueta de anclaje con rel='next' o cuyo texto sea similar a «Siguiente», extraiga su href y sígalo en un bucle hasta que deje de existir.
from bs4 import BeautifulSoup
import httpx
def scrape_all_pages(start_url: str) -> list:
results = []
url = start_url
while url:
response = httpx.get(url, timeout=10.0)
soup = BeautifulSoup(response.text, 'html.parser')
# Collect data from this page
for item in soup.select('.result-item'):
results.append(item.text.strip())
# Find the next page link
next_link = soup.find('a', rel='next') or soup.find('a', string='Next')
url = next_link.get('href') if next_link else None
return resultsPatrones de URL con números de página
Muchas API y sitios utilizan patrones de URL predecibles: /results?page=1, /results?page=2, etc. Un agente puede iterarlos directamente sin analizar el DOM para buscar un enlace a la página siguiente.
import httpx
def scrape_paginated_api(base_url: str, max_pages: int = 10) -> list:
all_items = []
for page in range(1, max_pages + 1):
response = httpx.get(
base_url,
params={'page': page, 'per_page': 50},
timeout=10.0
)
response.raise_for_status()
data = response.json()
items = data.get('results', [])
if not items:
break # No more data
all_items.extend(items)
print(f'Page {page}: fetched {len(items)} items')
return all_itemsPaginación basada en cursores
Las API modernas, como GitHub, Slack y Twitter, utilizan paginación basada en cursores. Cada respuesta incluye un token de cursor para la página siguiente. Pase el cursor en la siguiente solicitud hasta que no esté presente o sea nulo.
import httpx
def fetch_with_cursor(url: str, headers: dict) -> list:
all_data = []
cursor = None
while True:
params = {'cursor': cursor} if cursor else {}
response = httpx.get(url, headers=headers, params=params, timeout=10.0)
response.raise_for_status()
data = response.json()
all_data.extend(data.get('items', []))
cursor = data.get('next_cursor') # None when done
if not cursor:
break
return all_dataContenido estático frente a dinámico
Algunas páginas cargan contenido mediante JavaScript después de entregar el HTML inicial. Un cliente HTTP normal recibe únicamente la estructura vacía; los datos reales los inyecta JS en el navegador.
Para estas páginas, herramientas como Playwright ejecutan un motor de navegador real y esperan a que se ejecute JavaScript antes de extraer el contenido.
Instalación e importación de Playwright
Instale Playwright con pip install playwright y luego ejecute playwright install chromium para descargar el navegador. Use async_playwright() para flujos de trabajo asíncronos de los agentes.
# Installation (run in terminal):
# pip install playwright
# playwright install chromium
from playwright.async_api import async_playwright
import asyncio
async def fetch_dynamic(url: str) -> str:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
html = await page.content() # Full rendered HTML
await browser.close()
return html
# html = asyncio.run(fetch_dynamic('https://example.com'))Espera a que se cargue el contenido dinámico
Las páginas JavaScript suelen cargar datos de forma asíncrona. Indique a Playwright que espere hasta que aparezca un elemento específico antes de extraer contenido, para asegurarse de que los datos que necesita estén realmente presentes en el DOM.
from playwright.async_api import async_playwright
async def scrape_dynamic_table(url: str) -> list:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
# Wait for the table to appear in the DOM
await page.wait_for_selector('table.results', timeout=10000)
html = await page.content()
await browser.close()
from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'html.parser')
return [td.text for td in soup.select('table.results td')]Cómo hacer clic e interactuar con las páginas
Playwright puede simular interacciones del usuario: hacer clic, rellenar formularios, desplazarse y escribir con el teclado. Esto permite a un agente navegar por flujos de inicio de sesión, menús desplegables o páginas con desplazamiento infinito.
from playwright.async_api import async_playwright
async def click_load_more(url: str) -> str:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
# Click the 'Load More' button
load_more = page.locator('button:text("Load More")')
if await load_more.count() > 0:
await load_more.click()
await page.wait_for_timeout(2000) # wait 2s for content
html = await page.content()
await browser.close()
return htmlGestión del desplazamiento infinito
Algunos sitios cargan más contenido a medida que se desplaza hacia abajo. Playwright puede simular el desplazamiento para activar estas cargas. Desplácese repetidamente y compruebe cada vez si ha aparecido contenido nuevo.
from playwright.async_api import async_playwright
async def scrape_infinite_scroll(url: str, scroll_count: int = 5) -> str:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
for _ in range(scroll_count):
await page.evaluate('window.scrollTo(0, document.body.scrollHeight)')
await page.wait_for_timeout(1500) # wait for new content
html = await page.content()
await browser.close()
return htmlCombinación de Playwright con BeautifulSoup
Después de que Playwright procese la página y devuelva el HTML completo, páselo a BeautifulSoup para extraer datos fácilmente. Así combina las ventajas de ambas bibliotecas.
from playwright.async_api import async_playwright
from bs4 import BeautifulSoup
async def extract_js_rendered_data(url: str) -> list:
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True)
page = await browser.new_page()
await page.goto(url)
await page.wait_for_selector('.product-card')
html = await page.content()
await browser.close()
soup = BeautifulSoup(html, 'html.parser')
products = []
for card in soup.select('.product-card'):
products.append({
'name': card.select_one('.name').text.strip(),
'price': card.select_one('.price').text.strip()
})
return productsElección de la herramienta adecuada
No todas las páginas necesitan Playwright. Utilice el enfoque más sencillo que funcione:
- HTML estático: httpx + BeautifulSoup (rápido, sin la sobrecarga de un navegador)
- API JSON con paginación: httpx con parámetros de página o cursor
- Contenido renderizado con JS: Playwright asíncrono (más lento, más potente)
Comience siempre con el enfoque estático y recurra a Playwright solo cuando sea necesario.
Comprobación de conocimientos: paginación y contenido dinámico
Compruebe sus conocimientos sobre la paginación y la gestión del contenido dinámico.
Resumen: paginación y contenido dinámico
Ahora sus agentes pueden gestionar todo tipo de contenido web:
- Seguir enlaces a la página siguiente o iterar los parámetros de página de una URL
- Usar tokens de cursor para la paginación de las API modernas
- Usar
async_playwright()para páginas renderizadas con JavaScript - Esperar a que aparezcan elementos con
page.wait_for_selector() - Combinar Playwright con BeautifulSoup para extraer datos fácilmente
Comience siempre con el enfoque más sencillo y recurra a Playwright solo cuando el enfoque estático no sea suficiente.
Preguntas frecuentes
¿La lección «Gestión de la paginación y el contenido dinámico» es gratis?
Sí — el texto completo de «Gestión de la paginación y el contenido dinámico» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Agents, actualiza a CoddyKit PRO. El curso de AI Agents incluye 4 lecciones en total.
¿Qué aprenderé en «Gestión de la paginación y el contenido dinámico»?
Siga los enlaces a la página siguiente y use Playwright para páginas renderizadas con JavaScript. Practicas AI Agents con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar AI Agents?
No se requiere experiencia previa. AI Agents en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «Gestión de la paginación y el contenido dinámico»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de AI Agents?
Sí. Cada lección de AI Agents incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Clientes HTTP para agentes: httpx y requests
- Análisis de HTML con BeautifulSoup
- Gestión de la paginación y el contenido dinámico
- Prácticas responsables de scraping