Os meios de comunicação e plataformas de mídia usam CAPTCHAs para proteger o conteúdo da agregação automatizada. Monitores de mídia, empresas de relações públicas e organizações de pesquisa precisam coletar artigos de forma programática. CaptchaAI lida com desafios CAPTCHA em fontes de notícias.
CAPTCHAs em plataformas de notícias
| Tipo de fonte | CAPTCHA | Gatilho | Conteúdo |
|---|---|---|---|
| Principais meios de comunicação | Cloudflare Turnstile | Detecção de bots | Artigos, manchetes |
| Serviços de notícias (AP, Reuters) | reCAPTCHA v2 | Acesso em massa | Notícias de última hora |
| Publicações com acesso pago | reCAPTCHA v3 | Tentativas de acesso | Artigos premium |
| Sites de notícias locais | reCAPTCHA v2 | Limitação de taxa | Notícias regionais |
| Agregadores de notícias | Cloudflare Turnstile em staging | Detecção de raspagem | Feeds agregados |
| Sites de comunicados de imprensa | Imagem CAPTCHA | Baixar páginas | Conteúdo de relações públicas |
Agregador de notícias
import requests
import time
import re
from bs4 import BeautifulSoup
from datetime import datetime
import json
CAPTCHAAI_KEY = "YOUR_API_KEY"
CAPTCHAAI_URL = "https://ocr.captchaai.com"
def solve_captcha(method, sitekey, pageurl, **kwargs):
data = {
"key": CAPTCHAAI_KEY, "method": method,
"googlekey": sitekey, "pageurl": pageurl, "json": 1,
}
data.update(kwargs)
resp = requests.post(f"{CAPTCHAAI_URL}/in.php", data=data)
task_id = resp.json()["request"]
for _ in range(60):
time.sleep(5)
result = requests.get(f"{CAPTCHAAI_URL}/res.php", params={
"key": CAPTCHAAI_KEY, "action": "get",
"id": task_id, "json": 1,
})
r = result.json()
if r["request"] != "CAPCHA_NOT_READY":
return r["request"]
raise TimeoutError("Timeout")
class NewsAggregator:
def __init__(self, proxy=None):
self.session = requests.Session()
if proxy:
self.session.proxies = {"http": proxy, "https": proxy}
self.session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 Chrome/126.0.0.0 Safari/537.36",
"Accept-Language": "en-US,en;q=0.9",
})
def collect_headlines(self, source_url, section=None):
"""Collect headlines from a news source."""
url = f"{source_url}/{section}" if section else source_url
resp = self.session.get(url, timeout=30)
if self._has_captcha(resp.text):
resp = self._solve_and_retry(resp.text, url)
soup = BeautifulSoup(resp.text, "html.parser")
articles = []
for item in soup.select("article, .story, .headline-item, h2 a, h3 a"):
link = item if item.name == "a" else item.select_one("a")
if link:
articles.append({
"title": link.get_text(strip=True),
"url": self._abs_url(source_url, link.get("href", "")),
"source": source_url,
"collected_at": datetime.now().isoformat(),
})
return articles
def get_article(self, article_url):
"""Fetch full article content."""
resp = self.session.get(article_url, timeout=30)
if self._has_captcha(resp.text):
resp = self._solve_and_retry(resp.text, article_url)
soup = BeautifulSoup(resp.text, "html.parser")
# Remove unwanted elements
for tag in soup.select("script, style, nav, footer, .ad, .sidebar"):
tag.decompose()
content_el = soup.select_one(
"article, .article-body, .story-body, .entry-content"
)
return {
"url": article_url,
"title": self._text(soup, "h1, .article-title"),
"author": self._text(soup, ".author, .byline, [rel='author']"),
"date": self._text(soup, "time, .publish-date, .article-date"),
"content": content_el.get_text(separator="\n", strip=True) if content_el else "",
"word_count": len(content_el.get_text().split()) if content_el else 0,
}
def aggregate_sources(self, sources, max_articles_per=20):
"""Aggregate headlines across multiple sources."""
all_articles = []
for source in sources:
try:
articles = self.collect_headlines(source["url"], source.get("section"))
all_articles.extend(articles[:max_articles_per])
print(f"{source['name']}: {len(articles)} headlines")
except Exception as e:
print(f"{source['name']}: Error - {e}")
time.sleep(3)
return all_articles
def _has_captcha(self, html):
return any(tag in html.lower() for tag in [
'data-sitekey', 'g-recaptcha', 'cf-turnstile',
])
def _solve_and_retry(self, html, url):
match = re.search(r'data-sitekey="([^"]+)"', html)
if not match:
return self.session.get(url)
sitekey = match.group(1)
if 'cf-turnstile' in html:
token = solve_captcha("turnstile", sitekey, url)
return self.session.post(url, data={"cf-turnstile-response": token})
token = solve_captcha("userrecaptcha", sitekey, url)
return self.session.post(url, data={"g-recaptcha-response": token})
def _text(self, soup, selector):
el = soup.select_one(selector)
return el.get_text(strip=True) if el else ""
def _abs_url(self, base, href):
if href.startswith("http"):
return href
return base.rstrip("/") + "/" + href.lstrip("/")
# Usage
aggregator = NewsAggregator(
proxy="http://user:pass@residential.proxy.com:5000"
)
sources = [
{"name": "Tech News A", "url": "https://technews-a.example.com", "section": "latest"},
{"name": "Business B", "url": "https://business-b.example.com", "section": "tech"},
{"name": "Industry C", "url": "https://industry-c.example.com"},
]
headlines = aggregator.aggregate_sources(sources)
print(f"Total: {len(headlines)} headlines collected")
Monitoramento de notícias baseado em palavras-chave
class NewsMonitor:
def __init__(self, keywords, sources, proxy=None):
self.keywords = [kw.lower() for kw in keywords]
self.aggregator = NewsAggregator(proxy=proxy)
self.sources = sources
self.seen_urls = set()
def scan(self):
"""Scan for articles matching keywords."""
headlines = self.aggregator.aggregate_sources(self.sources)
matches = []
for article in headlines:
if article["url"] in self.seen_urls:
continue
title_lower = article["title"].lower()
matched_kws = [kw for kw in self.keywords if kw in title_lower]
if matched_kws:
article["matched_keywords"] = matched_kws
matches.append(article)
self.seen_urls.add(article["url"])
return matches
def continuous_monitor(self, interval_min=30):
"""Run continuous monitoring with alerts."""
while True:
matches = self.scan()
if matches:
print(f"\n=== {len(matches)} new matches found ===")
for m in matches:
print(f" [{', '.join(m['matched_keywords'])}] {m['title']}")
print(f" {m['url']}")
else:
print(f"No new matches at {datetime.now().strftime('%H:%M')}")
time.sleep(interval_min * 60)
# Monitor for specific topics
monitor = NewsMonitor(
keywords=["captcha", "bot detection", "coleta autorizada", "automation"],
sources=sources,
proxy="http://user:pass@residential.proxy.com:5000",
)
matches = monitor.scan()
Plano de orçamento de domínio
- Atribua a cada fonte um orçamento de rastreamento com base nas necessidades de atualização, na pressão do CAPTCHA e no valor do fluxo de conteúdo.
- Diminua a velocidade dos domínios confidenciais primeiro, em vez de aplicar o mesmo padrão de novas tentativas em todos os editores.
- Rastreie soluções, erros e cadência de busca por domínio para que o orçamento possa ser ajustado com sinais reais.
Solução de problemas
| Problema | Causa | Correção |
|---|---|---|
| Cloudflare bloqueando todas as solicitações | Detecção agressiva de bots | Use egress de rede autorizado + UA realista |
| Paywall em vez de artigo | Conteúdo por trás da assinatura | Detectar acesso pago, pular ou manipular |
| CAPTCHA em todas as páginas | IP sinalizado | Gire o proxy, adicione atrasos de mais de 5 segundos |
| Conteúdo do artigo vazio | Conteúdo renderizado em JS | Use Selenium/Puppeteer para sites de SPA |
| Artigos duplicados | A mesma história de várias fontes | Desduplicar por similaridade de título |
Perguntas frequentes
A agregação de notícias é legal?
A recolha de manchetes e metadados para investigação ou monitorização é uma prática comum. Reproduzir artigos completos protegidos por direitos autorais sem permissão não é. Use trechos e crie um link para a fonte original.
Como lidar com conteúdo com acesso pago?
Detecte o acesso pago (procure classes CSS do acesso pago ou comprimento de conteúdo limitado) e sinalize-o. Acesse apenas o conteúdo que você está autorizado a visualizar.
Qual tipo de proxy funciona mais adequado para sites de notícias?
Os proxies residenciais rotativos funcionam mais adequado. Os principais meios de comunicação usam o Cloudflare, que bloqueia agressivamente IPs de datacenters.
Guias Relacionados
- Proxies residenciais rotativos
- Pesquisa de mídia social
- Notícias agregadas de qualquer fonte -obtenha sua chave CaptchaAIe automatizar a coleta de conteúdo.*