Uma plataforma de baixo código que combina a simplicidade sem código com o poder do código completo 🚀
Comece gratuitamente
Condições de espera personalizadas com waitForFunction no Puppeteer
21 de março de 2025
.
9
min ler

Condições de espera personalizadas com waitForFunction no Puppeteer

Jorge Miloradovitch
Pesquisador, redator e entrevistador de casos de uso
Índice

Quer o seu Marionetista scripts para lidar melhor com sites dinâmicos? Aqui está a chave: waitForFunction permite que você defina regras de espera personalizadas para garantir que sua automação funcione perfeitamente com as mudanças de conteúdo.

Por que usar waitForFunction?

  • Tempo de controle: Aguarde até que condições específicas sejam atendidas (por exemplo, elementos são carregados, texto é alterado).
  • Lidar com conteúdo dinâmico: Perfeito para sites modernos e dinâmicos.
  • Evitar erros: Evite atrasos desnecessários ou interações prematuras.

Como Funciona:

  • Escreva condições JavaScript que retornem true quando estiver pronto.
  • Use opções como frequência de pesquisa (raf, mutation, ou milissegundos) e tempos limite para melhor desempenho.
  • Combine verificações DOM com respostas de API para cenários avançados.

Exemplo:

await page.waitForFunction(
  () => document.querySelector('.status').textContent === 'Ready'
);

Principais Recursos:

  • Monitore a visibilidade dos elementos, o conteúdo do texto ou as propriedades personalizadas.
  • Combine várias condições para fluxos de trabalho complexos.
  • Lide com tempos limite e erros com elegância.

Dica: Usar waitForFunction para substituir desatualizado sleep chamadas e melhorar a eficiência.

Visão geral rápida:

Característica O que faz
Modos de votação Verifica as condições via 'raf', 'mutation', ou intervalos personalizados
Condições Personalizadas Aguarde estados DOM específicos ou respostas de API
Gerenciamento de tempo limite Definir tempos limite globais ou específicos da operação

Este método garante que seus scripts sejam confiáveis, eficientes e prontos para qualquer desafio de conteúdo dinâmico.

Como esperar / dormir por N segundos em titereiro?

titereiro

Noções básicas de waitForFunction

A waitForFunction O método no Puppeteer permite que você configure condições personalizadas para seus scripts esperarem antes de prosseguir. Veja como você pode usá-lo efetivamente.

Como escrever funções básicas de espera

Aqui está uma maneira simples de criar uma função de espera:

// Wait until the input element has a specific value
await page.waitForFunction(
  'document.getElementById("loginUsername").value === "hello"'
);

// Using an arrow function for a condition
await page.waitForFunction(
  () => document.querySelector('.status').textContent === 'Ready'
);

A chave aqui é que sua função precisa retornar um valor verdadeiro antes que o roteiro possa prosseguir.

Agora, vamos ver como configurá-lo para melhor desempenho.

Configurando Parâmetros de Função

Você pode fazer ajustes finos waitForFunction passando um objeto de opções. Os principais parâmetros incluem:

Parâmetro Descrição Valores comuns
Votação Com que frequência a condição é verificada 'raf', 'mutação' ou milissegundos
tempo limite Tempo máximo de espera Padrão: 30,000 ms (30 segundos)

Modos de votação:

  1. RequestAnimationFrame ('raf')
    Melhor para monitorar mudanças de estilo, pois verifica as condições durante cada quadro de animação.
  2. Observador de mutação ('mutação')
    Útil para rastrear alterações na estrutura do DOM. Ele dispara verificações sempre que o DOM é atualizado.
  3. Intervalo personalizado (milissegundos)
    Por exemplo, isso verifica a condição a cada segundo:
    await page.waitForFunction(
      () => document.readyState === 'complete',
      { polling: 1000, timeout: 5000 }
    );
    

Escolha o modo de votação com base em suas necessidades:

  • Use 'raf' para animações ou atualizações de estilo.
  • Optar por 'mutation' para alterações relacionadas ao DOM.
  • Defina um intervalo personalizado (milissegundos) para casos de uso mais amplos.

Criando regras de espera personalizadas

Verificando o status de exibição do elemento

Para confirmar que um elemento está visível, você pode verificar sua presença e dimensões:

await page.waitForFunction(() => {
    const element = document.querySelector('.tv-lightweight-charts');
    return element && element.offsetHeight > 0 && element.offsetWidth > 0;
});

Isso garante que o elemento exista e tenha dimensões visíveis na página. É especialmente útil para conteúdo dinâmico que leva tempo para carregar corretamente.

Testando propriedades de texto e elementos

Além das verificações visuais, você pode monitorar o conteúdo do texto ou propriedades específicas dos elementos:

// Wait for specific text content
await page.waitForFunction(
    selector => {
        const element = document.querySelector(selector);
        return element && element.textContent.includes('Ready');
    },
    {},
    '.status-message'
);

Para verificações de propriedade mais detalhadas, passe argumentos adicionais:

const expectedValue = 'completed';
const selector = '.status';

await page.waitForFunction(
    (sel, val) => {
        const element = document.querySelector(sel);
        return element && element.getAttribute('data-state') === val;
    },
    {},
    selector,
    expectedValue
);

Combinando várias regras de espera

Depois de testar condições individuais, você pode combiná-las para cenários mais complexos. Por exemplo:

await page.waitForFunction(() => {
    // Check multiple elements and conditions
    const button = document.querySelector('.donate-button');
    const searchBox = document.querySelector('.search-button');

    return button && 
           searchBox && 
           button.offsetHeight > 0 && 
           searchBox.offsetHeight > 0 &&
           !button.disabled;
});

Para manipular vários elementos com condições independentes, use Promise combinações:

Padrão de espera Caso de uso Implementação
Todos os elementos Aguarde vários elementos necessários Promise.all()
Qualquer elemento Continue quando o primeiro elemento aparecer Promise.race()
Lógica personalizada Lidar com verificações condicionais complexas Funções de espera combinadas

Para operações assíncronas, você pode criar condições de espera avançadas:

await page.waitForFunction(
    async () => {
        const response = await fetch('/api/status');
        const data = await response.json();
        return data.isReady && document.querySelector('.content').offsetHeight > 0;
    },
    { polling: 'mutation' }
);

Este método combina Validação de resposta da API com Verificações de elementos DOM, garantindo que tanto os dados quanto o conteúdo visual estejam prontos.

sbb-itb-23997f1

Métodos avançados waitForFunction

Escrevendo condições complexas em JavaScript

Para aplicações web mais dinâmicas, você pode usar esperarPorFunção para criar condições JavaScript detalhadas. Aqui está um exemplo:

await page.waitForFunction(
    (threshold) => {
        const chart = document.querySelector('.tv-lightweight-charts');
        const dataPoints = chart?.querySelectorAll('.data-point');

        return chart && 
               dataPoints?.length > threshold && 
               Array.from(dataPoints).every(point => 
                   point.getBoundingClientRect().height > 0 &&
                   !point.classList.contains('loading')
               );
    },
    { polling: 'mutation' },
    5
);

Este script garante:

  • O contêiner do gráfico existe.
  • Um número mínimo de pontos de dados está presente.
  • Todos os pontos de dados são visíveis.
  • Nenhum dos pontos está em estado de carregamento.

Você também pode combinar verificações assíncronas com avaliações DOM para cenários mais complexos:

await page.waitForFunction(
    async () => {
        // Check if the container is ready
        const container = document.querySelector('.dynamic-content');
        if (!container || container.offsetHeight === 0) return false;

        // Validate API response
        try {
            const response = await fetch('/api/status');
            const data = await response.json();
            return data.isReady && container.children.length > 0;
        } catch {
            return false;
        }
    },
    { 
        polling: 'raf',
        timeout: 30000
    }
);

Essa abordagem combina verificações de DOM com uma chamada de API para garantir que a interface do usuário e o backend estejam sincronizados.

Lidando com tempos limite e erros

O gerenciamento de tempo limite é crucial ao trabalhar com esperarPorFunção. Aqui está um exemplo de como lidar com timeouts de forma eficaz:

try {
    await page.setDefaultTimeout(60000); // Set a global timeout of 60 seconds

    await page.waitForFunction(
        () => {
            const element = document.querySelector('.dynamic-element');
            return element?.complete === true;
        },
        {
            timeout: 45000, // Specific timeout for this operation
            polling: 'mutation'
        }
    );
} catch (error) {
    if (error.name === 'TimeoutError') {
        console.error('Element state check timed out:', error.message);
        await page.reload(); // Reload page as a fallback
    }
    throw error;
}

Aqui está uma rápida visão geral das estratégias de tempo limite:

Estratégia de tempo limite Caso de uso Configuração
Tempo limite padrão Operações gerais page.setDefaultTimeout()
Tempo limite de navegação Carregamento de página page.setDefaultNavigationTimeout()
Específico da operação Verificações detalhadas Use o timeout opção no método
Espera infinita Atrasos conhecidos timeout: 0

Para melhorar o tratamento de erros:

  • Ajuste as configurações de tempo limite com base na complexidade de cada operação.
  • Use try-catch blocos para se recuperarem graciosamente de erros.
  • Monitore a atividade da rede para identificar gargalos.
  • Implemente ações de fallback, como recarregar a página, quando ocorrerem tempos limite.
  • Verifique novamente os seletores para evitar atrasos desnecessários.

Essas práticas ajudarão a garantir que seus scripts sejam confiáveis ​​e eficientes.

Fazendo waitForFunction rodar mais rápido

Dicas de velocidade e recursos

Para obter esperarPorFunção para executar com mais eficiência, concentre-se em estratégias de espera inteligentes e gerenciamento adequado de recursos. Use ferramentas de desenvolvedor de navegador para medir tempos de carregamento e definir timeouts precisos.

// Optimize waiting with a networkidle strategy
await page.goto('https://example.com', {
    waitUntil: 'networkidle2',
    timeout: 30000
});

// Combine checks in a single evaluate call
await page.evaluate(() => {
    const element = document.querySelector('.dynamic-content');
    const isVisible = element?.offsetHeight > 0;
    const hasData = element?.children.length > 0;
    return isVisible && hasData;
});

Para reduzir o uso de recursos:

  • Bloqueie recursos desnecessários, como imagens ou fontes.
  • Use waitForSelector or waitForFunction em vez de desatualizado waitForTimeout.
  • Combine várias verificações em uma única evaluate chamada para reduzir a comunicação do navegador para o Node.
Estratégia Impacto no desempenho Melhor caso de uso
networkidle2 Moderado Navegação de página
waitForSelector pomposidade Verificações de elementos individuais
waitForFunction Variável Condições complexas
Combinado evaluate Fastest Verificações de múltiplos elementos

Esses métodos podem ajudar a resolver gargalos comuns, que são abordados na próxima seção.

Resolvendo problemas comuns

Problemas de desempenho geralmente decorrem de padrões de espera ineficientes. Veja como lidar com eles:

Problemas com o seletor
Seletores excessivamente rígidos podem causar falhas. Simplifique-os para melhor confiabilidade:

// Avoid rigid selectors like this
await page.waitForSelector('div.container > div:nth-child(2) > span.text-red');

// Use a more flexible approach
await page.waitForFunction(
    () => document.querySelector('.text-red')?.offsetParent !== null
);

Gestão de Recursos
Gerencie recursos e evite atrasos desnecessários:

try {
    await page.waitForFunction(
        () => document.readyState === 'complete' &&
              performance.now() > 1000
    );
} catch (error) {
    console.error('Page load timeout:', error.message);
}

"Puppeteer tem uma arquitetura orientada a eventos, o que remove muitas falhas potenciais. Não há necessidade de maldade sleep[undefined] chamadas em scripts de marionetista." - leia-me do Puppeteer

Sempre envolva métodos de espera em try...catch blocos para lidar com erros graciosamente e fornecer opções de fallback. Essa abordagem garante que seus scripts permaneçam robustos e confiáveis.

Usos comuns para regras de espera personalizadas

Carregando produtos da loja online

Garantir que os produtos sejam carregados corretamente é essencial para coletar dados precisos. Use uma regra de espera personalizada para pausar a execução até que os itens do produto sejam totalmente carregados:

await page.waitForFunction(() => {
    const products = document.querySelectorAll('.product-card');
    return products.length > 0 && all images and prices fully load;
});

Para maior precisão, você pode usar esta abordagem:

await page.waitForFunction(() => {
    const productDetails = document.querySelector('.product-details');
    return productDetails && 
           productDetails.offsetHeight > 0 && 
           productDetails.querySelector('.inventory-status') !== null;
}, {timeout: 30000});

Isso garante que seu script aguarde o carregamento de todos os elementos necessários, melhorando a confiabilidade da coleta de dados em cenários de comércio eletrônico.

Carregando conteúdo em aplicativos da Web modernos

Aplicativos web dinâmicos geralmente exigem condições de espera específicas para lidar com o carregamento de conteúdo. Por exemplo, você pode esperar que um elemento específico se torne totalmente visível:

await page.waitForFunction(() => {
    const element = document.querySelector('.tv-lightweight-charts');
    return element && element.offsetHeight > 0 && element.offsetWidth > 0;
});

Se várias seções precisarem ser carregadas, combine condições como esta:

await page.waitForFunction(() => {
    const contentLoaded = document.querySelector('.content').children.length > 0;
    const dataUpdated = document.body.textContent.includes('Last updated:');
    return contentLoaded && dataUpdated;
}, {polling: 1000});

Este método ajuda a garantir que seus scripts de automação interajam perfeitamente com conteúdo dinâmico.

Detecção de mensagem de erro de formulário

A detecção de erros de formulário usa uma lógica semelhante às verificações de visibilidade de elementos. Veja como você pode monitorar mensagens de erro:

await page.waitForFunction(() => {
    const errorContainer = document.querySelector('.error-messages');
    const hasErrors = errorContainer?.children.length > 0;
    const isVisible = errorContainer?.offsetParent !== null;
    return hasErrors && isVisible;
});

Você também pode rastrear vários estados de validação de formulários usando condições de espera específicas:

Tipo de validação Condição de espera Caso de uso
Erros de campo Verifique a presença de uma classe de erro Validação de campo individual
Erros em todo o formulário Monitore o contêiner de erro Status geral do formulário
Mensagens de sucesso Fique atento às exibições de confirmação Conclusão da submissão
Estados de carregamento Estado do botão de envio da trilha Indicação de processamento

Conclusão

Principais lições

A waitForFunction O método no Puppeteer avalia as condições do JavaScript até que elas retornem true, oferecendo controle preciso sobre interações dinâmicas de páginas.

Aqui estão alguns dos principais benefícios do uso waitForFunction:

  • Avaliação Flexível: Lida com funções assíncronas para monitorar estados de páginas complexos.
  • Integração de Contexto: Permite a passagem direta de argumentos do Node.js para o contexto do navegador.
  • Lógica personalizada: Permite automação personalizada com base em condições específicas da página.

Essa abordagem é particularmente útil em casos em que métodos de espera padrão não são suficientes. Por exemplo, em aplicativos avançados de página única, vários elementos podem ser carregados simultaneamente, ou estados JavaScript específicos podem precisar ser confirmados antes de prosseguir.

Marionetista e Nó latente Em ação

Nó latente

Latenode aproveita waitForFunction para aprimorar a automação do fluxo de trabalho. Ao integrar esse método, a Latenode criou um nó de monitoramento personalizado que verifica os status do site e captura capturas de tela quando certas condições não são satisfeitas.

Aqui está um exemplo de como o Latenode usa waitForFunction para garantir que os elementos críticos sejam totalmente renderizados antes de prosseguir:

await page.waitForFunction(() => {
    const element = document.querySelector('.tv-lightweight-charts');
    return element && element.offsetHeight > 0 && element.offsetWidth > 0;
});

Este snippet aguarda um elemento com a classe .tv-lightweight-charts para não apenas aparecer no DOM, mas também ser totalmente renderizado.

Para melhores resultados ao usar o Latenode com o Puppeteer:

  • Defina valores de tempo limite apropriados usando page.setDefaultTimeout().
  • Use try-catch blocos para tratamento robusto de erros.
  • Acompanhe os tempos de execução para ajustar suas condições de espera.

Posts Relacionados do Blog

Blogs relacionados

Caso de uso

Apoiado por