Una plataforma de código bajo que combina la simplicidad sin código con el poder del código completo 🚀
Empieza ahora gratis
Depuración de scripts de Puppeteer: del modo cámara lenta a técnicas avanzadas
Marzo 25, 2025
10
min leer

Depuración de scripts de Puppeteer: del modo cámara lenta a técnicas avanzadas

George Miloradovich
Investigador, redactor y entrevistador de casos prácticos
Tabla de contenidos.

Depuración Titiritero Los guiones pueden resultar abrumadores, pero dominar algunas técnicas clave puede ahorrarte tiempo y frustración. Aquí tienes un breve resumen de lo que aprenderás:

  • Comience con la depuración visual: Utiliza slowMo Modo y modo de navegador completo para ver su script en acción.
  • Errores de captura: Agrega try-catch Bloquea y automatiza capturas de pantalla de errores para una mejor resolución de problemas.
  • Aprovechar los registros de la consola:Realice un seguimiento de errores de página, solicitudes fallidas y mensajes personalizados para obtener información más detallada.
  • Selectores de manijas y sincronización:Utilice estrategias de selección sólidas y administre los tiempos de espera para evitar errores comunes.
  • Organiza tu código:Divida los scripts en módulos para acciones, selectores y validaciones para simplificar el mantenimiento.

Ejemplo de configuración rápida:

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

Consejos de depuración:

  1. Habilitar registro:Corre con DEBUG="puppeteer:*" para registros detallados.
  2. Usar capturas de pantalla:Captura los estados de la página para ver qué salió mal.
  3. Gestionar recursos:Limpie siempre las instancias del navegador y de la página para evitar fallos.

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

Configuración del entorno de depuración

Configuración básica 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 habilitar el registro detallado, ejecute su script con el siguiente comando:

DEBUG="puppeteer:*" node script.js

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

Herramientas de depuración necesarias

Aquí hay algunas herramientas que le ayudarán a resolver problemas de manera efectiva:

Propósito Función clave
DevTools de Chrome Inspeccionar scripts Herramientas de consola y red
Código VS Depurador Administrar puntos de interrupción Ejecución paso a paso
Utilidad de captura de pantalla Solución de problemas visuales Capturar estados de página

También puedes agregar puntos de control en tu código para una mejor visibilidad:

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

Organización del guión

Una buena organización es tan importante como las herramientas que utilizas. Divide tu script en módulos lógicos e incluye 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(`Navigation failed: ${error.message}`);
    await page.screenshot({ path: 'error-state.png' });
}

Para reducir la posibilidad de detección de bots, integre el complemento oculto:

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

Por último, asegúrese de gestionar adecuadamente 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.

Titiritero - 3 enfoques a considerar en la depuración

Titiritero

Métodos de depuración visual

Observar tus 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 tus opciones de depuración más allá de los registros de consola y el seguimiento de errores.

Guía del modo cámara lenta

SlowMo introduce un retraso entre las acciones de Puppeteer, lo que hace que sea más fácil seguir lo que está sucediendo:

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

La slowMo El valor (en milisegundos) controla el retraso entre acciones. Ajústalo según lo que estés probando:

Tipo de operación Cámara lenta recomendada (ms) Caso de uso
Clics simples 100-250 Pasos básicos de navegación
El rellenado de formularios 250-500 Prueba de validación de entrada
Contenido dinámico 500-1000 Comprobación de estados de carga

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

Modo de vista del navegador

El modo de vista del navegador le permite ver su script ejecutarse en una ventana visible del navegador, lo que es 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, acme corporaciónEl equipo de control de calidad de [nombre del sitio web] utilizó este modo en junio de 2024 para solucionar problemas con un script de web scraping. Detectaron selectores incorrectos y los solucionaron, reduciendo el tiempo de depuración en un 40 %.

Para complementar esto, capture capturas de pantalla de estados visuales importantes para su posterior análisis.

Grabación visual

Las capturas de pantalla y los videos pueden crear un registro claro de la ejecución de su script, lo que facilita la depuración:

// Screenshot of a specific element
await page.screenshot({
    path: 'element-state.png',
    clip: {
        x: 0,
        y: 0,
        width: 500,
        height: 300
    }
});

// Full-page screenshot
await page.screenshot({
    path: 'full-page.png',
    fullPage: true
});

Empieza por activar el modo de vista del navegador, usa SlowMo para un seguimiento detallado y documenta los momentos clave con capturas de pantalla. Juntos, estos pasos crean un proceso de depuración visual exhaustivo.

Métodos de depuración de la consola

Los métodos de consola ofrecen una forma sencilla de obtener información textual sobre el comportamiento de tus scripts. Estas salidas se complementan con la depuración visual para brindarte detalles precisos sobre la ejecución del script.

Seguimiento de mensajes de la consola

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

page.on('console', msg => {
    console.log('PAGE LOG:', msg.text());
});

page.on('pageerror', err => {
    console.error('PAGE ERROR:', err.message);
});

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

Esta configuración crea un sistema de registro que rastrea los mensajes de la consola, los errores de página y las solicitudes fallidas. Para mayor claridad, puede categorizar los mensajes por tipo:

Tipo de mensaje Propósito Salida de ejemplo
Log Información general Flujo de ejecución estándar
Error Problemas mayores Operaciones fallidas
advertencia Posibles preocupaciones Ralentizaciones del rendimiento
Info Actualizaciones de estado La terminación de la tarea

Mejores prácticas para Console.log

Usando console.log Depurar con prudencia puede facilitar mucho la depuración. Coloque los registros estratégicamente para seguir el progreso e identificar problemas.

// Log before attempting to find an element
console.log(`Looking for element: ${selector}`);
const element = await page.$(selector);
// Log after confirming the element exists
console.log(`Element found: ${!!element}`);

// Log form data before filling it out
console.log(`Form data: ${JSON.stringify(formData)}`);
await page.type('#email', formData.email);

Métodos de registro extendidos

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

// Enable detailed debugging for Puppeteer
process.env.DEBUG = 'puppeteer:*';
process.env.DEBUG_MAX_STRING_LENGTH = null;

// Monitor pending protocol calls
const browser = await puppeteer.launch({
    dumpio: true
});
console.log(browser.debugInfo.pendingProtocolErrors);

Un equipo observó una caída del 40% en las fallas de pruebas luego de adoptar un registro de protocolo detallado.

// Filter out specific network domain messages
// Command: DEBUG="puppeteer:*" DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'

Estos métodos agregan una capa basada en texto a su proceso de depuración, ayudándolo a detectar y resolver problemas de manera más efectiva.

sbb-itb-23997f1

Métodos de depuración avanzados

La depuración de scripts complejos de Puppeteer implica el uso de estrategias efectivas de manejo de errores y técnicas avanzadas para garantizar que los scripts se ejecuten sin problemas.

Try-Catch para el manejo 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(`Element ${selector} not found within timeout`);
            // Add recovery logic if needed
            await page.reload();
        } else {
            console.error(`Navigation failed: ${error.message}`);
            throw error; // Re-throw unexpected errors
        }
    }
}

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

Clases de error personalizadas

La creación de clases de error personalizadas le ayuda a identificar y clasificar problemas de manera 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(`Failed to find selector: ${selector}`, {
            selector,
            context,
            type: 'SELECTOR_ERROR'
        });
        this.name = 'SelectorError';
    }
}

Estas clases le permiten rastrear y depurar operaciones asincrónicas con más claridad.

Depuración de código asincrónico

El código asincrónico suele generar problemas de sincronización y promesas sin resolver. Aborde estos problemas con las siguientes técnicas:

// Enable detailed debugging for protocol calls
const browser = await puppeteer.launch({
    dumpio: true
});

// Monitor unresolved promises periodically
setInterval(() => {
    const pending = browser.debugInfo.pendingProtocolErrors;
    if (pending.length > 0) {
        console.log('Pending protocol calls:', pending);
    }
}, 5000);

// Handle async errors with a timeout mechanism
async function safeExecute(promiseFn) {
    try {
        return await Promise.race([
            promiseFn(),
            new Promise((_, reject) => 
                setTimeout(() => reject(new Error('Operation timed out')), 30000)
            )
        ]);
    } catch (error) {
        console.error(`Operation failed: ${error.message}`);
        throw new PuppeteerScriptError('Execution timeout', {
            originalError: error,
            operation: promiseFn.name
        });
    }
}

Mediante el uso de la debugInfo Interfaz, puede monitorear devoluciones de llamadas pendientes e identificar promesas no resueltas durante la comunicación del protocolo del navegador.

Nivel de depuración Propósito Implementación
Funda Térmica Manejar errores comunes Bloques try-catch estándar
Intermedio Clasificar errores Jerarquía de clases de error personalizada
Advanzado Problemas con el protocolo de seguimiento Monitoreo de la interfaz de depuración

Soluciones a problemas comunes

Esta sección analiza los desafíos frecuentes con Puppeteer y proporciona soluciones claras para mantener sus scripts de automatización funcionando sin problemas.

Problemas con el selector

Los problemas con el selector a menudo pueden interrumpir la ejecución del script. Aquí te explicamos cómo solucionarlos 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 DOM de sombra, utilice estos enfoques:

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

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

El manejo adecuado de los selectores garantiza que sus scripts localicen los elementos de manera confiable.

Problemas de sincronización

Una vez que los selectores son estables, la gestión del tiempo 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 se muestra una referencia rápida para los controles de tiempo:

Problema de tiempo Solución Implementación
Carga de página esperarNavegación Espere a que la red esté inactiva
Contenido dinámico esperarAlSelector Úselo con el tiempo de espera apropiado
Actualizaciones de AJAX esperarRespuesta Monitorear solicitudes de red específicas

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

Correcciones de fallos del navegador

Incluso con estrategias de selección y sincronización sólidas, el navegador puede fallar. Aquí te explicamos cómo minimizarlas y recuperarte:

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

Para la recuperación ante fallos:

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

  page.on('error', err => {
    console.error('Page crashed:', err);
  });

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

Si está trabajando en Linux, verifique si faltan dependencias:

ldd chrome | grep not

Para optimizar el uso de recursos, ajuste las banderas 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 una mayor resiliencia:

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

Optimización de depuración de scripts

Mejore sus scripts para facilitar el mantenimiento y lograr una resolución de errores más rápida aprovechando técnicas de depuración probadas.

Claridad de código

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

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

// Use descriptive function names
async function validatePageContent(page) {
  const pageTitle = await page.title();
  console.log(`Validating content for page: ${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 del módulo

Divida sus scripts en módulos separados para simplificar la depuración. Este enfoque aísla selectores, acciones y validaciones, lo que facilita 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('Login failed: ' + await page.evaluate(el => el.textContent, errorElement));
  }
}

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

Configuración de seguimiento de errores

Configure el seguimiento de errores para identificar problemas rápidamente y proporcionar un 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(
      `Failed to ${description}`,
      error.message,
      error.selector
    );
  }
}

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

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

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

    // Log to external service or file
    logger.log({
      level: type,
      message: text,
      timestamp: new Date().toISOString(),
      url: page.url()
    });
  }
});

Validación para operaciones críticas

Agregue 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 métodos de depuración anteriores, le ayudan a identificar y resolver problemas rápidamente y, al mismo tiempo, a mantener sus scripts en condiciones de mantenimiento.

Conclusión

Técnicas clave de depuración

Usando la depuración visual en modo headful con slowMo Permite obtener retroalimentación inmediata sobre los scripts y ajustes precisos de la sincronización. Para escenarios más detallados, el protocolo DevTools proporciona depuración paso a paso y acceso a los registros de procesos para obtener información más detallada.

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

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

PWOCHEN ETAP YO

Ahora que tienes una base sólida en técnicas de depuración, aquí te mostramos cómo puedes optimizar y mantener tus scripts de Puppeteer:

  • Supervisión del rendimientoUtilice registros detallados para controlar los tiempos de ejecución y el uso de recursos. Esto ayuda a identificar cuellos de botella y a optimizar la depuración.
  • Prevención de errores: Añade el puppeteer-extra-plugin-stealth Complemento para minimizar la detección de automatización y reducir fallas de script.
  • Gestión de Recursos:Concéntrese en el uso eficiente de la memoria e implemente rutinas de limpieza para mantener sus scripts funcionando sin problemas.

A continuación se muestra un ejemplo de una función de limpieza para administrar recursos de manera eficaz:

async function cleanupResources(page) {
    await page.evaluate(() => {
        if (window.performance.memory) {
            console.log(`Heap size limit: ${(window.performance.memory.jsHeapSizeLimit / 1024 / 1024).toFixed(2)} MB`);
        }
    });
    await page.close();
}

Manténgase a la vanguardia consultando regularmente el repositorio de Puppeteer en GitHub para obtener actualizaciones, nuevas funciones y mejores prácticas. Mantener su conjunto de herramientas actualizado garantiza que sus scripts se mantengan eficientes y adaptables a medida que las tecnologías web cambian.

Artículos relacionados con

Blogs relacionados

Caso de uso

Respaldado por