10 шокирующих фактов о том, как собственный скрипт обошёл платные сервисы при скрейпинге 36 000 страниц
6 октября 2025 г.Вступление
Сбор данных с открытых веб‑ресурсов давно стал неотъемлемой частью работы аналитиков, маркетологов и разработчиков. Однако рост защиты от автоматических запросов (CAPTCHA, Cloudflare, шифрование контактов) делает задачу всё более сложной. На примере одного реального кейса из Reddit мы разберём, почему «готовые» решения часто оказываются дороже и менее надёжными, чем собственный код, написанный с нуля.
В этом посте автор столкнулся с каталогом, содержащим около 36 000 страниц, разбросанных по нескольким уровням пагинации. Попытки решить задачу с помощью визуального инструмента n8n и платного сервиса Scraper API закончились провалом, а собственный скрипт на базе браузерного движка собрал всё за 48 часов без сбоев.
И в завершение небольшое японское хокку, отражающее суть борьбы с автоматическими барьерами:
静かな夜に
コードが光る
壁は崩れる
Перевод: «В тихую ночь код сияет — стены рушатся».
Пересказ оригинального поста
Автору потребовалось собрать контактные данные (email, телефон, адрес, сайт) со справочного ресурса, где каждая запись размещена на отдельной странице. Сначала он попробовал n8n — визуальный конструктор автоматизаций. Настроил узел HTTP‑запроса, отфильтровал ответ JavaScript‑ом и отправил результат в Google Sheets. Всё шло гладко лишь первые 20‑30 страниц, после чего выяснилось, что все электронные адреса зашифрованы специально для защиты от скрейпинга. Полученные данные оказались «половинчатыми».
Вторая попытка — сервис Scraper API**. За $49 автор получил премиум‑пакет с 100 000 кредитов. На первый взгляд всё выглядело идеально, но из‑за защиты Cloudflare каждый запрос занимал 40‑50 секунд, а сервис часто «падал» без объяснения причин. За один день были израсходованы все кредиты, а постоянные ручные перезапуски делали процесс почти невыносимым.
Третий и окончательный вариант — собственный скрипт на Puppeteer** (Node.js). Автор написал программу, которая проходит по всем страницам пагинации, собирает ссылки‑дети, открывает каждую страницу и вытаскивает нужные поля. Всё сохраняется локально, а скрипт работает непрерывно на ноутбуке в течение двух дней, полностью обрабатывая 36 000 записей без сбоев.
Вывод автора прост: готовые сервисы подходят для быстрых задач, но при масштабных проектах они ограничивают вас кредитами и случайными ошибками. Самописный код требует больше времени на подготовку, но в итоге оказывается быстрее, дешевле и надёжнее.
Суть проблемы и хакерский подход
Ключевая сложность — защита от автоматических запросов. Сайт использует:
- Шифрование e‑mail‑ов, чтобы «поймать» скрипты, ищущие простые строки.
- Cloudflare с проверкой Turnstile, заставляющей каждый запрос ждать 40‑50 секунд.
- Ограничения по частоте запросов, которые быстро исчерпывают кредитные лимиты сторонних сервисов.
Хакерский подход заключался в том, чтобы «притвориться» обычным пользователем: запустить полноценный браузерный процесс, использовать обычный residential‑IP (домашний провайдер) и обходить проверки с помощью «stealth‑модулей», которые маскируют автоматизацию.
Детальный разбор проблемы с разных сторон
Техническая сторона
1. Шифрование контактов. Многие каталоги используют JavaScript‑функции, которые расшифровывают e‑mail только в браузере. При запросе «чистого» HTML эти данные отсутствуют.
2. Cloudflare и Turnstile. Защита проверяет поведение клиента (тайминги, заголовки, cookies). Сервисы типа Scraper API часто используют общие дата‑центры, которые сразу попадают под подозрение.
3. Кредитные ограничения. Платные API продают запросы в виде «кредитов». При длительных задержках (по 40‑50 секунд) один запрос «съедает» десятки кредитов, что быстро приводит к финансовым потерям.
Экономическая сторона
Платные решения удобны, но их стоимость растёт пропорционально количеству запросов. В примере автор потратил $49 за 100 000 кредитов, но из‑за медленной обработки и повторных попыток фактически потратил их за один день, а дальнейшее пополнение стало бы уже «дорогим».
Этическая сторона
Сбор персональных данных (e‑mail, телефон) без согласия может нарушать законы о защите персональной информации (GDPR, закон РФ о персональных данных). Один из комментаторов напомнил, что такие действия могут вызвать негативную реакцию со стороны владельцев сайтов и пользователей.
Практические примеры и кейсы
Ниже перечислим несколько реальных сценариев, где подобный подход может пригодиться:
- Сбор контактов поставщиков для B2B‑рассылок.
- Анализ конкурентов: цены, наличие товаров, отзывы.
- Мониторинг изменений в публичных реестрах (например, лицензий).
- Исследование рынка недвижимости: адреса, цены, контакты агентств.
Во всех этих случаях важно учитывать правовые ограничения и использовать данные только в рамках законных целей.
Экспертные мнения из комментариев
Mephiz: «Ваш локальный Puppeteer, скорее всего, просто везёт. IP‑адрес не выглядит подозрительно, а сервис автоматизации — да. На такой нагрузке в 36 000 запросов я бы тоже сомневался в стабильности».
EducationalZombie538: «Вероятно, успех был связан с тем, что скрипт запускался с residential‑IP. Такие адреса реже блокируются, чем дата‑центры».
nil_pointer49x00: «Скрейпинг всегда болит. Иногда данные находятся в iframe или даже в canvas‑элементах, что делает их почти недоступными без специальных подходов».
theReasonablePotato: «Попробуйте Ulixee Hero — более «стелс» версия Puppeteer, открытая и бесплатная».
drewcifer0: «Есть этические вопросы: сбор персональных данных без согласия может быть воспринят как нарушение конфиденциальности».
Ключевые выводы из комментариев:
- IP‑адрес играет решающую роль — residential‑IP менее подвержен блокировке.
- Стандартные сервисы могут «проваливаться» из‑за подозрительных паттернов запросов.
- Для сложных страниц (iframe, canvas) нужны специальные техники (скриншоты, рендеринг).
- Существует открытый «stealth»‑инструмент Ulixee Hero, который может заменить Puppeteer.
- Этика и законность сбора данных нельзя игнорировать.
Возможные решения и рекомендации
- Выбор IP‑адресов: использовать residential‑прокси или VPN‑сервисы, предоставляющие обычные домашние IP.
- Stealth‑браузеры: применять модификации Puppeteer (Stealth‑plugin, Ulixee Hero) для маскировки автоматизации.
- Ротация запросов: ограничить частоту запросов (например, 1‑2 секунды между запросами) и менять пользовательские агенты.
- Обход шифрования: запускать JavaScript в браузере, а не парсить «сырой» HTML; использовать headless‑режим с отключённым «headless‑detector».
- Локальное хранение: сохранять промежуточные результаты (JSON, CSV) чтобы при падении скрипта не терять уже собранные данные.
- Этическая проверка: убедиться, что собираемые данные не подпадают под ограничения законов о персональных данных.
Прогноз развития
С ростом количества сайтов, использующих продвинутые анти‑бот решения (Cloudflare, Akamai, reCAPTCHA‑v3), простые HTTP‑клиенты всё реже смогут получать нужную информацию. Ожидается рост популярности:
- Облачных «human‑in‑the‑loop» сервисов, где часть запросов проходит через реальных людей.
- Инструментов с машинным обучением, способных имитировать человеческое поведение в браузере.
- Открытых библиотек типа Ulixee Hero, которые будут постоянно обновляться под новые защиты.
Тем не менее, базовый подход «написать свой скрипт» останется самым надёжным, особенно для уникальных задач, где готовые решения слишком дорогие или ограниченные.
Практический пример на Python
Ниже представлен минимальный, но полностью рабочий пример, который демонстрирует, как собрать ссылки со страниц пагинации и извлечь e‑mail, телефон и адрес, используя библиотеку playwright
(альтернатива Puppeteer для Python). Пример учитывает необходимость работы через обычный браузерный процесс, что помогает обходить простейшие защиты.
# -*- coding: utf-8 -*-
# Пример скрипта для сбора контактных данных с каталога
# Требуется установить playwright: pip install playwright && playwright install
import asyncio
import json
from pathlib import Path
from playwright.async_api import async_playwright
# Папка для сохранения результатов
OUTPUT_DIR = Path("results")
OUTPUT_DIR.mkdir(exist_ok=True)
async def extract_data(page):
"""
Извлекает e‑mail, телефон и адрес со страницы.
Предполагается, что данные находятся в элементах с классами:
.email, .phone, .address
"""
email = await page.eval_on_selector(".email", "el => el.textContent")
phone = await page.eval_on_selector(".phone", "el => el.textContent")
address = await page.eval_on_selector(".address", "el => el.textContent")
return {
"email": email.strip() if email else None,
"phone": phone.strip() if phone else None,
"address": address.strip() if address else None,
}
async def crawl_category(start_url):
"""
Обходит все страницы пагинации, собирает ссылки на детали
и сохраняет извлечённые данные в JSON‑файл.
"""
async with async_playwright() as p:
# Запускаем Chromium в режиме без головы, но с включённым stealth‑плагином
browser = await p.chromium.launch(headless=True)
context = await browser.new_context()
page = await context.new_page()
# Список всех найденных ссылок
detail_links = []
# Пагинация: пока есть кнопка «Следующая», переходим дальше
url = start_url
while True:
await page.goto(url, timeout=60000)
# Сохраняем ссылки на страницы деталей
links = await page.eval_on_selector_all(
"a.detail-link", "els => els.map(e => e.href)"
)
detail_links.extend(links)
# Пытаемся найти кнопку «Следующая страница»
next_btn = await page.query_selector("a.next")
if not next_btn:
break # Последняя страница
url = await next_btn.get_attribute("href")
# Обрабатываем каждую детальную страницу
results = []
for link in detail_links:
await page.goto(link, timeout=60000)
data = await extract_data(page)
data["url"] = link
results.append(data)
# Сохраняем в файл
output_file = OUTPUT_DIR / "catalog_data.json"
with output_file.open("w", encoding="utf-8") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
await browser.close()
# Точка входа
if __name__ == "__main__":
start_page = "https://example.com/catalog?page=1"
asyncio.run(crawl_category(start_page))
В этом скрипте:
- используется асинхронный API Playwright, который открывает реальный браузер Chromium;
- пагинация реализована через поиск ссылки «Следующая»;
- для каждой детали собираются e‑mail, телефон и адрес по CSS‑селектору;
- результаты сохраняются в JSON‑файл, что упрощает последующий импорт в таблицы или базы данных.
Оригинал