🎯 Um navegador em nuvem personalizável e anti-detecção alimentado por Chromium desenvolvido internamente, projetado para rastreadores web e agentes de IA. 👉Experimente agora
De volta ao blog

Raspagem de Scroll Infinito: Pare de Adivinhar Quantas Vezes Rolagem fazer

Emily Chen
Emily Chen

Advanced Data Extraction Specialist

04-Aug-2026

TL;DR:

  • Uma página de rolagem infinita envia quase nada em seu HTML. A demonstração usada aqui serve 2.671 bytes contendo zero elementos de citação; cada item chega depois.
  • Um número fixo de rolagens é a falha que todos entregam. Cinco rolagens retornaram 60 de 100 itens — sem erro, sem aviso, uma saída limpa com 40% dos dados faltando.
  • Role até que a contagem de itens pare de crescer. Isso retornou todos os 100.
  • O número de rolagens não é uma propriedade do site. O mesmo loop precisou de 11 ações de rolagem localmente e 3 em um navegador em nuvem, alcançando 100 em ambas as vezes.
  • A página fez 10 chamadas para /api/quotes?page=N. Ler esse endpoint diretamente retorna os mesmos 100 itens e relata has_next, para que o loop saiba quando está terminado.
  • O plano gratuito do Scrapeless cobre a execução em navegador em nuvem neste guia.

A rolagem infinita quebra os scrapers silenciosamente. A solicitação é bem-sucedida, os seletores combinam, o script sai com zero — e o conjunto de dados é curto. Nada na execução diz quanto você perdeu, porque a página nunca prometeu quanto havia.

Este guia mede isso em uma página de demonstração ao vivo. Ele constrói o loop que a maioria dos tutoriais entrega, mostra exatamente o que ele descarta, substitui por um que tem uma condição de parada real e, em seguida, encontra a solicitação que a página estava fazendo o tempo todo.

O que o Servidor Realmente Envia

Busque a página sem um navegador e não há nada para analisar:

python Copy
def served_html() -> tuple[int, int]:
    request = urllib.request.Request(SCROLL_URL, headers={"User-Agent": UA})
    with urllib.request.urlopen(request, timeout=45) as response:
        html = response.read().decode("utf-8", "replace")
    return len(html), html.count('class="quote"')
text Copy
bytes da página de rolagem     : 2671
elementos de citação no html    : 0

2.671 bytes e nenhum item. A marcação é uma casca; o conteúdo é buscado por script após a página ser carregada, tipicamente quando um elemento sentinela próximo ao fundo entra em vista — o mecanismo a especificação do Intersection Observer define. Um seletor CSS não pode falhar de forma mais clara do que isso — ele não combina com nada porque nada está lá ainda.

Instalação

bash Copy
pip install playwright
playwright install chromium

O segundo comando faz o download do binário do navegador; o pacote pip sozinho não irá iniciar. A execução de verificação usou o Playwright 1.59.0.

O Loop Que Todos Entregam

A receita padrão é rolar um número fixo de vezes e então ler a página. page.mouse.wheel() despacha um verdadeiro evento de rolagem do tipo a especificação de Eventos de UI define, que é o que o próprio ouvinte da página está esperando:

python Copy
def scroll_fixed(page, times: int, pause: float) -> int:
    for _ in range(times):
        page.mouse.wheel(0, 20000)
        time.sleep(pause)
    return page.locator("div.quote").count()

Cinco rolagens contra a página ao vivo:

text Copy
citações após 5 rolagens   : 60
segundos decorrido          : 5.1

Sessenta itens. A página tem cem. O script não gerou nada, o seletor funcionou, e a execução parece bem-sucedida por fora — o que torna isso a versão cara do bug. Escolha cinco porque funcionou uma vez, e cada execução posterior herda uma silenciosa falta de 40%.

Aumentar o número também não é uma solução. Isso troca a subcoleta por rolagens desperdiçadas e ainda codifica um palpite sobre um site que pode mudar seu tamanho de lote sempre que desejar.

Role Até Parar de Crescer

A condição que você realmente deseja é observável: continue rolando enquanto a contagem de itens ainda estiver aumentando e pare assim que se mantiver estável.

python Copy
def scroll_until_stable(page, pause: float, no_growth_limit: int = 2) -> tuple[int, int]:
    seen = page.locator("div.quote").count()
    scrolls = 0
    stable = 0
    while stable < no_growth_limit:
        page.mouse.wheel(0, 20000)
        time.sleep(pause)
        scrolls += 1
        count = page.locator("div.quote").count()
        if count == seen:
            stable += 1
        else:
            stable = 0
            seen = count
    return seen, scrolls

no_growth_limit decide quantas evidências você precisa antes de acreditar que a página terminou. Uma leitura plana não é prova — um lote ainda em trânsito parece idêntico ao final da lista. Exigir duas leituras planas consecutivas custa uma rolagem extra e remove essa ambiguidade.

text Copy
citações coletadas          : 100
ações de rolagem realizadas : 11
segundos decorrido          : 11.1
chamadas para a API que a página fez  : 10
primeira URL da API         : https://quotes.toscrape.com/api/quotes?page=1

Todos os 100, e o loop descobriu a contagem em vez de presumir. Note que o número de segundos decorrido é principalmente o intervalo que este loop escolhe esperar — onze rolagens a um segundo cada. É uma propriedade do loop, não do site.

A Contagem de Rolagens Não É uma Propriedade do Site

Executando a função idêntica em um navegador em nuvem em vez do Chromium local:

text Copy
cotações coletadas       : 100
ações de rolagem realizadas : 3

Mesma função, mesma página, mesmos 100 itens — 3 ações de rolagem em vez de 11. A altura da janela de visualização e a rapidez com que cada lote chega decidem quanto um evento de rolagem avança a página, e nenhum dos dois está sob seu controle. As dimensões da janela de visualização contra as quais a rolagem é medida são aquelas que o Módulo de Visualização CSSOM especifica. Qualquer contagem de rolagem codificada é calibrada para o tamanho da janela de uma máquina.

Essa execução usou o Navegador de Scraping Scrapeless, ao qual o Playwright se conecta através do Protocolo DevTools do Chrome. Apenas a linha de conexão muda:

python Copy
    endpoint = (
        "wss://browser.scrapeless.com/api/v2/browser"
        f"?token={os.environ['SCRAPELESS_API_KEY']}&sessionTTL=180&proxyCountry=ANY"
    )
    with sync_playwright() as p:
        browser = p.chromium.connect_over_cdp(endpoint, timeout=90000)
        page = browser.new_page()
        page.goto(SCROLL_URL, wait_until="domcontentloaded")
        cloud_total, cloud_scrolls = scroll_until_stable(page, pause=1.0)

connect_over_cdp substitui chromium.launch() e fala o Protocolo DevTools do Chrome através de um socket em vez de um processo local, então o loop de rolagem, seletores e extração permanecem exatamente como estavam. Mantenha a chave no ambiente como SCRAPELESS_API_KEY; a introdução ao Navegador de Scraping documenta os parâmetros de sessão restantes.

Começar leva um minuto — crie uma conta gratuita no Scrapeless e o plano gratuito cobre essa execução.

Veja o Que a Página Está Solicitando

O loop de rolagem é uma maneira de pedir à página que busque dados. Ouvir as solicitações mostra o que ela busca:

python Copy
        calls: list[str] = []
        context = browser.new_context(user_agent=UA)
        context.on("request", lambda r: calls.append(r.url) if "/api/quotes" in r.url else None)

Dez chamadas, a primeira sendo https://quotes.toscrape.com/api/quotes?page=1. A página está paginando um endpoint JSON e renderizando os resultados; a rolagem é apenas o gatilho.

Esse endpoint pode ser lido diretamente e responde à pergunta que o loop de rolagem teve que inferir:

python Copy
def read_api() -> tuple[int, int]:
    quotes = 0
    page = 1
    while True:
        request = urllib.request.Request(API_URL.format(page=page), headers={"User-Agent": UA})
        with urllib.request.urlopen(request, timeout=45) as response:
            payload = json.loads(response.read().decode())
        quotes += len(payload["quotes"])
        if not payload["has_next"]:
            return quotes, page
        page += 1
text Copy
cotações coletadas       : 100
páginas da API solicitadas : 10
segundos decorridos      : 3.8

Os mesmos 100 itens, com has_next como uma condição de término explícita em vez de "a contagem parou de mudar." A resposta já está estruturada, então nenhum seletor está entre você e os campos — o que também significa nenhum seletor que quebre quando a marcação é reestilizada.

Isso vale a pena verificar antes de escrever qualquer loop de rolagem. Não existe sempre: muitos sites renderizam do lado do servidor ao rolar, assinam suas solicitações ou retornam fragmentos HTML em vez de JSON. Quando existe, é o alvo mais durável, e o navegador ainda é o que mostra que ele está lá. Para as outras formas de paginação — botões de próximo, páginas numeradas, carregar mais — o guia completo de paginação cobre cada tipo.

Execute

bash Copy
export SCRAPELESS_API_KEY="sua-chave-api"
python3 scroll_demo.py

A saída completa da execução de verificação:

text Copy
playwright 1.59.0
--- o que o servidor realmente envia ---
bytes da página de rolagem : 2671
elementos de citação no html : 0
--- número fixo de rolagens ---
cotações após 5 rolagens   : 60
segundos decorridos          : 5.1
--- rolagem até a contagem parar de crescer ---
cotações coletadas         : 100
ações de rolagem realizadas : 11
segundos decorridos          : 11.1
chamadas da API que a página fez  : 10
primeira url da API         : https://quotes.toscrape.com/api/quotes?page=1
--- o mesmo loop no Navegador de Scraping ---
cotações coletadas         : 100
ações de rolagem realizadas : 3
--- lendo a mesma API diretamente ---
cotações coletadas         : 100
páginas da API solicitadas : 10
segundos decorridos          : 3.8

proporção do tempo do navegador/api: 3x

A proporção na última linha compara o relógio do loop do navegador com as leituras diretas. A maior parte do lado do navegador é a pausa deliberada de um segundo entre os rolagens, então leia isso como o custo de verificar uma página por uma condição que nunca é reportada — não como um benchmark do próprio navegador.

Resolução de Problemas

A contagem nunca para de crescer. Algumas páginas fazem loop em seu conteúdo. Limite o loop com uma contagem máxima de rolagem junto com a verificação de estabilidade, e trate atingir esse limite como um sinal para inspecionar a página em vez de como uma execução concluída.

Zero itens mesmo após rolar. O contêiner pode rolar em vez da janela. Role o próprio elemento com page.locator(...).hover() seguido de page.mouse.wheel(...), ou chame scroll_into_view_if_needed() no último item.

A contagem cresce e a página fica em branco. Listas longas são frequentemente virtualizadas, então as linhas são removidas do DOM à medida que saem da viewport. Colete os itens à medida que avança, em vez de lê-los todos no final.

Funciona com cabeça e não sem cabeça. O tamanho da viewport difere entre os dois, o que muda a distância que um evento de roda percorre e se o carregador entra em vista. Defina uma viewport explícita no contexto.

playwright._impl._errors.Error: Executável não existe. O binário do navegador nunca foi baixado. Execute playwright install chromium.

Conclusão

A rolagem infinita transforma "eu consegui tudo?" em uma pergunta que seu scraper deve responder por conta própria, e uma contagem fixa de rolagem responde isso adivinhando. As medições aqui mostram qual é o custo: 60 itens de 100 em cinco rolagens, e uma contagem de rolagem que mudou de 11 para 3 simplesmente ao mudar para um navegador diferente.

Loop em uma condição observada — contagem de itens estável em leituras consecutivas — em vez de um número que você escolheu. E antes de escrever o loop, observe as solicitações da página: quando o conteúdo chega como JSON com uma flag has_next, a página já lhe disse como saber quando você terminou.

Pronto para tentar? Comece com o plano gratuito do Scrapeless e veja a tabela de preços atual para volumes maiores.

FAQ

Q: Quantas vezes devo rolar?

Não escolha um número. As medições acima usaram um loop contra dois navegadores e precisaram de 11 rolagens em um e 3 no outro para os mesmos 100 itens, porque a altura da viewport e o tempo de lote decidem quão longe cada evento de roda vai. Faça loop enquanto a contagem de itens ainda estiver crescendo e pare depois que ela se manter estável duas vezes.

Q: Como sei se a página terminou de carregar tudo?

Duas leituras consecutivas com uma contagem de itens inalterada é o sinal prático, porque uma única leitura plana é indistinguível de um lote ainda em voo. Se a solicitação subjacente da página expõe uma flag como has_next, essa é uma resposta definitiva em vez de uma inferência.

Q: Preciso de um navegador para rolagem infinita?

Frequentemente não. A página de demonstração aqui carrega seu conteúdo de um endpoint JSON que pode ser lido diretamente para todos os 100 itens. O navegador ainda é como você descobre esse endpoint — anexe um ouvinte de solicitações, role uma vez e leia as URLs. Sites que renderizam do lado do servidor ao rolar ou assinam suas solicitações realmente precisam do navegador.

Q: Por que meu scraper retorna menos itens do que a página exibe?

Ou o loop parou cedo, ou a lista é virtualizada e as linhas foram removidas do DOM à medida que saíram de vista. Imprima a contagem de itens após cada rolagem: uma contagem que sobe e depois cai indica virtualização, e uma contagem ainda subindo quando o loop termina indica que o loop parou muito cedo.

Q: wait_until="networkidle" resolve isso?

Não. Ele espera que o carregamento inicial se estabilize, o que acontece antes de qualquer rolagem ter acionado uma busca. Os lotes chegam em resposta aos eventos de rolagem, então a página pode estar ociosa e quase vazia ao mesmo tempo — que é exatamente o estado medido de 2.671 bytes no início.

Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.

Artigos mais populares

Catálogo