Скрейпинг новостных агрегаторов на Python для маркетинговых исследований
Продакшн-ready пайплайн на Python: extract_rules, TLS-профили, эмуляция поведения, networkidle vs load, session_id и масштабирование через async и batch.
Команда InfraProxy
20 февраля 2026 г.
Почему новостные агрегаторы сложно скрейпить в 2026 году
Новостные агрегаторы — ценный источник для маркетинговых исследований, мониторинга репутации и анализа медиа-покрытия. Но в 2026 году извлечение данных с них стало значительно сложнее из-за усиления антибот-защит и динамической загрузки контента.
Rate limiting и CAPTCHA. Агрегаторы ограничивают количество запросов с одного IP. После 20–50 запросов — блокировка или CAPTCHA. Массовый сбор с одного датацентрового IP не работает.
TLS-отпечатки. Python-клиенты (requests, httpx) используют OpenSSL, чей отпечаток отличается от реального Chrome. Системы защиты детектируют это и блокируют запросы.
JavaScript и динамическая подгрузка. Список новостей часто рендерится на клиенте: при скролле подгружаются новые карточки, контент приходит через XHR. Обычный HTTP-запрос возвращает пустой или неполный HTML.
Поведенческий анализ. Продвинутые системы отслеживают паттерны навигации. Запросы без задержек, без скролла, с подозрительно быстрой последовательностью — признаки бота.
Для стабильного сбора нужен API для скрейпинга с резидентными прокси, браузерными TLS-профилями и поведенческой эмуляцией.
Продакшн-ready пайплайн на Python с extract_rules
Структура запроса
import httpx
import os
API_KEY = os.environ.get("SCRAPER_API_KEY")
BASE_URL = "https://api.example.com/v1/scrape"
extract_rules = {
"query": "h1.search-headline, .search-title",
"items": {
"selector": "article.news-item, .search-result-item",
"type": "list",
"fields": {
"title": "h2, .title, a",
"link": "a@href",
"source": ".source-name, .publisher",
"date": "time@datetime, .date",
"snippet": ".snippet, .description"
}
}
}
Селекторы подбираются под структуру конкретного агрегатора. Синтаксис @href и @datetime извлекает атрибуты элементов.
Полный пример скрипта
def scrape_news_aggregator(query: str, country: str = "ru") -> list[dict]:
url = f"https://news.example.com/search?q={query}&gl={country}"
payload = {
"url": url,
"use_js_render": True,
"use_residential": True,
"country": country,
"extract_rules": extract_rules
}
with httpx.Client(timeout=45.0) as client:
resp = client.post(
BASE_URL,
json=payload,
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
)
resp.raise_for_status()
data = resp.json()
return data.get("extract", {}).get("items", [])
Параметр country обеспечивает геотаргетинг — выдача новостей зависит от региона. Для российского рынка используйте country: "ru".
TLS-профили и поведенческая эмуляция
API для скрейпинга по умолчанию использует TLS-отпечаток Chrome и эмулирует поведение реального пользователя:
- Корректные заголовки (User-Agent, Accept-Language, Sec-CH-UA и др.)
- Последовательность загрузки ресурсов, близкая к браузеру
- Задержки между действиями при необходимости
- Прохождение JavaScript-челленджей
Явно указывать эти параметры обычно не нужно. При низком success rate проверьте: включены ли резидентные прокси, достаточен ли таймаут, не блокируется ли запрос по гео.
Подводные камни: networkidle vs load
wait_for: "load" — ожидание события load (DOM загружен, основные ресурсы получены). Быстрее, но на страницах с тяжёлой аналитикой или long polling контент может ещё подгружаться.
wait_for: "networkidle" — ожидание прекращения сетевой активности (нет запросов дольше N мс). Страницы новостных агрегаторов часто делают постоянные фоновые запросы (метрика, обновление счётчиков). В таком случае networkidle может никогда не наступить или ждать десятки секунд.
Рекомендация: используйте явное ожидание конкретного элемента — селектор контейнера со списком новостей (.search-results, .news-list и т.п.). Это надёжнее и быстрее, чем networkidle на «шумных» страницах.
{
"url": "https://news.example.com/search?q=...",
"use_js_render": true,
"js_wait_for": ".news-list, .search-results",
"extract_rules": { ... }
}
extract_rules vs extract_prompt
extract_rules — CSS-селекторы, декларативное описание. Быстро, дёшево. При изменении вёрстки агрегатора селекторы нужно обновлять. Подходят для стабильных источников.
extract_prompt — текстовое описание того, что извлечь, плюс необязательная схема. Модель интерпретирует страницу и возвращает структурированные данные. Устойчивее к изменениям, но дороже и медленнее. Имеет смысл при парсинге множества разнородных агрегаторов или при нестабильной разметке.
Для начала используйте extract_rules; при частых поломках переходите на extract_prompt.
session_id для rate-limited задач
При сборе нескольких страниц одного агрегатора (пагинация, разные запросы) используйте один и тот же session_id. API направляет трафик через один прокси и сохраняет cookies — снижается вероятность CAPTCHA при «естественном» поведении в рамках одной сессии.
payload = {
"url": url,
"session_id": "news-aggregator-session-001",
"use_js_render": True,
"extract_rules": extract_rules
}
Не переиспользуйте один session_id бесконечно: при длительных прогонах лучше ротировать сессии (например, новая сессия каждые 50 запросов).
Масштабирование: async и batch-эндпоинты
Для мониторинга сотен запросов в день используйте асинхронный подход:
import asyncio
import httpx
async def scrape_queries(queries: list[str], max_concurrent: int = 5) -> list[dict]:
results = []
sem = asyncio.Semaphore(max_concurrent)
async def fetch_one(client: httpx.AsyncClient, q: str):
async with sem:
url = f"https://news.example.com/search?q={q}"
payload = {
"url": url,
"use_js_render": True,
"use_residential": True,
"extract_rules": extract_rules
}
resp = await client.post(BASE_URL, json=payload, headers={"Authorization": f"Bearer {API_KEY}"})
resp.raise_for_status()
return {"query": q, "items": resp.json().get("extract", {}).get("items", [])}
async with httpx.AsyncClient(timeout=60.0) as client:
tasks = [fetch_one(client, q) for q in queries]
results = await asyncio.gather(*tasks)
return results
При больших объёмах (десятки URL в одном прогоне) рассмотрите batch-эндпоинт: один запрос с массивом URL, единый ответ с массивом результатов. Меньше накладных расходов, проще оркестрация.
Резюме
- Новостные агрегаторы в 2026 году защищены rate limiting, TLS-проверками и JavaScript-зависимым контентом
- Продакшн-пайплайн: Python + API для скрейпинга + extract_rules + резидентные прокси
- Используйте
js_wait_forна контейнер с контентом вместоnetworkidleна «шумных» страницах - extract_rules — для стабильных источников; extract_prompt — при нестабильной разметке
- session_id снижает вероятность CAPTCHA при многостраничном сборе
- Масштабируйте через async с ограничением concurrency или batch-эндпоинт
Читайте также
InfraProxy Scraper API обеспечивает резидентные прокси и TLS-профили для стабильного сбора данных с новостных агрегаторов в рамках маркетинговых и репутационных исследований. Узнайте условия.
Нужны надёжные прокси для вашего проекта?
InfraProxy предоставляет серверные и резидентные прокси для российского бизнеса. Договор, постоплата, техподдержка.
Читайте также
Настройка прокси для мониторинга цен конкурентов
Пошаговое руководство по настройке прокси для мониторинга цен: ротация IP, geo-targeting, sticky-сессии, обход антибот-защит. Код на Python и bash.
РуководстваКак настроить прокси для RAG-пайплайна
Практическое руководство по настройке прокси для RAG-пайплайна: архитектура, код на Python, sticky-сессии, расписание обходов. InfraProxy, SOCKS5, 100 000+ IP.
РуководстваNo-code веб-скрейпинг: извлечение данных без программирования
Как настроить сбор данных в 2026 году без написания кода: API для скрейпинга, extract_rules, автоматизация через n8n и Make.com, батчевая обработка 100+ страниц.