ACCESIBLES
PRODUCTO
SOLUCIONES
por casos de uso
AI Plomo GestiónFacturaciónRedes socialesGestión de proyectos
Gestión de datos por sector
Más información
BlogPlantillasVideosYouTubeRECURSOS
COMUNIDADES Y REDES SOCIALES
SOCIOS
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:
slowMo
Modo y modo de navegador completo para ver su script en acción.try-catch
Bloquea y automatiza capturas de pantalla de errores para una mejor resolución de problemas.const browser = await puppeteer.launch({
headless: false,
slowMo: 100,
devtools: true
});
DEBUG="puppeteer:*"
para registros detallados.Al combinar estas técnicas, agilizará su proceso de depuración y mejorará la confiabilidad de sus scripts de Puppeteer.
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.
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' });
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.
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.
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.
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.
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.
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.
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 |
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);
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.
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.
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.
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.
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 |
Esta sección analiza los desafíos frecuentes con Puppeteer y proporciona soluciones claras para mantener sus scripts de automatización funcionando sin problemas.
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.
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.
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;
}
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.
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;
}
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.
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()
});
}
});
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.
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.
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:
puppeteer-extra-plugin-stealth
Complemento para minimizar la detección de automatización y reducir fallas de script.
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.