A raspagem de dados médicos é uma tarefa que requer uma abordagem especial na escolha de proxies. Portais médicos, bancos de dados de estudos clínicos e recursos farmacêuticos utilizam sistemas avançados de proteção contra coleta automatizada de dados. Neste artigo, vamos discutir como configurar proxies corretamente para uma raspagem segura de informações médicas, evitar bloqueios e coletar os dados necessários de forma eficiente.
Por que os sites médicos bloqueiam a raspagem
Portais médicos e bancos de dados são especialmente sensíveis à coleta automatizada de informações por várias razões. Em primeiro lugar, muitos deles operam com base comercial e vendem acesso a dados por meio de assinaturas pagas. A raspagem automática pode violar os termos de uso e acordos de licença.
Em segundo lugar, os dados médicos frequentemente contêm informações confidenciais, protegidas por legislação (HIPAA nos EUA, GDPR na Europa). Os proprietários dos recursos são obrigados a controlar o acesso a esses dados e prevenir sua divulgação não autorizada. Portanto, eles utilizam sistemas avançados de proteção:
- Rate limiting — limitação do número de requisições de um único endereço IP em um determinado período (geralmente 10-50 requisições por minuto)
- Fingerprinting — análise das características do navegador, cabeçalhos HTTP, ordem de carregamento de recursos
- CAPTCHA — sistemas como reCAPTCHA v3, que são acionados durante atividades suspeitas
- Bloqueios de IP — bloqueio temporário ou permanente de endereços IP de data centers
- Cloudflare e similares — proteção contra bots no nível do CDN
A terceira razão é a carga nos servidores. Bancos de dados médicos frequentemente contêm milhões de registros, e a raspagem em massa pode criar uma carga significativa na infraestrutura. Portanto, os administradores lutam ativamente contra a coleta automatizada de dados, monitorando padrões de comportamento típicos de bots: intervalos iguais entre requisições, navegação linear pelas páginas, ausência de JavaScript e cookies.
Importante: Antes de iniciar a raspagem de dados médicos, estude os termos de uso do site e a legislação aplicável. Alguns dados podem estar protegidos por direitos autorais ou conter informações pessoais de pacientes. Certifique-se de que sua atividade é legal e não viola os direitos de terceiros.
Qual tipo de proxy escolher para dados médicos
A escolha do tipo de proxy é crítica para o sucesso da raspagem de dados médicos. Diferentes fontes exigem abordagens diferentes. Vamos considerar os principais tipos de proxies e sua aplicabilidade:
| Tipo de proxy | Vantagens | Desvantagens | Quando usar |
|---|---|---|---|
| Proxies de data center | Alta velocidade (100+ Mbps), baixo custo, conexão estável | Fácil detecção, frequentemente bloqueados em sites protegidos | Bancos de dados abertos sem proteção rigorosa (PubMed, OMS) |
| Proxies residenciais | IPs reais de usuários domésticos, baixo risco de bloqueio, passam pelo Cloudflare | Custo mais alto, velocidade variável, podem ser instáveis | Bancos de dados comerciais protegidos (Elsevier, Springer), sites com Cloudflare |
| Proxies móveis | Máxima confiança (IPs de operadoras móveis), praticamente não são bloqueados | Os mais caros, geografia limitada, podem ser mais lentos | Recursos altamente protegidos, quando proxies residenciais não ajudam |
| Proxies ISP | Velocidade de data center + confiança de residenciais, IPs estáticos | Custo médio, disponibilidade limitada | Raspagem a longo prazo de um IP, quando a estabilidade é necessária |
Para a maioria das tarefas de raspagem de dados médicos, recomenda-se o uso de proxies residenciais. Eles oferecem um equilíbrio ideal entre custo e eficácia. Proxies de data center são adequados apenas para fontes abertas sem proteção. Proxies móveis devem ser usados em casos extremos, quando outros tipos não funcionam.
Recomendações para escolha de fontes específicas
- PubMed, PubMed Central — proxies de data center são suficientes, mas com limitação de velocidade de até 3 requisições por segundo
- ClinicalTrials.gov — proxies de data center, há uma API oficial disponível
- Elsevier, Springer, Wiley — proxies residenciais são obrigatórios, utilizam fingerprinting avançado
- DrugBank, RxList — proxies residenciais, proteção ativa contra raspagem
- Bancos de dados FDA, EMA — proxies de data center são adequados, mas com velocidade de raspagem lenta
Principais fontes de dados médicos e sua proteção
Os dados médicos estão distribuídos em várias fontes, cada uma com suas especificidades e níveis de proteção. Compreender essas características ajudará a configurar corretamente a estratégia de raspagem.
Bancos de dados governamentais abertos
PubMed/PubMed Central — o maior banco de dados de publicações médicas, contém mais de 35 milhões de registros. A Biblioteca Nacional de Medicina dos EUA (NLM) fornece uma API oficial E-utilities, que é o método preferido de acesso aos dados. A raspagem direta da interface web é possível, mas limitada a 3 requisições por segundo de um único IP. Exceder o limite resulta em bloqueio temporário de 24 horas.
ClinicalTrials.gov — banco de dados de estudos clínicos, contém informações sobre mais de 400.000 estudos em 220 países. Também fornece uma API para acesso programático. A interface web é protegida por rate limiting — máximo de 100 requisições em 5 minutos de um único IP. Utiliza proteção básica contra bots, mas sem Cloudflare.
Banco de Dados de Medicamentos da FDA — banco de dados de medicamentos aprovados pela FDA. Acesso aberto através da interface web e API openFDA. Limitações: 240 requisições por minuto para usuários anônimos, 1000 requisições por minuto com chave de API. Bloqueios são raros, mas podem ocorrer com raspagem agressiva.
Editoras científicas comerciais
Elsevier (ScienceDirect) — uma das maiores editoras de literatura científica. Utiliza proteção em múltiplos níveis: Cloudflare, fingerprinting do navegador, análise do comportamento do usuário. Detecta padrões de download automático: acesso sequencial a artigos, ausência de JavaScript, User-Agent não típico. Ao detectar raspagem, bloqueia o IP no nível da conta e pode bloquear toda a instituição. É obrigatório o uso de proxies residenciais com rotação e emulação completa do navegador.
Springer Nature — proteção semelhante, além disso, monitora a velocidade de rolagem das páginas e movimentos do mouse. Utiliza machine learning para detecção de bots. Recomenda-se raspar não mais que 10-15 artigos por hora de um único IP, com delays aleatórios entre as requisições.
Wiley Online Library — proteção menos agressiva, mas ainda assim requer o uso de proxies. Permite cerca de 50 requisições por hora de um único IP sem bloqueio. Utiliza cookies de sessão para monitorar a atividade.
Bancos de dados farmacêuticos
DrugBank — banco de dados abrangente de medicamentos. A versão gratuita é limitada à interface web, a versão comercial fornece API e exportações de dados. A versão web é protegida por Cloudflare e rate limiting — máximo de 20 requisições por minuto. Detecta automação pela ausência de cookies e JavaScript.
RxList, Drugs.com — diretórios populares de medicamentos para consumidores. Utilizam Cloudflare e lutam ativamente contra a raspagem. Bloqueiam IPs de data centers praticamente instantaneamente. Requerem proxies residenciais e velocidade de raspagem lenta (5-10 páginas por minuto).
Configuração de rotação de IP para raspagem a longo prazo
A rotação correta de endereços IP é um fator chave para o sucesso da raspagem de dados médicos. Existem duas abordagens principais: rotação no nível das requisições e rotação por tempo.
Rotação no nível das requisições
Nesta abordagem, cada requisição é enviada através de um novo endereço IP. Isso minimiza o risco de bloqueio, mas pode causar problemas com sites que monitoram sessões através de cookies. É adequado para raspagem de listas e diretórios, onde não é necessário manter o estado da sessão.
A maioria dos provedores de proxies residenciais oferece rotação automática através de um endpoint especial. Por exemplo, ao usar um endpoint de proxy rotativo, cada nova conexão TCP recebe um novo IP. Isso funciona automaticamente com bibliotecas como requests em Python, pois por padrão uma nova conexão é criada para cada requisição.
Rotação por tempo (sticky sessions)
Sticky sessions permitem usar um endereço IP por um período específico (geralmente 5-30 minutos), após o qual ocorre a troca automática. Isso é útil para sites que exigem autenticação ou monitoram o estado da sessão através de cookies. Você pode raspar várias páginas de um único IP, imitando o comportamento de um usuário real, e então o IP muda automaticamente.
Para sites médicos, recomenda-se usar sticky sessions com duração de 10-15 minutos. Nesse tempo, é possível raspar 10-20 páginas (dependendo dos delays), após o qual o IP muda e você inicia uma "nova sessão". Isso parece natural e reduz o risco de detecção.
Tamanho do pool de endereços IP
Para raspagem a longo prazo, o tamanho do pool de endereços IP disponíveis é importante. Se você usar o mesmo conjunto de 100 IPs durante uma semana, o site pode notar o padrão e bloquear todos esses endereços. Proxies residenciais geralmente fornecem acesso a milhões de IPs, o que praticamente elimina a reutilização do mesmo endereço.
Ao usar proxies de data center, recomenda-se ter um pool de pelo menos 500-1000 IPs para raspagem de volume médio (10.000-50.000 páginas por mês). Para raspagem em larga escala (centenas de milhares de páginas), é melhor usar proxies residenciais com seus enormes pools de IPs.
Dicas de rotação para diferentes fontes:
- PubMed — rotação não é obrigatória, basta 1 IP respeitando o rate limit
- Editoras comerciais — sticky sessions de 10-15 minutos, novo IP a cada 15-20 páginas
- Bancos de dados farmacêuticos — rotação a cada requisição ou sticky sessions de 5 minutos
- Sites com Cloudflare — sticky sessions são obrigatórias, rotação no nível das requisições não funciona
Exemplos de código em Python para raspagem com proxies
Vamos considerar exemplos práticos de configuração de proxies para raspagem de dados médicos usando bibliotecas populares do Python. Começaremos com um exemplo básico e gradualmente o tornaremos mais complexo.
Configuração básica com a biblioteca requests
import requests
from time import sleep
import random
# Configuração do proxy (substitua pelos seus dados)
PROXY_HOST = "proxy.example.com"
PROXY_PORT = "8080"
PROXY_USER = "username"
PROXY_PASS = "password"
proxies = {
'http': f'http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}',
'https': f'http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}'
}
# Cabeçalhos para simular um navegador real
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'DNT': '1',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1'
}
# Exemplo de requisição ao PubMed
url = "https://pubmed.ncbi.nlm.nih.gov/?term=diabetes"
try:
response = requests.get(url, proxies=proxies, headers=headers, timeout=30)
print(f"Código de status: {response.status_code}")
print(f"Comprimento do conteúdo: {len(response.content)}")
# Adicionando delay entre requisições (obrigatório para PubMed)
sleep(random.uniform(1.0, 3.0))
except requests.exceptions.RequestException as e:
print(f"Erro: {e}")
Configuração avançada com rotação e lógica de retry
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
from time import sleep
import random
class ProxyRotator:
def __init__(self, proxy_list):
"""
proxy_list: lista de dicionários com proxies
[{'http': 'http://user:pass@host:port', 'https': '...'}, ...]
"""
self.proxy_list = proxy_list
self.current_index = 0
def get_next_proxy(self):
"""Obter o próximo proxy da lista"""
proxy = self.proxy_list[self.current_index]
self.current_index = (self.current_index + 1) % len(self.proxy_list)
return proxy
def create_session_with_retries():
"""Criar uma sessão com repetições automáticas em caso de erros"""
session = requests.Session()
# Configuração de repetições automáticas
retry_strategy = Retry(
total=3, # máximo de 3 tentativas
backoff_factor=1, # delay entre tentativas: 1, 2, 4 segundos
status_forcelist=[429, 500, 502, 503, 504], # códigos para repetição
allowed_methods=["GET", "POST"]
)
adapter = HTTPAdapter(max_retries=retry_strategy)
session.mount("http://", adapter)
session.mount("https://", adapter)
return session
def scrape_with_rotation(urls, proxy_rotator):
"""Raspagem de uma lista de URLs com rotação de proxies"""
session = create_session_with_retries()
results = []
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
}
for url in urls:
# Obter um novo proxy para cada requisição
proxy = proxy_rotator.get_next_proxy()
try:
response = session.get(
url,
proxies=proxy,
headers=headers,
timeout=30
)
if response.status_code == 200:
results.append({
'url': url,
'status': 'success',
'content_length': len(response.content)
})
print(f"✓ Sucesso: {url}")
else:
results.append({
'url': url,
'status': 'failed',
'error': f"Código de status: {response.status_code}"
})
print(f"✗ Falhou: {url} (Status: {response.status_code})")
except requests.exceptions.RequestException as e:
results.append({
'url': url,
'status': 'error',
'error': str(e)
})
print(f"✗ Erro: {url} ({e})")
# Delay aleatório entre requisições (importante!)
sleep(random.uniform(2.0, 5.0))
return results
# Exemplo de uso
proxy_list = [
{
'http': 'http://user1:pass1@proxy1.example.com:8080',
'https': 'http://user1:pass1@proxy1.example.com:8080'
},
{
'http': 'http://user2:pass2@proxy2.example.com:8080',
'https': 'http://user2:pass2@proxy2.example.com:8080'
}
]
rotator = ProxyRotator(proxy_list)
urls_to_scrape = [
"https://pubmed.ncbi.nlm.nih.gov/?term=diabetes",
"https://pubmed.ncbi.nlm.nih.gov/?term=cancer",
"https://pubmed.ncbi.nlm.nih.gov/?term=covid"
]
results = scrape_with_rotation(urls_to_scrape, rotator)
Uso do Selenium para sites com JavaScript
Muitos sites médicos modernos utilizam JavaScript para carregar conteúdo. Nesses casos, é necessário um navegador headless:
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
def create_proxy_driver(proxy_host, proxy_port, proxy_user, proxy_pass):
"""Criar Chrome WebDriver com proxy"""
chrome_options = Options()
# Modo headless (sem GUI)
chrome_options.add_argument('--headless')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
# Configuração do proxy
chrome_options.add_argument(f'--proxy-server=http://{proxy_host}:{proxy_port}')
# Desativar automação (importante para contornar detecção)
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
# User-Agent
chrome_options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36')
driver = webdriver.Chrome(options=chrome_options)
# Para proxies com autenticação, é necessário usar uma extensão
# ou configurar através de capabilities (opção mais complexa)
return driver
def scrape_with_selenium(url, driver):
"""Raspagem de página com espera pelo carregamento do JavaScript"""
driver.get(url)
# Espera pelo carregamento do elemento (por exemplo, resultados da pesquisa)
try:
wait = WebDriverWait(driver, 10)
results = wait.until(
EC.presence_of_element_located((By.CLASS_NAME, "results-article"))
)
# Extração de dados
articles = driver.find_elements(By.CLASS_NAME, "results-article")
data = []
for article in articles:
try:
title = article.find_element(By.CLASS_NAME, "docsum-title").text
authors = article.find_element(By.CLASS_NAME, "docsum-authors").text
data.append({
'title': title,
'authors': authors
})
except:
continue
return data
except Exception as e:
print(f"Erro ao esperar pelos elementos: {e}")
return []
# Exemplo de uso
proxy_host = "proxy.example.com"
proxy_port = "8080"
proxy_user = "username"
proxy_pass = "password"
driver = create_proxy_driver(proxy_host, proxy_port, proxy_user, proxy_pass)
try:
url = "https://pubmed.ncbi.nlm.nih.gov/?term=diabetes"
results = scrape_with_selenium(url, driver)
for result in results:
print(f"Título: {result['title']}")
print(f"Autores: {result['authors']}\n")
finally:
driver.quit()
Controle de velocidade de requisições e contorno de rate limiting
Rate limiting é uma das principais proteções dos sites médicos contra raspagem. A configuração correta da velocidade das requisições é crítica para raspagem a longo prazo sem bloqueios.
Definindo uma velocidade segura
O primeiro passo é determinar os limites de um site específico. Isso pode ser feito experimentalmente, aumentando gradualmente a velocidade das requisições até que apareçam erros 429 (Too Many Requests) ou bloqueios. Para a maioria dos sites médicos, os valores seguros são:
- PubMed — máximo de 3 requisições por segundo (recomendação oficial)
- ClinicalTrials.gov — 20 requisições por minuto é seguro, até 100 em 5 minutos é aceitável
- Editoras comerciais — 10-15 requisições por hora de um único IP
- Bancos de dados farmacêuticos — 5-10 requisições por minuto
Implementação de rate limiter em Python
import time
from collections import deque
class RateLimiter:
def __init__(self, max_calls, period):
"""
max_calls: número máximo de chamadas
period: período de tempo em segundos
Por exemplo: RateLimiter(3, 1) = 3 requisições por segundo
"""
self.max_calls = max_calls
self.period = period
self.calls = deque()
def __call__(self, func):
"""Decorador para limitar a velocidade de chamada da função"""
def wrapper(*args, **kwargs):
now = time.time()
# Remove chamadas antigas fora do período
while self.calls and self.calls[0] < now - self.period:
self.calls.popleft()
# Se atingirmos o limite, aguardamos
if len(self.calls) >= self.max_calls:
sleep_time = self.period - (now - self.calls[0])
if sleep_time > 0:
print(f"Limite de taxa atingido, aguardando {sleep_time:.2f}s")
time.sleep(sleep_time)
# Limpa após a espera
self.calls.clear()
# Registra o tempo da chamada
self.calls.append(time.time())
# Executa a função
return func(*args, **kwargs)
return wrapper
# Exemplo de uso
@RateLimiter(max_calls=3, period=1) # 3 requisições por segundo
def fetch_pubmed_page(url):
response = requests.get(url, headers=headers, proxies=proxies)
return response
# Agora a função automaticamente respeita o rate limit
for i in range(10):
result = fetch_pubmed_page(f"https://pubmed.ncbi.nlm.nih.gov/?term=test&page={i}")
print(f"Página {i} obtida")
Rate limiting adaptativo
Uma abordagem mais avançada é a alteração adaptativa da velocidade com base nas respostas do servidor. Se recebermos erros 429 ou 503, diminuímos automaticamente a velocidade:
import time
import random
class AdaptiveRateLimiter:
def __init__(self, initial_delay=1.0, max_delay=60.0):
self.current_delay = initial_delay
self.initial_delay = initial_delay
self.max_delay = max_delay
self.success_count = 0
def wait(self):
"""Aguarda antes da próxima requisição"""
# Adiciona aleatoriedade para naturalidade
actual_delay = self.current_delay * random.uniform(0.8, 1.2)
time.sleep(actual_delay)
def on_success(self):
"""Chamado em caso de requisição bem-sucedida"""
self.success_count += 1
# Após 10 requisições bem-sucedidas, aceleramos um pouco
if self.success_count >= 10:
self.current_delay = max(
self.initial_delay,
self.current_delay * 0.9
)
self.success_count = 0
def on_rate_limit(self):
"""Chamado ao receber 429 ou erros semelhantes"""
# Dobra o delay, mas não mais que o máximo
self.current_delay = min(
self.current_delay * 2,
self.max_delay
)
self.success_count = 0
print(f"Limite de taxa atingido! Aumentando o delay para {self.current_delay:.2f}s")
def on_error(self):
"""Chamado em caso de outros erros"""
# Aumenta um pouco o delay
self.current_delay = min(
self.current_delay * 1.5,
self.max_delay
)
self.success_count = 0
# Exemplo de uso
limiter = AdaptiveRateLimiter(initial_delay=2.0, max_delay=30.0)
for url in urls_to_scrape:
limiter.wait()
try:
response = requests.get(url, proxies=proxies, headers=headers)
if response.status_code == 200:
limiter.on_success()
# Processar dados
elif response.status_code == 429:
limiter.on_rate_limit()
# Repetir mais tarde
else:
limiter.on_error()
except requests.exceptions.RequestException:
limiter.on_error()
Cabeçalhos corretos e User-Agent para sites médicos
Sites médicos analisam cabeçalhos HTTP para detectar bots. Cabeçalhos incorretos ou ausentes são uma causa comum de bloqueios, mesmo ao usar proxies de qualidade.
Cabeçalhos obrigatórios
O conjunto mínimo de cabeçalhos que deve estar presente em cada requisição:
headers = {
# User-Agent — deve ser um navegador atual
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
# Accept — tipos de conteúdo que o navegador aceita
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8',
# Accept-Language — idioma do usuário
'Accept-Language': 'en-US,en;q=0.9',
# Accept-Encoding — suporte a compressão
'Accept-Encoding': 'gzip, deflate, br',
# Connection — manter a conexão
'Connection': 'keep-alive',
# Upgrade-Insecure-Requests — transição automática para HTTPS
'Upgrade-Insecure-Requests': '1',
# DNT — Do Not Track (opcional, mas adiciona realismo)
'DNT': '1',
# Sec-Fetch-* cabeçalhos (importantes para navegadores modernos)
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
# Cache-Control
'Cache-Control': 'max-age=0'
}
Rotação de User-Agent
Usar o mesmo User-Agent pode ser suspeito. Recomenda-se a rotação entre vários navegadores atuais:
import random
USER_AGENTS = [
# Chrome no Windows
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
# Chrome no Mac
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
# Firefox no Windows
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0',
# Firefox no Mac
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:121.0) Gecko/20100101 Firefox/121.0',
# Safari no Mac
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15',
# Edge no Windows
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0'
]
def get_random_headers():
"""Obter cabeçalhos com User-Agent aleatório"""
return {
'User-Agent': random.choice(USER_AGENTS),
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'DNT': '1'
}
# Uso
for url in urls:
headers = get_random_headers()
response = requests.get(url, headers=headers, proxies=proxies)
Referer e Origin para formulários
Ao trabalhar com formulários de pesquisa ou enviar requisições POST, sempre adicione os cabeçalhos Referer e Origin:
# Para requisições POST ao formulário de pesquisa
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Content-Type': 'application/x-www-form-urlencoded',
'Origin': 'https://example.com',
'Referer': 'https://example.com/search',
'Connection': 'keep-alive'
}
# Requisição POST com dados do formulário
data = {
'query': 'diabetes',
'page': '1'
}
response = requests.post(
'https://example.com/search',
headers=headers,
data=data,
proxies=proxies
)
Problemas comuns e suas soluções
Ao raspar dados médicos, surgem problemas específicos. Vamos considerar os mais comuns e como resolvê-los.
Problema: Cloudflare bloqueia todas as requisições
Sintomas: Você recebe uma página com o texto "Checking your browser" ou um erro 403 Forbidden mencionando Cloudflare.
Solução:
- Use proxies residenciais em vez de data centers — Cloudflare bloqueia IPs de data centers por padrão
- Mude para Selenium ou Puppeteer — navegadores headless passam melhor pelas verificações do Cloudflare
- Use a biblioteca cloudscraper para Python — ela contorna automaticamente a proteção básica do Cloudflare
- Ative cookies e JavaScript — Cloudflare verifica a presença deles
- Adicione fingerprinting TLS — use curl_cffi para simular um navegador real no nível TLS
Problema: Recebo erro 429 Too Many Requests
Sintomas: Após várias requisições bem-sucedidas, o servidor começa a retornar 429.
Solução:
- Aumente o delay entre as requisições — comece com 3-5 segundos
- Ative a rotação de IP — cada requisição através de um novo IP remove o rate limiting
- Verifique o cabeçalho Retry-After na resposta 429 — ele indica quantos segundos você deve esperar
- Use um delay exponencial em repetições — 1s, 2s, 4s, 8s etc.
Problema: Proxies funcionam lentamente ou caem frequentemente
Sintomas: Erros de timeout, carregamento muito lento das páginas, desconexões.
Solução:
- Aumente o timeout nas requisições para 30-60 segundos — proxies residenciais podem ser mais lentos
- Use proxies geograficamente próximos — se você está raspando um site europeu, use IPs europeus
- Verifique a qualidade do provedor de proxies — proxies baratos são frequentemente instáveis
- Adicione lógica de retry — repita automaticamente a requisição em caso de erro de conexão
- Use connection pooling — reutilize conexões TCP através de requests.Session()
Problema: O site exige autenticação ou assinatura
Sintomas: Acesso aos textos completos dos artigos é restrito, requer login.
Solução:
- Use acesso institucional — muitas universidades e hospitais têm assinaturas
- Verifique a disponibilidade de versões Open Access — muitos artigos estão disponíveis gratuitamente através de repositórios
- Use API em vez de raspagem — algumas editoras oferecem API para pesquisadores
- Raspe apenas metadados (títulos, autores, resumos) — eles geralmente estão disponíveis gratuitamente
Problema: Conteúdo JavaScript não carrega
Sintomas: Não há dados necessários no HTML, apenas spinners de carregamento ou contêineres vazios.
Solução:
- Mude para Selenium/Puppeteer — eles executam JavaScript
- Encontre o endpoint da API — abra o DevTools no navegador, aba Network, e encontre requisições XHR com dados
- Use requests-html — biblioteca com suporte a JavaScript