Latenode

Puppeteer Wait for Network Idle: guia completo de métodos de espera

Aprenda estratégias de espera eficazes no Puppeteer para aumentar a confiabilidade e a velocidade dos seus scripts de automação web.

8 min de leitura
Ilustração de estratégias de espera e conexões de rede no Puppeteer

Com dificuldades com scripts do Puppeteer que expiram ou falham? Veja como corrigir.

O Puppeteer, uma biblioteca Node.js para controlar o Chrome, é poderoso para automação web. Mas conteúdo dinâmico e páginas orientadas por API podem tornar a temporização complexa. Estratégias de espera adequadas garantem que seus scripts funcionem de forma confiável e eficiente.

Principais pontos:

  • waitForSelector(): Aguarda o surgimento de elementos, como botões ou formulários.
  • waitForNavigation(): Gerencia transições de página e garante carregamentos completos.
  • waitForNetworkIdle(): Ideal para páginas com uso intenso de APIs, aguarda a conclusão de todas as solicitações de rede.
  • Condições personalizadas: Use waitForFunction() para situações complexas, como conteúdo dinâmico ou animações.

Dicas rápidas:

  • Ajuste os limites de tempo usando page.setDefaultTimeout() para lidar com páginas de carregamento lento.
  • Combine vários métodos de espera com Promise.all() para ter mais confiabilidade.
  • Depure erros de espera monitorando solicitações de rede ou verificando a visibilidade dos elementos.

Comece com estas estratégias para tornar seus scripts do Puppeteer mais rápidos, confiáveis e adequados a aplicações web modernas.

Como aguardar / pausar por N segundos no puppeteer?

Como o Puppeteer lida com esperas

Ao usar o Puppeteer para automação, entender como ele lida com esperas é essencial para criar scripts que funcionam de forma confiável. O Puppeteer inclui configurações padrão de limite de tempo para evitar que os scripts fiquem travados indefinidamente, mas essas configurações podem precisar de ajustes ou estratégias personalizadas para situações mais complexas.

Configurações de limite de tempo integradas

O Puppeteer define limites de tempo padrão para gerenciar tarefas como navegação, seleção de elementos, solicitações de rede, consultas XPath e funções personalizadas. Isso garante que seus scripts não fiquem travados indefinidamente caso algo dê errado ou demore demais [2].

Você pode modificar esses padrões com page.setDefaultTimeout(timeout) [2]. Por exemplo, se sua aplicação demora mais para carregar funcionalidades complexas, aumentar o limite de tempo pode ajudar seu script a evitar o encerramento prematuro. Embora sejam convenientes, essas configurações padrão nem sempre correspondem ao comportamento de aplicações dinâmicas.

Desafios das configurações padrão

As aplicações web modernas frequentemente dependem do carregamento dinâmico de conteúdo, o que pode tornar insuficientes os mecanismos padrão de espera do Puppeteer. O Puppeteer oferece duas condições de inatividade de rede para ajudar a gerenciar isso:

  • networkidle0: Aguarda até não haver conexões de rede por 500 ms [1].
  • networkidle2: Aguarda até que não haja mais de 2 conexões de rede por 500 ms [1].

No entanto, essas condições nem sempre correspondem ao comportamento das aplicações web. Problemas comuns incluem:

  • Carregamento de conteúdo via JavaScript após o DOM estar pronto
  • Atualização de elementos em resposta a chamadas de API
  • Rolagem infinita carregando conteúdo adicional
  • Aplicações de página única atualizando visualizações dinamicamente

Para lidar com esses desafios, experimente usar um bloco try-catch para gerenciar erros de limite de tempo [2]. Isso permite que seu script evite falhas abruptas e aplique estratégias alternativas quando necessário. Em vez de depender de atrasos fixos, considere criar condições de espera com base no status real da página [3]. Essa abordagem é mais flexível e mais adequada para ambientes dinâmicos.

Principais métodos de espera no Puppeteer

O Puppeteer oferece três métodos principais para lidar com a detecção de elementos, a navegação de páginas e a atividade de rede. Esses métodos ajudam a gerenciar interações com eficiência, especialmente em ambientes web dinâmicos.

Usando waitForSelector()

O método waitForSelector() pausa a execução até que um elemento específico apareça na página. Isso é especialmente útil para conteúdo carregado dinamicamente em aplicações de página única (SPAs).

Veja como usá-lo:

// Wait for an element to appear
await page.waitForSelector('.button-class');

// Wait for the element to be visible
await page.waitForSelector('.button-class', { visible: true });

// Set a custom timeout
await page.waitForSelector('.button-class', { timeout: 5000 });

Esse método garante que seu script interaja com os elementos somente quando eles estiverem prontos.

Usando waitForNavigation()

O método waitForNavigation() foi criado para lidar com transições de página. Ele aguarda o carregamento completo da página após eventos como clicar em um link ou enviar um formulário.

await Promise.all([
  page.waitForNavigation(),
  page.click('.navigation-link')
]);

Você pode personalizar seu comportamento com opções:

OpçãoDescriçãoMelhor para
waitUntil: 'load'Aguarda o disparo do evento de carregamento da páginaPáginas estáticas
waitUntil: 'domcontentloaded'Aguarda o carregamento completo do DOMInterações rápidas
waitUntil: 'networkidle0'Aguarda até que não haja solicitações de rede ativasAplicações complexas

Essa flexibilidade garante uma gestão fluida da navegação em diferentes situações.

Usando waitForNetworkIdle()

A opção waitForNetworkIdle() é ideal para monitorar a atividade de rede. Ela aguarda até que a rede esteja completamente inativa ou quase inativa.

// Wait for all network requests to finish
await page.goto(url, { waitUntil: 'networkidle0' });

// Allow up to 2 active connections (e.g., WebSockets)
await page.goto(url, { waitUntil: 'networkidle2' });

Por exemplo:

try {
  await page.waitForNavigation({ waitUntil: 'networkidle0', timeout: 30000 });
  await page.waitForSelector('.dynamic-content', { visible: true });
} catch (error) {
  console.error('Loading timeout occurred');
}

Use networkidle0 para aguardar a conclusão completa das solicitações ou networkidle2 nos casos em que conexões em segundo plano possam permanecer ativas.

Esses métodos são fundamentais para criar scripts de automação web confiáveis, garantindo que suas interações com páginas web sejam consistentes e eficientes.

sbb-itb-23997f1

Técnicas complexas de espera

Às vezes, métodos básicos de espera simplesmente não são suficientes. Para situações mais elaboradas, técnicas avançadas são o melhor caminho.

Condições de espera personalizadas

Quando seletores padrão não são suficientes, você pode usar waitForFunction() para definir condições de espera personalizadas com base no estado da página ou em expressões JavaScript.

// Wait for a specific number of elements to load
await page.waitForFunction(() => {
  return document.querySelectorAll('.product-card').length > 5;
});

// Wait for dynamic content and validate its state
await page.waitForFunction(
  (expectedText) => {
    const element = document.querySelector('.status');
    return element && element.innerText.includes(expectedText);
  },
  {},
  'Ready'
);

Você também pode combinar várias condições para situações mais complexas:

await page.waitForFunction(() => {
  const isLoaded = document.readyState === 'complete';
  const hasContent = document.querySelector('.content')?.innerHTML.length > 0;
  const noSpinner = !document.querySelector('.loading-spinner');
  return isLoaded && hasContent && noSpinner;
});

Agora, vamos avançar um pouco mais gerenciando várias condições simultaneamente.

Vários métodos de espera

Para aplicações complexas, muitas vezes é necessário aguardar várias condições ao mesmo tempo. Usar Promise.all() pode ajudar a gerenciá-las com eficiência.

Exemplo de envio de formulário dinâmico:

// Handle form submission with multiple conditions
const submitForm = async () => {
  await Promise.all([
    page.waitForNavigation({ waitUntil: 'networkidle0' }),
    page.waitForFunction(() => !document.querySelector('.processing')),
    page.click('#submit-button')
  ]);
};

Lidando com condições de corrida:

Às vezes, você precisa continuar assim que a primeira condição for atendida. Para isso, pode usar Promise.race():

// Wait for either a success or error message
const waitForResponse = async () => {
  await Promise.race([
    page.waitForSelector('.success-message'),
    page.waitForSelector('.error-message')
  ]);
};

Situações complexas de carregamento:

Veja um exemplo de gerenciamento de carregamento de conteúdo dinâmico com várias condições:

const loadDynamicContent = async () => {
  await page.click('.load-more');
  await Promise.all([
    page.waitForFunction(() => {
      return window.scrollY + window.innerHeight >= document.documentElement.scrollHeight;
    }),
    page.waitForSelector('.new-items', { visible: true }),
    page.waitForFunction(() => {
      return document.querySelectorAll('.item').length > 10;
    })
  ]);
};

Essas técnicas ajudam você a criar scripts de automação mais robustos, capazes de lidar com aplicações web complexas que têm operações assíncronas e conteúdo dinâmico.

Como tornar os métodos de espera mais rápidos

Aprimorar os métodos de espera pode melhorar significativamente a velocidade e a confiabilidade dos scripts de automação. Ao combinar técnicas manuais mais inteligentes com estratégias orientadas por IA, você pode obter uma execução mais rápida sem comprometer a estabilidade.

Velocidade versus estabilidade

Um fator essencial para otimizar métodos de espera é entender como sua página carrega. Adaptar os tempos de espera ao comportamento real da página é fundamental.

// Set a default timeout for all operations
page.setDefaultTimeout(30000);

// Use efficient wait conditions
const waitForContent = async () => {
  try {
    await page.waitForSelector('.content', {
      visible: true,
      timeout: 5000 // Shorter timeout for specific elements
    });
  } catch (error) {
    console.error('Content load timeout');
    throw error;
  }
};

Para carregamentos completos de página, use 'networkidle0'; para conteúdo dinâmico, use 'networkidle2'. Isso equilibra velocidade e confiabilidade.

"Embora esperar por um período fixo seja uma prática ruim, no mundo real é difícil encontrar uma solução que funcione bem em todos os casos." - Dmytro Krasun [4]

Outra forma de melhorar o desempenho é desativar recursos não essenciais. Porém, para ter ainda mais eficiência, considere soluções com IA.

Lógica de espera com IA

A IA pode levar a otimização das esperas a outro nível ao analisar o comportamento da página e ajustar as condições dinamicamente. Ferramentas como Latenode usam IA para ajustar estratégias de espera.

// AI-enhanced wait logic example
const smartWait = async () => {
  await page.waitForFunction(() => {
    const contentReady = document.querySelector('.content')?.offsetHeight > 0;
    const apiLoaded = window._apiData && Object.keys(window._apiData).length > 0;
    const animationsComplete = !document.querySelector('.loading-animation');

    return contentReady && apiLoaded && animationsComplete;
  }, {
    timeout: 15000,
    polling: 'mutation' // Optimized polling strategy
  });
};

Para situações mais complexas, a espera paralela com limites de tempo otimizados pode fazer uma grande diferença:

// Parallel waiting with timeout optimization
const optimizedLoad = async () => {
  const timeoutPromise = new Promise((_, reject) => 
    setTimeout(() => reject(new Error('Operation timed out')), 10000)
  );

  try {
    await Promise.race([
      Promise.all([
        page.waitForSelector('.content'),
        page.waitForFunction(() => window.dataLoaded === true),
        page.waitForNetworkIdle({
          idleTime: 500,
          timeout: 8000
        })
      ]),
      timeoutPromise
    ]);
  } catch (error) {
    console.error('Loading failed:', error.message);
    throw error;
  }
};

Esses métodos ajudam seus scripts a se adaptar a diferentes condições de rede e tempos de carregamento de página, garantindo velocidade e confiabilidade.

Corrigindo problemas de espera

Para garantir que seus scripts de automação sejam executados sem problemas, é importante resolver erros de limite de tempo após otimizar os métodos de espera.

Gerenciando limites de tempo

Erros de limite de tempo ocorrem quando uma página demora mais para carregar do que o esperado. Por padrão, o Puppeteer define um limite de 30 segundos, o que pode não ser suficiente para conexões de internet mais lentas ou páginas pesadas.

Veja como ajustar as configurações de limite de tempo:

// Set a global timeout for all operations
await page.setDefaultTimeout(60000); // 60 seconds

// Set a specific timeout for navigation
await page.setDefaultNavigationTimeout(60000); // 60 seconds

try {
  await page.waitForSelector('.dynamic-content', {
    visible: true,
    timeout: 10000 // 10 seconds
  });
} catch (error) {
  console.error('Element wait timeout:', error.message);
  // Consider adding a fallback strategy here
}

Para situações mais complexas, experimente limites de tempo incrementais. Essa abordagem tenta novamente a operação com intervalos de tempo crescentes:

const waitWithRetry = async (selector, maxAttempts = 3) => {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      await page.waitForSelector(selector, {
        timeout: 5000 * attempt // Increase timeout with each attempt
      });
      return true;
    } catch (error) {
      if (attempt === maxAttempts) throw error;
      console.warn(`Attempt ${attempt} failed, retrying...`);
    }
  }
};

Encontrando erros de espera

Para depurar erros de espera, use técnicas sistemáticas de monitoramento. Por exemplo:

// Monitor network requests for potential timing issues
await page.setRequestInterception(true);
page.on('request', request => {
  console.log(`${request.method()} ${request.url()}`);
  request.continue();
});

// Check if an element is visible on the page
const elementVisibilityCheck = async (selector) => {
  const isVisible = await page.evaluate((sel) => {
    const element = document.querySelector(sel);
    if (!element) return false;

    const style = window.getComputedStyle(element);
    return style.display !== 'none' && 
           style.visibility !== 'hidden' && 
           style.opacity !== '0';
  }, selector);

  return isVisible;
};

Erros comuns de espera e suas soluções:

Tipo de erroCausaSolução
Limite de navegação excedidoCarregamento pesado da páginaAumente o limite de tempo para 60000ms
Elemento não encontradoConteúdo dinâmicoUse waitForFunction com um observador de mutação
Limite de inatividade de rede excedidoVárias chamadas de APIUse a estratégia networkidle2
Interação falhouEstado do elementoAdicione verificações da capacidade de interação do elemento

Veja um exemplo robusto para lidar com erros de espera com eficiência:

const robustWait = async (page, selector) => {
  try {
    const element = await page.waitForSelector(selector, {
      visible: true,
      timeout: 15000 // 15 seconds
    });

    // Ensure the element is interactive
    await page.waitForFunction(
      (sel) => {
        const el = document.querySelector(sel);
        return el && !el.disabled && el.getBoundingClientRect().height > 0;
      },
      { timeout: 5000 }, // Additional check timeout
      selector
    );

    return element;
  } catch (error) {
    console.error(`Wait error: ${error.message}`);
    throw new Error(`Element ${selector} isn't ready`);
  }
};

Essas estratégias podem ajudar você a solucionar e depurar problemas de limite de tempo com eficiência, garantindo que seus scripts lidem bem com diferentes situações.

Conclusão

Encontrar o equilíbrio certo entre velocidade e estabilidade é fundamental ao usar estratégias de espera no Puppeteer. Escolher o método de espera adequado garante que suas interações web automatizadas funcionem sem problemas e entreguem resultados confiáveis.

Veja uma visão geral rápida das estratégias de espera mais comuns e de quando usá-las:

Estratégia de esperaMelhor caso de usoPrincipal benefício
waitForSelector()Elementos dinâmicos de interfaceConfirma que o elemento está presente antes do uso
waitForNavigation()Transições de páginaMantém seu script sincronizado com as mudanças da página
waitForNetworkIdle()Páginas com uso intenso de APIsConfirma que todas as solicitações de rede foram concluídas
Condições de espera personalizadasSituações complexasOferece controle preciso sobre a temporização

Para conteúdo dinâmico, combinar waitForSelector() com condições de espera personalizadas geralmente funciona melhor do que se limitar aos limites de tempo padrão. Essa abordagem oferece mais controle e reduz as chances de erros.

Usar ferramentas como a Latenode pode simplificar o processo de configurar estratégias de espera eficazes, ajudando você a melhorar a velocidade e a confiabilidade. Além disso, definir limites de tempo com page.setDefaultTimeout() pode ajudar a evitar falhas nos scripts e, ao mesmo tempo, manter sua automação eficiente.

References

FAQ

Frequently Asked Questions

Use-o em aplicações com muitas chamadas de API ou aplicações de página única, nas quais o conteúdo é carregado depois que o DOM está pronto. networkidle0 espera até que não haja conexões por 500 ms; networkidle2 permite até duas conexões ativas em páginas com sockets em segundo plano.

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