Latenode

Depuración de scripts de Puppeteer: desde el modo slowMo hasta técnicas avanzadas

Domine técnicas esenciales de depuración para scripts de Puppeteer, desde métodos visuales hasta gestión avanzada de errores, para mejorar la fiabilidad de sus scripts.

9 min de lectura
Ventana de navegador mostrando herramientas para depurar un script de Puppeteer

Depurar scripts de Puppeteer puede resultar abrumador, pero dominar algunas técnicas clave puede ahorrarle tiempo y frustraciones. A continuación, un resumen rápido de lo que aprenderá:

  • Empiece con la depuración visual: Use el modo slowMo y el modo de navegador visible para observar su script en acción.
  • Capture errores: Añada bloques try-catch y automatice capturas de pantalla de errores para solucionar problemas de forma más eficaz.
  • Aproveche los registros de consola: Realice un seguimiento de errores de página, solicitudes fallidas y mensajes personalizados para obtener información más detallada.
  • Gestione selectores y tiempos: Use estrategias de selectores sólidas y administre los tiempos de espera para evitar problemas habituales.
  • Organice su código: Divida los scripts en módulos para acciones, selectores y validaciones, y simplifique el mantenimiento.

Ejemplo de configuración rápida:

const browser = await puppeteer.launch({
    headless: false,
    slowMo: 100,
    devtools: true
});

Consejos de depuración:

  1. Active el registro: Ejecute con DEBUG="puppeteer:*" para obtener registros detallados.
  2. Use capturas de pantalla: Capture los estados de la página para ver qué salió mal.
  3. Administre los recursos: Limpie siempre las instancias del navegador y de las páginas para evitar bloqueos.

Al combinar estas técnicas, agilizará su proceso de depuración y mejorará la fiabilidad de sus scripts de Puppeteer.

Configuración del entorno de depuración

Ajustes básicos de depuración

Configure Puppeteer para la depuración con estas opciones de inicio:

const browser = await puppeteer.launch({
    headless: false,
    slowMo: 20,
    devtools: true
});

Para activar un registro detallado, ejecute su script con el siguiente comando:

DEBUG="puppeteer:*" node script.js

Una vez configurado, use herramientas de depuración para analizar y perfeccionar el comportamiento de su script.

Herramientas de depuración necesarias

Estas son algunas herramientas que le ayudarán a resolver problemas de forma eficaz:

HerramientaPropósitoFunción clave
Chrome DevToolsInspeccionar scriptsHerramientas de consola y red
Depurador de VS CodeGestionar puntos de interrupciónEjecución paso a paso
Utilidad de capturas de pantallaResolución visual de problemasCapturar estados de página

También puede añadir puntos de control a su código para obtener mayor visibilidad:

await page.screenshot({ path: 'before_click.png' });
await page.click('#button');
await page.screenshot({ path: 'after_click.png' });

Organización del script

Una buena organización es tan importante como las herramientas que utiliza. Divida su script en módulos lógicos e incluya gestión de errores para una depuración más fluida:

try {
    await page.waitForSelector('#target-element');
    await page.click('#target-element');
} catch (error) {
    console.error(`La navegación falló: ${error.message}`);
    await page.screenshot({ path: 'error-state.png' });
}

Para reducir la probabilidad de detección de bots, integre el plugin stealth:

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());

Por último, asegure una gestión adecuada de los recursos implementando procedimientos de limpieza:

async function cleanup() {
    if (page) await page.close();
    if (browser) await browser.close();
}

Esta configuración proporciona una base sólida para la depuración visual y de consola en sus proyectos.

Puppeteer: 3 enfoques que debe considerar para la depuración

Métodos de depuración visual

Observar sus scripts en acción puede revelar problemas que el análisis de código tradicional podría pasar por alto. Estos métodos amplían sus opciones de depuración más allá de los registros de consola y el seguimiento de errores.

Guía del modo SlowMo

SlowMo introduce una demora entre las acciones de Puppeteer, lo que facilita seguir lo que ocurre:

const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    devtools: true
});

El valor de slowMo (en milisegundos) controla la demora entre acciones. Ajústelo según lo que esté probando:

Tipo de operaciónSlowMo recomendado (ms)Caso de uso
Clics simples100–250Pasos básicos de navegación
Relleno de formularios250–500Pruebas de validación de entradas
Contenido dinámico500–1000Comprobación de estados de carga

Una vez que haya configurado SlowMo, combínelo con el modo de vista del navegador para supervisar cómo se comporta la interfaz durante la ejecución del script.

Modo de vista del navegador

El modo de vista del navegador le permite ver cómo se ejecuta su script en una ventana de navegador visible, lo que resulta especialmente útil para depurar contenido dinámico e interacciones complejas.

const browser = await puppeteer.launch({
    headless: false,
    defaultViewport: { width: 1700, height: 800 },
    args: ['--start-maximized']
});

Por ejemplo, el equipo de QA de Acme Corp utilizó este modo en junio de 2024 para solucionar problemas en un script de web scraping. Detectaron selectores incorrectos y los corrigieron, reduciendo el tiempo de depuración en un 40 %.

Para complementar este proceso, capture capturas de pantalla de estados visuales importantes para analizarlos posteriormente.

Registro visual

Las capturas de pantalla y los vídeos pueden crear un registro claro de la ejecución de su script, facilitando la depuración:

// Captura de pantalla de un elemento específico
await page.screenshot({
    path: 'element-state.png',
    clip: {
        x: 0,
        y: 0,
        width: 500,
        height: 300
    }
});

// Captura de pantalla de página completa
await page.screenshot({
    path: 'full-page.png',
    fullPage: true
});

Empiece activando el modo de vista del navegador, use SlowMo para realizar un seguimiento detallado y documente los momentos clave con capturas de pantalla. En conjunto, estos pasos crean un proceso completo de depuración visual.

Métodos de depuración de consola

Los métodos de consola ofrecen una forma directa de obtener información basada en texto sobre el comportamiento de sus scripts. Estas salidas complementan la depuración visual y le proporcionan detalles precisos sobre la ejecución del script.

Seguimiento de mensajes de consola

Puppeteer facilita la captura de mensajes del navegador con controladores de eventos como estos:

page.on('console', msg => {
    console.log('REGISTRO DE PÁGINA:', msg.text());
});

page.on('pageerror', err => {
    console.error('ERROR DE PÁGINA:', err.message);
});

page.on('requestfailed', request => {
    console.error('SOLICITUD FALLIDA:', request.url());
});

Esta configuración crea un sistema de registro que realiza el seguimiento de mensajes de consola, errores de página y solicitudes fallidas. Para que todo sea más claro, puede categorizar los mensajes por tipo:

Tipo de mensajePropósitoEjemplo de salida
RegistroInformación generalFlujo de ejecución estándar
ErrorProblemas importantesOperaciones fallidas
AdvertenciaPosibles incidenciasRalentizaciones del rendimiento
InformaciónActualizaciones de estadoFinalización de tareas

Buenas prácticas para Console.log

Usar console.log de forma estratégica puede facilitar mucho la depuración. Coloque registros en puntos clave para seguir el progreso e identificar problemas:

// Registrar antes de intentar encontrar un elemento
console.log(`Buscando el elemento: ${selector}`);
const element = await page.$(selector);
// Registrar después de confirmar que el elemento existe
console.log(`Elemento encontrado: ${!!element}`);

// Registrar los datos del formulario antes de rellenarlo
console.log(`Datos del formulario: ${JSON.stringify(formData)}`);
await page.type('#email', formData.email);

Métodos de registro ampliados

Para problemas más complejos, las técnicas avanzadas de registro pueden marcar una gran diferencia:

// Activar depuración detallada para Puppeteer
process.env.DEBUG = 'puppeteer:*';
process.env.DEBUG_MAX_STRING_LENGTH = null;

// Supervisar llamadas de protocolo pendientes
const browser = await puppeteer.launch({
    dumpio: true
});
console.log(browser.debugInfo.pendingProtocolErrors);

Un equipo observó una reducción del 40 % en los fallos de pruebas tras adoptar el registro detallado del protocolo.

// Filtrar mensajes de dominios de red específicos
// Comando: DEBUG="puppeteer:*" DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'

Estos métodos añaden una capa basada en texto a su proceso de depuración, ayudándole a detectar y resolver problemas de forma más eficaz.

sbb-itb-23997f1

Métodos avanzados de depuración

Depurar scripts complejos de Puppeteer implica usar estrategias eficaces de gestión de errores y técnicas avanzadas para garantizar que los scripts se ejecuten sin problemas.

Try-Catch para la gestión de errores

Use bloques try-catch para gestionar errores de forma eficaz y mantener su script en ejecución:

async function navigateAndScreenshot(url, selector) {
    try {
        await page.goto(url, { waitUntil: 'networkidle0' });
        const element = await page.waitForSelector(selector, { timeout: 5000 });
        await element.screenshot({ path: 'element.png' });
    } catch (error) {
        if (error instanceof TimeoutError) {
            console.error(`El elemento ${selector} no se encontró dentro del tiempo de espera`);
            // Añada lógica de recuperación si es necesario
            await page.reload();
        } else {
            console.error(`La navegación falló: ${error.message}`);
            throw error; // Volver a lanzar errores inesperados
        }
    }
}

Puede mejorar la gestión de errores combinando bloques try-catch con clases de error personalizadas para lograr una mejor categorización y respuesta.

Clases de error personalizadas

Crear clases de error personalizadas le ayuda a identificar y clasificar problemas de forma más eficiente:

class PuppeteerScriptError extends Error {
    constructor(message, details = {}) {
        super(message);
        this.name = 'PuppeteerScriptError';
        this.details = details;
        this.timestamp = new Date().toISOString();
    }
}

class SelectorError extends PuppeteerScriptError {
    constructor(selector, context) {
        super(`No se pudo encontrar el selector: ${selector}`, {
            selector,
            context,
            type: 'SELECTOR_ERROR'
        });
        this.name = 'SelectorError';
    }
}

Estas clases le permiten realizar el seguimiento y la depuración de operaciones asíncronas con mayor claridad.

Depuración de código asíncrono

El código asíncrono suele introducir problemas de temporización y promesas sin resolver. Aborde estos problemas con las siguientes técnicas:

// Activar depuración detallada para llamadas de protocolo
const browser = await puppeteer.launch({
    dumpio: true
});

// Supervisar periódicamente las promesas sin resolver
setInterval(() => {
    const pending = browser.debugInfo.pendingProtocolErrors;
    if (pending.length > 0) {
        console.log('Llamadas de protocolo pendientes:', pending);
    }
}, 5000);

// Gestionar errores asíncronos con un mecanismo de tiempo de espera
async function safeExecute(promiseFn) {
    try {
        return await Promise.race([
            promiseFn(),
            new Promise((_, reject) => 
                setTimeout(() => reject(new Error('La operación agotó el tiempo de espera')), 30000)
            )
        ]);
    } catch (error) {
        console.error(`La operación falló: ${error.message}`);
        throw new PuppeteerScriptError('Tiempo de ejecución agotado', {
            originalError: error,
            operation: promiseFn.name
        });
    }
}

Mediante la interfaz debugInfo, puede supervisar callbacks pendientes e identificar promesas sin resolver durante la comunicación con el protocolo del navegador.

Nivel de depuraciónPropósitoImplementación
BásicoGestionar errores habitualesBloques try-catch estándar
IntermedioClasificar erroresJerarquía de clases de error personalizadas
AvanzadoRealizar el seguimiento de problemas de protocoloSupervisión de la interfaz de depuración

Soluciones para problemas habituales

Esta sección aborda desafíos frecuentes con Puppeteer y ofrece soluciones claras para mantener sus scripts de automatización en funcionamiento sin problemas.

Problemas con selectores

Los problemas con selectores pueden interrumpir con frecuencia la ejecución del script. A continuación, se explica cómo gestionarlos eficazmente:

async function findElement(page) {
  try {
    const element = await page.waitForSelector('[data-testid="target"]', {
      timeout: 5000
    });
    return element;
  } catch {
    return page.waitForSelector('.target-class', {
      timeout: 5000
    });
  }
}

Para elementos dentro de iframes o Shadow DOM, use estos enfoques:

// Acceder al contenido de un iframe
const frame = await page.frames().find(f => f.name() === 'content-frame');
const button = await frame.$('button[data-hook="create"]');

// Gestionar elementos de Shadow DOM
await page.evaluateHandle(selector => {
  const element = document.querySelector('parent-element')
    .shadowRoot
    .querySelector(selector);
  return element;
}, 'target-selector');

Gestionar correctamente los selectores garantiza que sus scripts localicen elementos de forma fiable.

Problemas de temporización

Una vez que los selectores son estables, gestionar los tiempos es crucial para una ejecución fluida:

await page.setDefaultNavigationTimeout(30000);
await page.setDefaultTimeout(10000);

async function waitForContent(page) {
  await Promise.all([
    page.waitForNavigation({ waitUntil: 'networkidle0' }),
    page.click('#load-more-button')
  ]);
}

A continuación, encontrará una referencia rápida para los controles de temporización:

Problema de temporizaciónSoluciónImplementación
Carga de páginawaitForNavigationEsperar a que la red esté inactiva
Contenido dinámicowaitForSelectorUsar con un tiempo de espera adecuado
Actualizaciones AJAXwaitForResponseSupervisar solicitudes de red específicas

Estas estrategias ayudan a alinear la temporización de su script con el comportamiento de la página.

Soluciones para bloqueos del navegador

Incluso con estrategias sólidas de selectores y temporización, pueden producirse bloqueos del navegador. A continuación, se explica cómo minimizarlos y recuperarse de ellos:

const browser = await puppeteer.launch({
  args: [
    '--disable-dev-shm-usage',
    '--enable-gpu',
    '--no-first-run',
    '--disable-extensions'
  ]
});

Para la recuperación ante bloqueos:

let browser;
try {
  browser = await puppeteer.launch();
  const page = await browser.newPage();

  page.on('error', err => {
    console.error('La página se bloqueó:', err);
  });

  await page.goto('https://example.com');
} catch (error) {
  console.error('Error del navegador:', error);
} finally {
  if (browser) {
    await browser.close();
  }
}

Si trabaja en Linux, compruebe si faltan dependencias:

ldd chrome | grep not

Para optimizar el uso de recursos, ajuste las flags del navegador:

const browser = await puppeteer.launch({
  args: [
    '--disable-dev-shm-usage',
    '--disable-accelerated-2d-canvas',
    '--disable-gpu'
  ]
});

Configure la recuperación automática para aumentar la resiliencia:

async function checkAndRecoverPage(page) {
  if (!page.isClosed()) {
    try {
      await page.reload();
    } catch {
      page = await browser.newPage();
    }
  }
  return page;
}

Optimización de la depuración de scripts

Mejore sus scripts para facilitar el mantenimiento y resolver errores más rápidamente basándose en técnicas de depuración probadas.

Claridad del código

Mantenga su código legible agrupando configuraciones y utilizando nombres claros y descriptivos:

// Agrupar configuraciones relacionadas
const browserConfig = {
  headless: false,
  defaultViewport: { width: 1920, height: 1080 },
  args: ['--no-sandbox', '--disable-setuid-sandbox']
};

// Usar nombres de función descriptivos
async function validatePageContent(page) {
  const pageTitle = await page.title();
  console.log(`Validando contenido para la página: ${pageTitle}`);

  const contentExists = await page.evaluate(() => {
    const mainContent = document.querySelector('.main-content');
    return {
      hasHeader: !!document.querySelector('header'),
      hasContent: !!mainContent,
      contentLength: mainContent?.textContent.length || 0
    };
  });

  return contentExists;
}

Organización de módulos

Divida sus scripts en módulos independientes para simplificar la depuración. Este enfoque aísla selectores, acciones y validaciones, facilitando la localización y corrección de errores.

// selectors.js
export const SELECTORS = {
  loginForm: '#login-form',
  submitButton: '[data-testid="submit-btn"]',
  errorMessage: '.error-notification'
};

// actions.js
export async function performLogin(page, credentials) {
  await page.type(SELECTORS.loginForm + ' input[name="username"]', credentials.username);
  await page.type(SELECTORS.loginForm + ' input[name="password"]', credentials.password);
  await Promise.all([
    page.waitForNavigation(),
    page.click(SELECTORS.submitButton)
  ]);
}

// validators.js
export async function checkLoginStatus(page) {
  const errorElement = await page.$(SELECTORS.errorMessage);
  if (errorElement) {
    throw new Error('Error de inicio de sesión: ' + await page.evaluate(el => el.textContent, errorElement));
  }
}

Esta estructura modular no solo organiza su código, sino que también ayuda a agilizar el seguimiento de errores.

Configuración del seguimiento de errores

Configure el seguimiento de errores para identificar problemas rápidamente y proporcionar contexto detallado para la depuración:

class PuppeteerError extends Error {
  constructor(message, action, selector) {
    super(message);
    this.name = 'PuppeteerError';
    this.action = action;
    this.selector = selector;
    this.timestamp = new Date().toISOString();
  }
}

async function executeWithTracking(page, action, description) {
  try {
    await action();
  } catch (error) {
    const screenshot = await page.screenshot({
      path: `error-${Date.now()}.png`,
      fullPage: true
    });

    throw new PuppeteerError(
      `No se pudo ${description}`,
      error.message,
      error.selector
    );
  }
}

También puede automatizar el registro de errores y advertencias de consola:

page.on('console', message => {
  const type = message.type();
  const text = message.text();

  if (type === 'error' || type === 'warning') {
    console.log(`[${type.toUpperCase()}] ${text}`);

    // Registrar en un servicio externo o archivo
    logger.log({
      level: type,
      message: text,
      timestamp: new Date().toISOString(),
      url: page.url()
    });
  }
});

Validación de operaciones críticas

Añada comprobaciones de validación para garantizar que las operaciones críticas se completen correctamente:

async function validateOperation(page, action) {
  const beforeState = await page.evaluate(() => ({
    url: window.location.href,
    elements: document.querySelectorAll('*').length
  }));

  await action();

  const afterState = await page.evaluate(() => ({
    url: window.location.href,
    elements: document.querySelectorAll('*').length
  }));

  return {
    urlChanged: beforeState.url !== afterState.url,
    elementsDelta: afterState.elements - beforeState.elements
  };
}

Estas técnicas, combinadas con los métodos de depuración anteriores, le ayudan a identificar y resolver problemas rápidamente mientras mantiene sus scripts fáciles de mantener.

Conclusión

Técnicas clave de depuración

Usar la depuración visual en modo visible con slowMo permite obtener comentarios inmediatos sobre los scripts y realizar ajustes precisos de temporización. Para situaciones más detalladas, el protocolo DevTools ofrece depuración paso a paso y acceso a registros de procesos para obtener información más profunda.

const browser = await puppeteer.launch({
    headless: false,
    slowMo: 100,
    devtools: true,
    dumpio: true
});

Para mejorar su flujo, considere incorporar monitoreo continuo y prácticas de gestión de recursos junto con estos métodos de depuración.

Próximos pasos

Ahora que cuenta con una base sólida en técnicas de depuración, así puede optimizar y mantener sus scripts de Puppeteer:

  • Monitoreo del rendimiento: Use registros detallados para realizar el seguimiento de los tiempos de ejecución y el uso de recursos. Esto ayuda a identificar cuellos de botella y hace que la depuración sea más eficiente.
  • Prevención de errores: Añada el plugin puppeteer-extra-plugin-stealth para minimizar la detección de automatización y reducir los fallos de los scripts.
  • Gestión de recursos: Céntrese en el uso eficiente de la memoria e implemente rutinas de limpieza para que sus scripts sigan funcionando sin problemas.

A continuación, se muestra un ejemplo de una función de limpieza para gestionar los recursos eficazmente:

async function cleanupResources(page) {
    await page.evaluate(() => {
        if (window.performance.memory) {
            console.log(`Límite de tamaño del heap: ${(window.performance.memory.jsHeapSizeLimit / 1024 / 1024).toFixed(2)} MB`);
        }
    });
    await page.close();
}

Manténgase al día revisando periódicamente el repositorio de Puppeteer en GitHub para conocer actualizaciones, nuevas funciones y buenas prácticas. Mantener sus herramientas actualizadas garantiza que sus scripts sigan siendo eficientes y adaptables a medida que evolucionan las tecnologías web.

FAQ

Frequently Asked Questions

Inicie Puppeteer con headless: false, slowMo (normalmente, entre 100 y 250 ms para clics, y hasta 500–1000 ms para contenido dinámico) y devtools: true. Esto le permite observar cada acción en una ventana de navegador visible e inspeccionar elementos en Chrome DevTools mientras se ejecuta el script.

¿Te resultó útil? Compártelo →

Escrito por

Vasiliy Datsenko

Jefe de Soporte al Cliente

Vasiliy Datsenko es Jefe de Soporte al Cliente en Latenode y un escritor de automatización centrado en productos. Su trabajo conecta las conversaciones con los clientes, la investigación sobre automatización de flujos de trabajo, los casos de uso de IA y la educación práctica sobre productos para equipos que intentan automatizar procesos comerciales reales.

Perfil del autor →

Verificado por

Oleg Zankov

CEO Latenode, No-code Expert

Con una ética arraigada en la innovación, la resolución de problemas y la experiencia de usuario, me enfoco en capacitar a los equipos para crear integraciones personalizadas y automatizar flujos de trabajo con facilidad y eficiencia. Trayendo una gran experiencia en desarrollo empresarial, emprendimiento tecnológico y desarrollo de software, reconocí la necesidad de una solución de integración más accesible, escalable y adaptable. Así nació Latenode.com. Con nuestra plataforma, las empresas pueden aprovechar el poder de la tecnología sin necesidad de conocimientos extensos de codificación. Apasionado por fomentar un futuro donde la tecnología nos sirva, y no al revés, mi misión es simplificar procesos complejos. Creo en democratizar la tecnología y equipar a los equipos con las herramientas para innovar, crecer y tener éxito en un mundo cada vez más digital.

Perfil del autor →

Seguir leyendo