← Blog

Web scraping con Puppeteer en Node.js: casos de uso reales y buenas prácticas

D
Damián Oliva
·25 de marzo de 2025

Cuándo tiene sentido el web scraping

El scraping es una herramienta poderosa pero hay que usarla bien. Los casos que implemento frecuentemente:

  • Monitoreo de precios de competidores
  • Extracción de datos de portales sin API pública
  • Automatización de tareas manuales en sistemas legacy
  • Agregación de información de múltiples fuentes

Siempre verifico los términos de servicio del sitio y evito saturar servidores con requests agresivos.

Setup básico con Puppeteer

npm install puppeteer
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  headless: true,
  args: ['--no-sandbox', '--disable-setuid-sandbox'],
});

const page = await browser.newPage();
await page.goto('https://ejemplo.com', { waitUntil: 'networkidle0' });

const data = await page.evaluate(() => {
  return Array.from(document.querySelectorAll('.producto')).map(el => ({
    nombre: el.querySelector('.nombre')?.textContent?.trim(),
    precio: el.querySelector('.precio')?.textContent?.trim(),
  }));
});

await browser.close();
console.log(data);

Manejo de páginas dinámicas y esperas

// Esperar a que aparezca un elemento
await page.waitForSelector('.resultado', { timeout: 10000 });

// Esperar a que desaparezca un loader
await page.waitForFunction(
  () => !document.querySelector('.spinner'),
  { timeout: 15000 }
);

// Scroll infinito: cargar más contenido
const autoScroll = async (page) => {
  await page.evaluate(async () => {
    await new Promise(resolve => {
      let totalHeight = 0;
      const timer = setInterval(() => {
        window.scrollBy(0, 100);
        totalHeight += 100;
        if (totalHeight >= document.body.scrollHeight) {
          clearInterval(timer);
          resolve();
        }
      }, 100);
    });
  });
};

Puppeteer Extra + Stealth Plugin

Muchos sitios detectan y bloquean Puppeteer. El plugin stealth evita la mayoría de las detecciones básicas:

npm install puppeteer-extra puppeteer-extra-plugin-stealth
import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';

puppeteer.use(StealthPlugin());

const browser = await puppeteer.launch({ headless: true });

Rate limiting y respeto al servidor

const sleep = (ms) => new Promise(r => setTimeout(r, ms));

for (const url of urls) {
  await page.goto(url);
  // ... extraer datos
  await sleep(1500 + Math.random() * 1000); // 1.5-2.5 segundos entre requests
}

Caso real: scraping de expedientes judiciales

En el proyecto Magistrar, implementé scraping del portal del Poder Judicial para actualizar automáticamente el estado de expedientes. El desafío era un sistema con CAPTCHA y sesiones. La solución: iniciar sesión con Puppeteer, mantener las cookies, y solo scrapear cuando había cambios detectados por un polling liviano previo.

Newsletter

Ideas directamente
a tu bandeja de entrada

Comparto lo que estoy construyendo, lo que aprendo y lo que me parece interesante del mundo tech y startups. Sin spam. Cuando tenga algo que valga la pena.

Sin spam. Unsubscribe en cualquier momento.