Веб-скрейпер на Python: создание инструмента с обходом антибот-защит
Как построить надёжный Python-скрейпер, обходящий Cloudflare и антибот-системы: от httpx и Pydantic до stealth-режима, CAPTCHA и масштабирования до 10 000 страниц.
Команда InfraProxy
21 февраля 2026 г.
Почему связка requests + BeautifulSoup больше не работает в 2026 году
Классический стек — requests для HTTP и BeautifulSoup для парсинга HTML — десятилетиями использовался для сбора данных. Сегодня он перестаёт быть достаточным для большинства коммерчески значимых источников.
Проблема 1: TLS-отпечаток. Python-библиотека requests использует стандартную реализацию SSL/TLS из OpenSSL. Её JA3/JA4-отпечаток отличается от отпечатка реального Chrome. Антибот-системы (Cloudflare, DataDome, PerimeterX) проверяют отпечаток; несоответствие User-Agent и TLS ведёт к блокировке.
Проблема 2: JavaScript. Большая часть современного контента рендерится в браузере. Запрос через requests возвращает пустой или неполный HTML — данные подгружаются через XHR/Fetch после выполнения скриптов.
Проблема 3: Поведенческий анализ. Продвинутые системы отслеживают движения мыши, скорость скролла, паттерны навигации. Простой HTTP-клиент не генерирует такое поведение.
Проблема 4: CAPTCHA. При малейшем подозрении пользователю показывается CAPTCHA. requests не может ни пройти JavaScript-челлендж, ни решить визуальную задачу.
Для легального сбора данных с защищённых сайтов нужен другой подход: либо полноценный headless-браузер, либо специализированный API для скрейпинга, который решает эти задачи за вас.
Архитектура: Scraper API как слой обхода антиботов
Scraper API — это облачный сервис, который принимает URL и возвращает готовый HTML (или структурированные данные). Внутри он использует:
- Резидентные прокси с ротацией
- Реальные браузерные TLS-отпечатки
- JavaScript-рендеринг (Playwright/Puppeteer)
- Автоматическое решение CAPTCHA
- Повторные попытки при блокировках
Вы пишете простой клиент на Python: отправляете запросы к API, получаете данные, парсите их локально. Вся логика обхода защит инкапсулирована в сервисе.
Преимущества такого подхода:
- Быстрый старт без настройки инфраструктуры
- Предсказуемая стоимость (плата за успешный запрос)
- Актуальные обновления обхода при изменении защит
- Возможность сосредоточиться на бизнес-логике (извлечение, хранение, аналитика)
Настройка Python-окружения
Для работы с Scraper API достаточно стандартных библиотек HTTP и валидации данных:
# requirements.txt
httpx>=0.27.0
pydantic>=2.0.0
httpx — современная асинхронная HTTP-библиотека с поддержкой HTTP/2, совместимая с requests по интерфейсу. pydantic — для описания схем извлекаемых данных и валидации ответов.
import httpx
from pydantic import BaseModel
class ScraperClient:
def __init__(self, api_key: str, base_url: str = "https://api.example.com/v1"):
self.api_key = api_key
self.base_url = base_url
async def scrape(self, url: str, render_js: bool = True) -> str:
async with httpx.AsyncClient(timeout=60.0) as client:
resp = await client.post(
f"{self.base_url}/scrape",
json={"url": url, "render_js": render_js},
headers={"Authorization": f"Bearer {self.api_key}"}
)
resp.raise_for_status()
return resp.json()["html"]
Базовая интеграция не требует сложной логики — достаточно корректно формировать запросы и обрабатывать ответы.
Обход Cloudflare в stealth-режиме
Cloudflare блокирует запросы по нескольким признакам: IP из дата-центров, несовпадение TLS и User-Agent, отсутствие выполнения JavaScript-челленджей. Scraper API по умолчанию использует stealth-настройки:
- Резидентные прокси — IP домашних провайдеров с высокой репутацией
- Полноценный браузерный стек — TLS-отпечаток Chrome, корректные заголовки
- Выполнение челленджей — headless Chrome проходит проверки так же, как обычный браузер
- Задержки и ротация — запросы распределяются по разным IP с паузами между ними
При необходимости можно явно указать параметры:
country— геотаргетинг (например, для локальных вариантов сайта)proxy_type: "residential"— принудительное использование резидентных проксиbypass_level: "advanced"— для сайтов с усиленной защитой
Для большинства задач достаточно стандартных настроек; тонкая подстройка нужна только при низком success rate.
Обработка CAPTCHA
Даже при качественных прокси CAPTCHA иногда появляется — reCAPTCHA v3, hCaptcha, Cloudflare Turnstile. Scraper API обычно интегрирован с сервисами решения CAPTCHA:
- Автоматическое определение появления CAPTCHA на странице
- Отправка задачи в сервис решения (ИИ или ручной)
- Подстановка токена и повторная отправка запроса
С вашей стороны ничего делать не нужно — API обрабатывает CAPTCHA прозрачно. Стоимость решения, как правило, включается в стоимость запроса (или тарифицируется отдельно по факту). Важно отслеживать долю запросов, требующих CAPTCHA: если она растёт, возможны проблемы с прокси или частотой запросов.
LLM-экстракция структурированных данных
Классический парсинг опирается на CSS/XPath-селекторы. При частых изменениях вёрстки селекторы ломаются, парсеры требуют доработки. Альтернатива — извлечение с помощью LLM: вы передаёте HTML (или текст) и схему полей, модель возвращает структурированный JSON.
class Product(BaseModel):
title: str
price: float
currency: str
in_stock: bool
# В запросе к API указываем extract_schema на основе Pydantic-модели
extract_schema = {
"title": {"type": "string"},
"price": {"type": "number"},
"currency": {"type": "string"},
"in_stock": {"type": "boolean"}
}
API, поддерживающий AI-экстракцию, принимает такую схему и возвращает готовый JSON. Преимущества: устойчивость к редизайнам, работа с неструктурированным текстом. Недостатки: выше стоимость и время ответа. Для стабильных источников CSS-селекторы остаются экономичным вариантом; LLM имеет смысл для разнородных или часто меняющихся сайтов.
Масштабирование до 10 000 страниц: асинхронный батчинг
При объёмах в тысячи страниц критична параллельность. Синхронные запросы в цикле работают слишком медленно. Необходим асинхронный подход с ограничением concurrency, чтобы не превышать лимиты API и не перегружать целевые сайты.
import asyncio
from httpx import AsyncClient, Limits
async def scrape_batch(urls: list[str], api_key: str, max_concurrent: int = 10) -> list[dict]:
limits = Limits(max_connections=20, max_keepalive_connections=10)
results = []
async def fetch_one(client: AsyncClient, url: str) -> dict | None:
try:
resp = await client.post(
"https://api.example.com/v1/scrape",
json={"url": url, "render_js": True},
headers={"Authorization": f"Bearer {api_key}"}
)
resp.raise_for_status()
return {"url": url, "html": resp.json()["html"], "status": "ok"}
except Exception as e:
return {"url": url, "error": str(e), "status": "failed"}
async with AsyncClient(timeout=60.0, limits=limits) as client:
sem = asyncio.Semaphore(max_concurrent)
async def limited_fetch(url):
async with sem:
return await fetch_one(client, url)
tasks = [limited_fetch(url) for url in urls]
results = await asyncio.gather(*tasks)
return results
Ключевые моменты:
- Semaphore — ограничение одновременных запросов (например, 10–20)
- Connection pooling — переиспользование соединений через
AsyncClient - Обработка ошибок — логирование неудачных URL для повторной обработки
- Ретраи — экспоненциальный backoff при 429/503
При 10 000 URL и 10 параллельных запросах, при среднем времени ответа 5 секунд, полный прогон займёт ориентировочно 1–2 часа (с учётом ограничений и повторов).
Компромиссы и практические выводы
Плюсы Scraper API:
- Не нужно поддерживать инфраструктуру обхода (прокси, браузеры, CAPTCHA)
- Быстрый вывод продукта на рынок
- Предсказуемая стоимость при переменных объёмах
Минусы:
- Зависимость от провайдера
- При очень больших стабильных объёмах собственное решение с прокси может быть дешевле
- Ограничения по кастомизации (особые заголовки, сложные сценарии взаимодействия)
Гибридный подход:
- Простые, незащищённые сайты — собственный скрейпер + прокси InfraProxy
- Защищённые маркетплейсы, площадки с вакансиями, соцсети — Scraper API
- Комбинирование обоих вариантов в одном пайплайне
Для старта разумно начать с API: проверить гипотезу, оценить success rate и стоимость. При росте объёмов и стабилизации требований можно перенести часть нагрузки на DIY-решение с качественными резидентными прокси.
InfraProxy предоставляет резидентные прокси для DIY-скрейпинга и совместим с популярными Scraper API. Надёжные IP, ротация, поддержка HTTP/HTTPS/SOCKS5. Рассчитайте стоимость.
Нужны надёжные прокси для вашего проекта?
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+ страниц.