Latenode

Depuração de scripts Puppeteer: do modo slowMo a técnicas avançadas

Domine técnicas essenciais de depuração para scripts Puppeteer, de métodos visuais ao tratamento avançado de erros, e aumente a confiabilidade dos seus scripts.

9 min de leitura
Tela de depuração de script Puppeteer com ferramentas de desenvolvedor abertas

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 slowMo e o modo de navegador com interface para observar seu script em ação.
  • Capture erros: adicione blocos try-catch e 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:

  1. Ative os logs: execute com DEBUG="puppeteer:*" para obter logs detalhados.
  2. Use capturas de tela: registre os estados da página para ver o que deu errado.
  3. 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:

FerramentaFinalidadeRecurso principal
Chrome DevToolsInspecionar scriptsFerramentas de console e rede
Depurador do VS CodeGerenciar pontos de interrupçãoExecução passo a passo
Utilitário de captura de telaSolução visual de problemasCaptura 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çãoSlowMo recomendado (ms)Caso de uso
Cliques simples100–250Etapas básicas de navegação
Preenchimento de formulários250–500Teste de validação de entrada
Conteúdo dinâmico500–1000Verificaçã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 mensagemFinalidadeExemplo de saída
LogInformações geraisFluxo padrão de execução
ErroProblemas gravesOperações com falha
AvisoPossíveis preocupaçõesQuedas de desempenho
InformaçãoAtualizações de statusConclusã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çãoFinalidadeImplementação
BásicoTratar erros comunsBlocos try-catch padrão
IntermediárioClassificar errosHierarquia de classes de erro personalizadas
AvançadoAcompanhar problemas de protocoloMonitoramento 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çãoSoluçãoImplementação
Carregamento da páginawaitForNavigationAguarde a rede ficar ociosa
Conteúdo dinâmicowaitForSelectorUse com o tempo limite adequado
Atualizações AJAXwaitForResponseMonitore 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-stealth para 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.

FAQ

Frequently Asked Questions

Inicie o Puppeteer com headless: false, slowMo (normalmente de 100 a 250 ms para cliques e de até 500 a 1000 ms para conteúdo dinâmico) e devtools: true. Assim, você pode acompanhar cada ação em uma janela visível do navegador e inspecionar elementos no Chrome DevTools enquanto o script é executado.

Isso foi útil? Compartilhe →

Escrito por

Vasiliy Datsenko

Head of Customer Support

Vasiliy Datsenko é Head of Customer Support na Latenode e um escritor de automação focado em produto. Seu trabalho conecta conversas com clientes, pesquisa de automação de fluxos de trabalho, casos de uso de IA e educação prática sobre produtos para equipes que tentam automatizar processos de negócios reais.

Perfil do autor →

Verificado por

Oleg Zankov

CEO da Latenode, Especialista em No-code

Com uma filosofia enraizada em inovação, resolução de problemas e experiência do usuário, estou focado em capacitar equipes a criar integrações personalizadas e automatizar fluxos de trabalho com facilidade e eficiência. Trazendo uma vasta experiência em desenvolvimento de negócios, empreendedorismo tecnológico e desenvolvimento de software, reconheci a necessidade de uma solução de integração mais acessível, escalável e adaptável. Assim, nasceu a Latenode.com. Com nossa plataforma, as empresas podem aproveitar o poder da tecnologia sem a necessidade de conhecimentos extensos em programação. Apaixonado por promover um futuro onde a tecnologia nos serve, e não o contrário, minha missão é tornar processos complexos simples. Acredito em democratizar a tecnologia e equipar as equipes com as ferramentas para inovar, crescer e ter sucesso em um mundo cada vez mais digital.

Perfil do autor →

Continue lendo