Um coletor em Python começa com cinco linhas que funcionam na primeira tentativa. O problema aparece depois: na semana três, quando o site muda uma div; no mês dois, quando começam a chegar respostas de erro; no mês seis, quando alguém pergunta de onde veio aquele dado.
Este artigo é sobre a segunda parte. Se você ainda está decidindo se precisa coletar, comece por o que é web scraping, que trata da base legal e de quando a fonte oficial resolve sem raspar nada.
Antes da primeira linha: existe API?
Continua sendo a pergunta que mais economiza trabalho. Um endpoint oficial devolve dado estruturado, não quebra quando o site muda de visual, consome uma fração do tráfego e não gera discussão sobre termos de uso.
No Brasil, boa parte do que as pessoas tentam raspar já está aberta: compras públicas, processos judiciais, cadastro de empresas, tabela de veículos. Vale conferir a fonte antes de escrever o coletor.
O par que resolve a maioria dos casos
Para página que já vem pronta no HTML, requests busca e BeautifulSoup extrai:
import requests
from bs4 import BeautifulSoup
sessao = requests.Session()
sessao.headers.update({
"User-Agent": "MeuColetor/1.0 ([email protected])",
"Accept-Language": "pt-BR,pt;q=0.9",
})
resposta = sessao.get("https://exemplo.com.br/produtos", timeout=20)
resposta.raise_for_status()
pagina = BeautifulSoup(resposta.text, "html.parser")
for item in pagina.select(".produto"):
nome = item.select_one(".nome")
preco = item.select_one(".preco")
print(nome.get_text(strip=True), preco.get_text(strip=True))
Três detalhes desse trecho são o que separa script de coletor:
Session() em vez de requests.get solto. Reaproveita a conexão, o que reduz tempo e consumo. Em coleta grande, a diferença é grande.
User-Agent que identifica quem é. Um agente honesto, com forma de contato, é o que permite ao administrador do site falar com você em vez de simplesmente bloquear. É a diferença entre ser um parceiro chato e um problema anônimo.
timeout sempre. Sem ele, uma requisição pendurada trava o coletor por tempo indeterminado.
Selecione pelo que é estável
O motivo número um de coletor quebrado é seletor frágil. Classes geradas automaticamente mudam a cada publicação do site.
Prefira, nesta ordem: atributos de dado (data-produto-id), identificadores semânticos, estrutura de tabela, e só por último classe de estilo. E, muito antes disso, procure um bloco <script type="application/ld+json"> na página: muitos sites de comércio publicam ali o preço e o nome do produto em JSON limpo, prontos para ler sem nenhum seletor.
Devagar é mais rápido
A tentação é rodar tudo em paralelo. O resultado costuma ser bloqueio no primeiro dia.
import time, random
for url in urls:
resposta = sessao.get(url, timeout=20)
if resposta.status_code == 429:
espera = int(resposta.headers.get("Retry-After", 60))
time.sleep(espera)
continue
processa(resposta)
time.sleep(random.uniform(1.5, 4.0))
O código acima faz duas coisas que quase todo coletor amador não faz: lê o Retry-After em vez de tentar de novo na hora, e varia o intervalo em vez de bater no relógio. O significado exato do 429 e a estratégia de espera crescente estão em erro 429 Too Many Requests.
Antes de qualquer coisa, leia o robots.txt do site e os termos de uso. Não é formalidade: é o que define se a sua coleta é aceitável.
Quando o navegador é necessário (e por que evitar)
Se o conteúdo só aparece depois do JavaScript rodar, requests não serve e entra um navegador automatizado. Antes de aceitar esse custo, abra as ferramentas de desenvolvedor na aba de rede e procure a chamada que a própria página faz: em muitos casos existe um endpoint JSON por trás, que devolve o mesmo dado sem renderizar nada.
Quando o navegador é inevitável, o custo muda de ordem: cada página carrega imagens, fontes e scripts, e o consumo de tráfego explode. A conta está em consumo de GB no scraping, e vale bloquear imagem e fonte no carregamento.
Onde o proxy entra de verdade
No começo, não entra. Coleta pequena, de páginas públicas, sai pela sua própria conexão sem problema nenhum.
Ele passa a fazer sentido em três situações:
- O servidor conta por endereço. O volume cresceu e o limite passou a ser atingido. A saída é distribuir, sempre junto com a redução de frequência — nunca no lugar dela.
- O conteúdo muda por origem. Preço, catálogo e resultado de busca variam conforme o país ou a cidade de quem pede. Aí um endereço brasileiro não é otimização: é requisito de correção do dado.
- A coleta precisa manter login. Caso em que trocar de endereço no meio da sessão é justamente o que dispara alerta, e o correto é um endereço fixo.
A configuração em requests, httpx e aiohttp, com usuário e senha e o tratamento de senha com caractere especial, está no guia de proxy em Python. A escolha entre endereço fixo, por sessão ou por requisição está em proxy rotativo.
Vale medir antes de contratar: rode cem itens, meça o tráfego consumido e projete. A página de proxy para web scraping mostra os produtos por cenário.
O checklist do coletor que dura
- Conferiu se existe API ou dado aberto na fonte.
- Leu
robots.txte os termos de uso. - Definiu base legal se houver dado pessoal.
- Usa
Session,timeoute User-Agent identificável. - Seleciona por atributo estável, não por classe de estilo.
- Respeita
Retry-Aftere varia o intervalo. - Registra a taxa de erro e avisa quando ela sobe.
- Só então avalia proxy, pelo tipo de limite que apareceu.
Coletor montado nessa ordem custa menos em tráfego, quebra menos quando o site muda e não coloca ninguém em situação difícil.