Depurar scripts do Puppeteer pode parecer desafiador, mas dominar algumas técnicas essenciais pode economizar tempo e frustração. Veja um resumo rápido do que você vai aprender:
- Comece com a depuração visual: use o modo
slowMoe o modo de navegador com interface para observar seu script em ação. - Capture erros: adicione blocos
try-catche automatize capturas de tela de erros para solucionar problemas com mais eficiência. - Aproveite os logs do console: acompanhe erros de página, solicitações com falha e mensagens personalizadas para obter insights mais detalhados.
- Lide com seletores e temporização: use estratégias robustas de seletores e gerencie os tempos limite para evitar problemas comuns.
- Organize seu código: divida os scripts em módulos para ações, seletores e validações a fim de simplificar a manutenção.
Exemplo de configuração rápida:
const browser = await puppeteer.launch({
headless: false,
slowMo: 100,
devtools: true
});
Dicas de depuração:
- Ative os logs: execute com
DEBUG="puppeteer:*"para obter logs detalhados. - Use capturas de tela: registre os estados da página para ver o que deu errado.
- Gerencie recursos: sempre limpe as instâncias do navegador e da página para evitar falhas.
Ao combinar essas técnicas, você otimiza seu processo de depuração e melhora a confiabilidade dos seus scripts do Puppeteer.
Configuração do ambiente de depuração
Configurações básicas de depuração
Configure o Puppeteer para depuração com estas opções de inicialização:
const browser = await puppeteer.launch({
headless: false,
slowMo: 20,
devtools: true
});
Para ativar logs detalhados, execute seu script com o seguinte comando:
DEBUG="puppeteer:*" node script.js
Depois de configurar tudo, use ferramentas de depuração para analisar e aprimorar o comportamento do script.
Ferramentas de depuração necessárias
Veja algumas ferramentas que ajudam a resolver problemas com eficiência:
| Ferramenta | Finalidade | Recurso principal |
|---|---|---|
| Chrome DevTools | Inspecionar scripts | Ferramentas de console e rede |
| Depurador do VS Code | Gerenciar pontos de interrupção | Execução passo a passo |
| Utilitário de captura de tela | Solução visual de problemas | Captura estados da página |
Você também pode adicionar pontos de verificação ao código para ter mais visibilidade:
await page.screenshot({ path: 'before_click.png' });
await page.click('#button');
await page.screenshot({ path: 'after_click.png' });
Organização do script
Uma boa organização é tão importante quanto as ferramentas que você usa. Divida seu script em módulos lógicos e inclua tratamento de erros para uma depuração mais fluida:
try {
await page.waitForSelector('#target-element');
await page.click('#target-element');
} catch (error) {
console.error(`Falha na navegação: ${error.message}`);
await page.screenshot({ path: 'error-state.png' });
}
Para reduzir a probabilidade de detecção de bots, integre o plugin stealth:
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
Por fim, garanta o gerenciamento adequado de recursos implementando procedimentos de limpeza:
async function cleanup() {
if (page) await page.close();
if (browser) await browser.close();
}
Essa configuração oferece uma base sólida para depuração visual e pelo console em seus projetos.
Puppeteer - 3 abordagens para considerar na depuração
Métodos de depuração visual
Observar seus scripts em ação pode revelar problemas que a análise tradicional de código talvez não detecte. Esses métodos ampliam suas opções de depuração além dos logs do console e do acompanhamento de erros.
Guia do modo SlowMo
O SlowMo introduz um atraso entre as ações do Puppeteer, facilitando o acompanhamento do que está acontecendo:
const browser = await puppeteer.launch({
headless: false,
slowMo: 250,
devtools: true
});
O valor de slowMo (em milissegundos) controla o atraso entre as ações. Ajuste-o conforme o que você estiver testando:
| Tipo de operação | SlowMo recomendado (ms) | Caso de uso |
|---|---|---|
| Cliques simples | 100–250 | Etapas básicas de navegação |
| Preenchimento de formulários | 250–500 | Teste de validação de entrada |
| Conteúdo dinâmico | 500–1000 | Verificação de estados de carregamento |
Depois de configurar o SlowMo, combine-o com o modo de visualização do navegador para monitorar o comportamento da interface durante a execução do script.
Modo de visualização do navegador
O modo de visualização do navegador permite ver seu script sendo executado em uma janela visível do navegador, o que é especialmente útil para depurar conteúdo dinâmico e interações complexas.
const browser = await puppeteer.launch({
headless: false,
defaultViewport: { width: 1700, height: 800 },
args: ['--start-maximized']
});
Por exemplo, a equipe de QA da Acme Corp usou esse modo em junho de 2024 para solucionar problemas em um script de web scraping. Eles identificaram seletores incorretos e os corrigiram, reduzindo o tempo de depuração em 40%.
Para complementar esse processo, capture telas de estados visuais importantes para analisá-los depois.
Registro visual
Capturas de tela e vídeos podem criar um registro claro da execução do seu script, facilitando a depuração:
// Captura de tela de um elemento específico
await page.screenshot({
path: 'element-state.png',
clip: {
x: 0,
y: 0,
width: 500,
height: 300
}
});
// Captura de tela da página inteira
await page.screenshot({
path: 'full-page.png',
fullPage: true
});
Comece ativando o modo de visualização do navegador, use o SlowMo para acompanhamento detalhado e documente momentos importantes com capturas de tela. Juntas, essas etapas criam um processo completo de depuração visual.
Métodos de depuração pelo console
Os métodos de console oferecem uma forma direta de obter insights baseados em texto sobre o comportamento dos seus scripts. Essas saídas funcionam junto à depuração visual e fornecem detalhes precisos sobre a execução do script.
Acompanhamento de mensagens do console
O Puppeteer facilita a captura de mensagens do navegador com manipuladores de eventos como estes:
page.on('console', msg => {
console.log('LOG DA PÁGINA:', msg.text());
});
page.on('pageerror', err => {
console.error('ERRO DA PÁGINA:', err.message);
});
page.on('requestfailed', request => {
console.error('SOLICITAÇÃO FALHOU:', request.url());
});
Essa configuração cria um sistema de logs que acompanha mensagens do console, erros de página e solicitações com falha. Para deixar tudo mais claro, você pode categorizar as mensagens por tipo:
| Tipo de mensagem | Finalidade | Exemplo de saída |
|---|---|---|
| Log | Informações gerais | Fluxo padrão de execução |
| Erro | Problemas graves | Operações com falha |
| Aviso | Possíveis preocupações | Quedas de desempenho |
| Informação | Atualizações de status | Conclusão de tarefa |
Boas práticas para console.log
Usar console.log de forma inteligente pode facilitar muito a depuração. Posicione logs estrategicamente para acompanhar o progresso e identificar problemas:
// Registre antes de tentar encontrar um elemento
console.log(`Procurando elemento: ${selector}`);
const element = await page.$(selector);
// Registre após confirmar que o elemento existe
console.log(`Elemento encontrado: ${!!element}`);
// Registre os dados do formulário antes de preenchê-lo
console.log(`Dados do formulário: ${JSON.stringify(formData)}`);
await page.type('#email', formData.email);
Métodos de logging estendidos
Para problemas mais complexos, técnicas avançadas de logging podem fazer toda a diferença:
// Ative a depuração detalhada do Puppeteer
process.env.DEBUG = 'puppeteer:*';
process.env.DEBUG_MAX_STRING_LENGTH = null;
// Monitore chamadas de protocolo pendentes
const browser = await puppeteer.launch({
dumpio: true
});
console.log(browser.debugInfo.pendingProtocolErrors);
Uma equipe observou uma redução de 40% nas falhas de teste após adotar logs detalhados de protocolo.
// Filtre mensagens de um domínio de rede específico
// Comando: DEBUG="puppeteer:*" DEBUG_COLORS=true node script.js 2>&1 | grep -v '"Network'
Esses métodos adicionam uma camada baseada em texto ao seu processo de depuração, ajudando você a identificar e resolver problemas com mais eficiência.
sbb-itb-23997f1
Métodos avançados de depuração
Depurar scripts complexos do Puppeteer envolve usar estratégias eficazes de tratamento de erros e técnicas avançadas para garantir uma execução fluida.
Try-Catch para tratamento de erros
Use blocos try-catch para gerenciar erros com eficiência e manter seu script em execução:
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(`Elemento ${selector} não foi encontrado dentro do tempo limite`);
// Adicione lógica de recuperação, se necessário
await page.reload();
} else {
console.error(`Falha na navegação: ${error.message}`);
throw error; // Reenvie erros inesperados
}
}
}
Você pode aprimorar o tratamento de erros combinando blocos try-catch com classes de erro personalizadas para obter melhor categorização e resposta.
Classes de erro personalizadas
Criar classes de erro personalizadas ajuda você a identificar e classificar problemas com mais eficiência:
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(`Falha ao encontrar o seletor: ${selector}`, {
selector,
context,
type: 'SELECTOR_ERROR'
});
this.name = 'SelectorError';
}
}
Essas classes permitem acompanhar e depurar operações assíncronas com mais clareza.
Depuração de código assíncrono
O código assíncrono geralmente introduz problemas de temporização e promises não resolvidas. Resolva esses problemas com as seguintes técnicas:
// Ative a depuração detalhada para chamadas de protocolo
const browser = await puppeteer.launch({
dumpio: true
});
// Monitore periodicamente promises não resolvidas
setInterval(() => {
const pending = browser.debugInfo.pendingProtocolErrors;
if (pending.length > 0) {
console.log('Chamadas de protocolo pendentes:', pending);
}
}, 5000);
// Trate erros assíncronos com um mecanismo de tempo limite
async function safeExecute(promiseFn) {
try {
return await Promise.race([
promiseFn(),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('A operação excedeu o tempo limite')), 30000)
)
]);
} catch (error) {
console.error(`Falha na operação: ${error.message}`);
throw new PuppeteerScriptError('Tempo limite de execução', {
originalError: error,
operation: promiseFn.name
});
}
}
Ao usar a interface debugInfo, você pode monitorar callbacks pendentes e identificar promises não resolvidas durante a comunicação com o protocolo do navegador.
| Nível de depuração | Finalidade | Implementação |
|---|---|---|
| Básico | Tratar erros comuns | Blocos try-catch padrão |
| Intermediário | Classificar erros | Hierarquia de classes de erro personalizadas |
| Avançado | Acompanhar problemas de protocolo | Monitoramento da interface de depuração |
Soluções para problemas comuns
Esta seção aborda desafios frequentes no Puppeteer e apresenta correções claras para manter seus scripts de automação funcionando sem problemas.
Problemas com seletores
Problemas de seletor muitas vezes podem interromper a execução do script. Veja como lidar com eles de forma eficaz:
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 ou do Shadow DOM, use estas abordagens:
// Acesse o conteúdo do iframe
const frame = await page.frames().find(f => f.name() === 'content-frame');
const button = await frame.$('button[data-hook="create"]');
// Lide com elementos do Shadow DOM
await page.evaluateHandle(selector => {
const element = document.querySelector('parent-element')
.shadowRoot
.querySelector(selector);
return element;
}, 'target-selector');
O tratamento adequado dos seletores garante que seus scripts localizem elementos de forma confiável.
Problemas de temporização
Quando os seletores estão estáveis, gerenciar a temporização é essencial para uma execução 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')
]);
}
Veja uma referência rápida dos controles de temporização:
| Problema de temporização | Solução | Implementação |
|---|---|---|
| Carregamento da página | waitForNavigation | Aguarde a rede ficar ociosa |
| Conteúdo dinâmico | waitForSelector | Use com o tempo limite adequado |
| Atualizações AJAX | waitForResponse | Monitore solicitações de rede específicas |
Essas estratégias ajudam a alinhar a temporização do seu script ao comportamento da página.
Correções para falhas do navegador
Mesmo com estratégias sólidas de seletores e temporização, falhas no navegador ainda podem ocorrer. Veja como minimizá-las e se recuperar delas:
const browser = await puppeteer.launch({
args: [
'--disable-dev-shm-usage',
'--enable-gpu',
'--no-first-run',
'--disable-extensions'
]
});
Para recuperação após falhas:
let browser;
try {
browser = await puppeteer.launch();
const page = await browser.newPage();
page.on('error', err => {
console.error('A página travou:', err);
});
await page.goto('https://example.com');
} catch (error) {
console.error('Erro do navegador:', error);
} finally {
if (browser) {
await browser.close();
}
}
Se você estiver trabalhando no Linux, verifique se há dependências ausentes:
ldd chrome | grep not
Para otimizar o uso de recursos, ajuste as flags do navegador:
const browser = await puppeteer.launch({
args: [
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--disable-gpu'
]
});
Configure a recuperação automática para adicionar resiliência:
async function checkAndRecoverPage(page) {
if (!page.isClosed()) {
try {
await page.reload();
} catch {
page = await browser.newPage();
}
}
return page;
}
Otimização da depuração de scripts
Aprimore seus scripts para facilitar a manutenção e resolver erros mais rapidamente, aproveitando técnicas comprovadas de depuração.
Clareza do código
Mantenha seu código legível agrupando configurações e usando nomes claros e descritivos:
// Agrupe configurações relacionadas
const browserConfig = {
headless: false,
defaultViewport: { width: 1920, height: 1080 },
args: ['--no-sandbox', '--disable-setuid-sandbox']
};
// Use nomes descritivos para funções
async function validatePageContent(page) {
const pageTitle = await page.title();
console.log(`Validando conteúdo da 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;
}
Organização de módulos
Divida seus scripts em módulos separados para simplificar a depuração. Essa abordagem isola seletores, ações e validações, facilitando a localização e a correção de erros.
// 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('Falha no login: ' + await page.evaluate(el => el.textContent, errorElement));
}
}
Essa estrutura modular não apenas organiza seu código, mas também ajuda a otimizar o acompanhamento de erros.
Configuração de acompanhamento de erros
Configure o acompanhamento de erros para identificar problemas rapidamente e fornecer um contexto detalhado para a depuração:
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(
`Falha ao ${description}`,
error.message,
error.selector
);
}
}
Você também pode automatizar o registro de erros e avisos do console:
page.on('console', message => {
const type = message.type();
const text = message.text();
if (type === 'error' || type === 'warning') {
console.log(`[${type.toUpperCase()}] ${text}`);
// Registre em um serviço externo ou arquivo
logger.log({
level: type,
message: text,
timestamp: new Date().toISOString(),
url: page.url()
});
}
});
Validação de operações críticas
Adicione verificações de validação para garantir que operações críticas sejam concluídas com sucesso:
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
};
}
Essas técnicas, combinadas aos métodos de depuração anteriores, ajudam você a identificar e resolver problemas rapidamente, mantendo seus scripts fáceis de gerenciar.
Conclusão
Principais técnicas de depuração
Usar a depuração visual no modo com interface, com slowMo, permite obter feedback imediato sobre os scripts e fazer ajustes precisos de temporização. Para situações mais detalhadas, o protocolo DevTools oferece depuração passo a passo e acesso aos logs de processo para insights mais profundos.
const browser = await puppeteer.launch({
headless: false,
slowMo: 100,
devtools: true,
dumpio: true
});
Para melhorar seu fluxo, considere incorporar monitoramento contínuo e práticas de gerenciamento de recursos a esses métodos de depuração.
Próximos passos
Agora que você tem uma base sólida de técnicas de depuração, veja como otimizar e manter seus scripts do Puppeteer:
- Monitoramento de desempenho: use logs detalhados para acompanhar tempos de execução e uso de recursos. Isso ajuda a identificar gargalos e torna a depuração mais eficiente.
- Prevenção de erros: adicione o plugin
puppeteer-extra-plugin-stealthpara minimizar a detecção de automação e reduzir falhas nos scripts. - Gerenciamento de recursos: priorize o uso eficiente de memória e implemente rotinas de limpeza para manter seus scripts funcionando sem problemas.
Veja um exemplo de função de limpeza para gerenciar recursos com eficiência:
async function cleanupResources(page) {
await page.evaluate(() => {
if (window.performance.memory) {
console.log(`Limite de tamanho do heap: ${(window.performance.memory.jsHeapSizeLimit / 1024 / 1024).toFixed(2)} MB`);
}
});
await page.close();
}
Mantenha-se atualizado verificando regularmente o repositório GitHub do Puppeteer para acompanhar atualizações, novos recursos e boas práticas. Manter seu conjunto de ferramentas atualizado garante que seus scripts permaneçam eficientes e adaptáveis à medida que as tecnologias web evoluem.


