Новостные агентства и медиа-платформы используют CAPTCHA для защиты контента от автоматического агрегирования. Мониторам СМИ, PR-компаниям и исследовательским организациям необходимо собирать статьи программным способом. CaptchaAI решает проблемы CAPTCHA в различных источниках новостей.
CAPTCHA на новостных платформах
| Тип источника | КАПЧА | Курок | Содержание |
|---|---|---|---|
| Основные новостные агентства | Cloudflare Turnstile | Обнаружение ботов | Статьи, заголовки |
| Телеграфные службы (AP, Reuters) | reCAPTCHA v2 | Массовый доступ | Последние новости |
| Платные публикации | reCAPTCHA v3 | Попытки доступа | Премиум-статьи |
| Местные новостные сайты | reCAPTCHA v2 | Ограничение скорости | Региональные новости |
| Новостные агрегаторы | страница Cloudflare-защиты в staging | Обнаружение парсинга | Агрегированные фиды |
| Сайты пресс-релизов | Капча изображения | Скачать страницы | PR-контент |
Агрегатор новостей
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")
Мониторинг новостей по ключевым словам
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", "web scraping", "automation"],
sources=sources,
proxy="http://user:pass@residential.proxy.com:5000",
)
matches = monitor.scan()
Поиск неисправностей
| Проблема | Причина | Исправить |
|---|---|---|
| Cloudflare блокирует все запросы | Агрессивное обнаружение ботов | Используйте авторизованный сетевой выход + реалистичный UA |
| Paywall вместо статьи | Контент за подписку | Обнаружение платного доступа, пропуск или обработка |
| CAPTCHA на каждой странице | IP отмечен | Ротация прокси, добавление задержек более 5 секунд |
| Содержимое статьи пусто | JS-рендеринг контента | Используйте Selenium/Puppeteer для SPA-сайтов |
| Повторяющиеся статьи | Одна и та же история из нескольких источников | Дедупликация по сходству названий |
План бюджета домена
- Назначьте каждому источнику бюджет сканирования на основе потребностей в свежести, давления CAPTCHA и ценности потока контента.
- Сначала замедлите работу конфиденциальных доменов, а не применяйте один и тот же шаблон повтора ко всем издателям.
- Отслеживайте решения, промахи и получайте данные о частоте выполнения по каждому домену, чтобы бюджет можно было настроить с помощью реальных сигналов.
Часто задаваемые вопросы
Законно ли агрегирование новостей?
Сбор заголовков и метаданных для исследований или мониторинга является обычной практикой. Воспроизведение статей, защищенных авторским правом, без разрешения запрещено. Используйте фрагменты и дайте ссылку на первоисточник.
Как обращаться с платным контентом?
Обнаружьте платный доступ (ищите классы CSS платного доступа или ограниченную длину контента) и пометьте его. Получайте доступ только к тому контенту, на просмотр которого у вас есть разрешение.
Какой тип прокси подходящий всего подходит для новостных сайтов?
подходящий всего работают ротационные авторизованный сетевой выход. Крупные новостные агентства используют Cloudflare, который агрессивно блокирует IP-адреса центров обработки данных.
Связанные руководства
- Ротация авторизованный сетевой выход
- Исследования социальных сетей
Совокупные новости из любого источника —получите ключ CaptchaAIи автоматизировать сбор контента.