← Voltar ao blog

Lógica de Retry do Parser: como requisições repetidas consomem até 40% do tráfego e como corrigir isso

Solicitações repetidas podem consumir até 40% do tráfego do proxy. Mostramos como calcular as perdas reais e reduzi-las por meio de um backoff adequado, um disjuntor e uma rotação inteligente de proxies.

📅27 de setembro de 2026

Se a conta do proxy está crescendo mais rápido do que o volume de dados coletados, o problema quase sempre está na lógica de retry. O parser silenciosamente repete solicitações malsucedidas várias vezes, consumindo tráfego em timeouts e captchas, enquanto o desenvolvedor nem vê esses gastos nos logs. Vamos analisar como calcular as perdas reais e reduzi-las sem perder a qualidade dos dados.

Por que a lógica de retry consome tráfego

A maioria dos parsers é escrita com uma lógica de retry ingênua: se a solicitação falhar — repetir, e assim por 3-5 vezes. O problema é que cada solicitação repetida não é apenas uma nova solicitação HTTP, mas um ciclo completo: handshake TCP, negociação TLS, carregamento da página inteira (mesmo que apenas um bloco de dados seja necessário), e às vezes até o recarregamento de imagens ou arquivos JS, se o parser usar um navegador headless em vez de um simples cliente HTTP.

As repetições são especialmente caras ao trabalhar com proxies residenciais, onde o tráfego é tarifado por volume, e não pelo número de solicitações. Uma solicitação malsucedida para uma página de produto da Wildberries com imagens e scripts pode custar 300-500 KB. Se o parser faz 3 repetições em caso de timeout, você paga pela mesma solicitação malsucedida quatro vezes seguidas — e isso sem garantia de que a quarta tentativa será bem-sucedida.

A segunda razão é o retry em erros que não podem ser corrigidos com uma repetição. Se o site retornou 403 devido à detecção de um bot, a solicitação repetida com a mesma impressão digital e a mesma sessão de cookies quase certamente receberá a mesma resposta. O parser consome tráfego em tentativas que matematicamente não podem terminar em sucesso, a menos que o endereço IP ou a impressão digital do navegador mudem.

Quanto tráfego realmente vai para repetições

Para entender a magnitude do problema, vamos pegar um exemplo simples. O parser coleta cartões de produtos de um marketplace, o tamanho médio da resposta é de 250 KB (HTML + JSON API + parte da estática). Em um funcionamento estável sem bloqueios, a proporção de solicitações malsucedidas se mantém em torno de 5-8%. Mas em uma coleta agressiva através de proxies baratos de data center, esse número pode subir para 25-35%, porque o provedor-alvo rapidamente reconhece o padrão e começa a retornar captchas ou banimentos temporários por IP.

Vamos calcular com números. Suponha que precisamos coletar 100.000 cartões de produtos:

Proporção de solicitações malsucedidas Repetições por solicitação (em média) Tráfego total Excesso de consumo
5% 0.15 28.75 GB +15%
15% 0.45 36.25 GB +45%
30% 0.90 47.5 GB +90%

Como pode ser visto, com uma proporção de falhas de 30% e uma estratégia de retry de "repetir até 3 vezes", o tráfego real quase dobra em relação ao mínimo teórico de 25 GB. Esses mais de 20 GB extras são perdas diretas no orçamento de proxies, que podem ser reduzidas se a lógica de repetições for revista.

Erros comuns na lógica de retry dos parsers

Antes de corrigir a lógica de retry, é importante reconhecer os antipadrões típicos que ocorrem em 90% dos parsers feitos à mão:

  • Retry sem analisar o código de erro. A repetição é acionada para qualquer situação anômala — 403, 429, 500, timeout, desconexão — embora a estratégia de tratamento para elas deva ser diferente.
  • Atraso fixo entre repetições. Por exemplo, 2 segundos entre tentativas, independentemente de ser a primeira ou a quinta tentativa — isso é ou muito agressivo para o site, ou muito lento para grandes volumes.
  • Repetição com o mesmo IP e a mesma sessão. Se o site bloqueou a solicitação por impressão digital, repetir com parâmetros idênticos não muda o resultado, mas consome tráfego.
  • Sem limite superior de tentativas. Alguns parsers ficam presos em URLs "mortas" e fazem dezenas de repetições antes de desistir.
  • Falta de distinção entre erros temporários e permanentes. 404 (página não existe) e 503 (servidor temporariamente indisponível) requerem lógicas diferentes — mas muitas vezes são tratados da mesma forma.

Backoff exponencial com código em Python

Uma solução simples, mas eficaz, é o atraso exponencial com jitter (variação aleatória), que reduz o número de repetições sem sentido e distribui a carga ao longo do tempo. Em vez de uma pausa fixa entre tentativas, o atraso cresce exponencialmente, dando ao site tempo para "esfriar" após um bloqueio, e ao próprio parser — não gastar tráfego em solicitações que quase certamente falharão.

import time
import random
import requests

def fetch_with_backoff(url, proxies, max_retries=4, base_delay=1.0):
    retryable_codes = {429, 500, 502, 503, 504}
    non_retryable_codes = {404, 410}

    for attempt in range(max_retries + 1):
        try:
            response = requests.get(url, proxies=proxies, timeout=10)

            if response.status_code == 200:
                return response

            if response.status_code in non_retryable_codes:
                # não faz sentido repetir — a página fisicamente não existe
                return None

            if response.status_code not in retryable_codes:
                return None

        except (requests.exceptions.Timeout,
                requests.exceptions.ConnectionError):
            pass  # erro de rede temporário — pode repetir

        if attempt == max_retries:
            return None

        # atraso exponencial com jitter
        delay = base_delay * (2 ** attempt) + random.uniform(0, 1)
        time.sleep(delay)

    return None

A ideia chave deste código é a separação de erros em três categorias: aqueles que não podem ser corrigidos com repetição (404, 410), aqueles que podem ser repetidos com atraso (429, 500-504, timeouts), e tudo o mais que é imediatamente considerado uma falha sem gastos em tentativas adicionais. Essa separação por si só reduz o tráfego desnecessário em 20-30% em comparação com a ingênua "repetir tudo".

Dica: adicione o cabeçalho Retry-After ao tratamento — muitos sites indicam quantos segundos esperar antes de repetir. Ignorar esse cabeçalho é uma causa comum de banimentos e tráfego desnecessário.

Circuit breaker: quando parar

O backoff exponencial ajuda no nível de uma solicitação, mas não protege contra a situação em que todo o domínio ou um proxy específico está temporariamente indisponível para centenas de URLs consecutivas. Aqui, é necessário um padrão de circuit breaker — um "disjuntor" que monitora a proporção de erros durante um período recente e interrompe temporariamente as tentativas se essa proporção exceder um limite, em vez de continuar batendo em uma porta fechada.

class CircuitBreaker:
    def __init__(self, failure_threshold=0.5, window_size=50, cooldown=60):
        self.failure_threshold = failure_threshold
        self.window_size = window_size
        self.cooldown = cooldown
        self.results = []
        self.open_until = 0

    def is_open(self):
        return time.time() < self.open_until

    def record(self, success: bool):
        self.results.append(success)
        if len(self.results) > self.window_size:
            self.results.pop(0)

        if len(self.results) == self.window_size:
            failure_rate = 1 - sum(self.results) / self.window_size
            if failure_rate > self.failure_threshold:
                self.open_until = time.time() + self.cooldown
                self.results.clear()

A lógica é simples: se mais da metade das últimas 50 solicitações falharam, o parser suspende as tentativas para esse domínio ou proxy por 60 segundos. Durante esse tempo, é possível mudar o IP, reduzir a velocidade das solicitações ou alternar para outro pool de proxies. Isso é especialmente importante ao trabalhar com sites-alvo que temporariamente banem um intervalo de IPs após exceder a frequência de solicitações — continuar batendo em uma porta fechada significa apenas queimar tráfego em vão.

Rotação inteligente de proxies em repetições

Uma das medidas mais eficazes contra retries desnecessários é não repetir a solicitação com o mesmo IP que já recebeu uma recusa. A lógica é simples: se o erro está relacionado ao bloqueio por IP (403, 429, redirecionamento para captcha), mudar o proxy antes da repetição aumenta drasticamente a chance de sucesso e reduz o número de tentativas.

Para a coleta de dados de marketplaces como Wildberries, Ozon ou Avito, uma boa combinação é: solicitações normais vão através de proxies de data center — eles são mais rápidos e baratos, e assim que o detector de bloqueio dispara várias vezes seguidas, o parser muda para proxies residenciais, que raramente caem em filtros de sistemas anti-bots. Essa abordagem híbrida reduz o consumo total de tráfego, pois os caros IPs residenciais são usados apenas onde realmente necessário, e não para todas as solicitações consecutivas.

Tipo de erro Estratégia de repetição Mudança de IP necessária?
Timeout de conexão Backoff, 1-2 repetições Não
403 / captcha Rotação imediata Sim, obrigatoriamente
429 (limite de taxa) Backoff com Retry-After Desejável
500-503 Backoff, 2-3 repetições Não
404 / 410 Sem repetições —

Para parsers que emulam tráfego móvel (por exemplo, coleta de dados de versões móveis de aplicativos de marketplaces ou redes sociais), faz sentido usar proxies móveis — eles raramente levantam suspeitas nos sistemas de proteção, justamente porque os operadores de telecomunicações atribuem os mesmos IPs a milhares de usuários reais simultaneamente, e o bloqueio pontual se torna inviável para o site-alvo.

Monitoramento de métricas de retry

Sem métricas, a otimização da lógica de retry se torna um palpite. O conjunto mínimo de indicadores que deve ser registrado em cada solicitação:

  • Taxa de retry — proporção de solicitações que exigiram pelo menos uma repetição.
  • Sucesso após retry — qual porcentagem de repetições acabou sendo bem-sucedida (se esse indicador for baixo, as repetições estão apenas queimando tráfego).
  • Tráfego para resultado bem-sucedido — volume total de dados transferidos, dividido pelo número de registros coletados com sucesso. Essa é a métrica chave de eficiência.
  • Distribuição de erros por códigos — ajuda a entender onde ocorre a principal perda de tráfego: timeouts, 403, 429 ou algo mais.
  • Taxa de retry por proxies específicos — se um IP tem uma taxa de retry de 80%, enquanto os outros têm 10%, o problema é local e pode ser resolvido mudando apenas aquele nó, e não toda a lógica.

Mesmo uma tabela simples no Google Sheets ou um log em CSV com essas cinco métricas, atualizada a cada hora, fornece dados suficientes para identificar anomalias e ajustar a estratégia a tempo — por exemplo, reduzindo a frequência de solicitações para uma seção específica do site ou aumentando a proporção de IPs residenciais no pool.

Checklist de otimização de tráfego em retry

  1. Separe os códigos de erro em retryable e non-retryable — não repita 404/410.
  2. Implemente um backoff exponencial com jitter em vez de um atraso fixo.
  3. Respeite o cabeçalho Retry-After, se o site o enviar.
  4. Mude o IP antes da repetição em caso de 403 e suspeita de detecção de bot.
  5. Estabeleça um limite rígido no número de tentativas (geralmente 3-4 é suficiente).
  6. Implemente um circuit breaker para domínios e nós de proxy com alta taxa de falhas.
  7. Registre a taxa de retry e o tráfego para resultados bem-sucedidos — sem métricas, a otimização é impossível.
  8. Separe o pool de proxies: data centers baratos para áreas estáveis, IPs residenciais ou móveis para áreas problemáticas.

Conclusão

A lógica de retry não é um pequeno detalhe do parser, mas um dos principais fatores que afetam o custo da coleta de dados. Uma estratégia ingênua de "repetir tudo" pode aumentar o tráfego real em 40-90% em comparação com o mínimo teórico, enquanto a maior parte das repetições termina na mesma falha que a primeira tentativa. A separação de erros por tipos, o backoff exponencial, o circuit breaker e a rotação inteligente de IPs permitem reduzir essas perdas drasticamente sem diminuir a completude dos dados coletados.

Se o seu parser trabalha com sites que detectam bots de forma agressiva — marketplaces, redes sociais, plataformas de publicidade — vale a pena combinar vários tipos de proxies dependendo da tarefa. Para operações básicas, proxies de data center são adequados, enquanto onde é necessária a máxima resistência a bloqueios, proxies residenciais com IPs reais de usuários comuns são a melhor escolha. Essa abordagem híbrida, combinada com uma lógica de retry bem estruturada, resulta em uma redução significativa do consumo de tráfego mantendo o mesmo volume de dados coletados.