Большинство ошибок при сборе данных — это типичные грабли, на которые наступали почти все, кто серьезно занимался сбором данных с сайтов. Сотни падений парсера из-за сломанной верстки, блокировки IP с формулировкой «Too Many Requests», получение пустых HTML, осознание, что 90% собранных данных — мусор.
За последние годы сайты стали гораздо агрессивнее защищаться от автоматического сбора данных. В это время парсеры учились на новых ошибках сбора данных и адаптировались к ужесточенным условиям.
Скрапинг — непростая задача, но ее можно выполнить быстрее, если не наступать на грабли. Поэтому сейчас вы узнаете про распространенные ошибки при сборе данных и как их избежать.
Игнорирование условий использования сайта
Некоторые веб-сайты прямо запрещают автоматический сбор данных в своих условиях использования (пользовательских соглашениях). Эти документы обычно спрятаны в футере сайта и редко читаются, но могут содержать пункт о запрете парсинга. Игнорируя это, парсер нарушает соглашение с сайтом, и, получается, что парсинг нелегален.
Нарушение условий использования чревато последствиями. В лучшем случае сайт просто заблокирует ваш IP или учетную запись. В худшем случае — могут последовать юридические шаги (особенно если при регистрации вы явно соглашались с правилами). К тому же, такой сбор данных можно считать неэтичным, подрывает доверие и может навредить вашей репутации.
Как избежать этого?
Всегда проверяйте разделы «Terms of Use», «Пользовательское соглашение» или «Правила сайта» перед началом скрапинга. Если в них есть запрет на автоматический сбор данных, лучше воздержаться от парсинга этого ресурса или запросить разрешение у владельцев. Обратите внимание и на файл robots.txt — хотя он не закон, он указывает, что администраторы не хотели бы, чтобы боты обходили определенные разделы сайта. Если парсинг необходим, соблюдайте оговоренные лимиты и не наносите сайту ущерб (не перегружайте сервер).
Игнорирование правовых ограничений (GDPR, CCPA и др.)
Скрапинг может затрагивать персональные данные пользователей (имена, контакты, отзывы и т.п.), которые защищаются законами о конфиденциальности — например, GDPR в Европе или CCPA в Калифорнии. Ошибка — не учитывать эти правовые нормы.
Нарушение законов о защите данных несет серьезные последствия. GDPR предусматривает огромные штрафы (до миллионов евро) за неправомерную обработку личных данных. Даже если вы технически сумели спарсить информацию, постфактум может оказаться, что ее использование незаконно. Компании, пользующиеся такими данными, рискуют судебными исками и репутационным ущербом. Кроме того, несанкционированный обход систем защиты (например, парсинг данных, защищенных Cloudflare) может квалифицироваться как неправомерный доступ и нарушать законы о кибербезопасности.
Что делать?
Предварительно изучайте юридическую сторону. Убедитесь, что сбор нужных данных не нарушает ни местное законодательство, ни политику приватности самого ресурса.
Также старайтесь парсить общедоступные данные и избегать того, что явно попадает под защиту (например, парсинг закрытых профилей пользователей соцсетей без разрешения). Если сайт предлагает официальные средства доступа к данным (API с ограничениями, как у TikTok для исследований в ЕС), лучше воспользоваться ими.
Отсутствие надежных прокси
Запуск скрапинга со своего реального IP-адреса или с одного-двух адресов без использования прокси-серверов — очень распространенная ошибка. Прокси нужны, чтобы распределять запросы и не раскрывать ваш настоящий IP. Без них скрапер быстро «засветится»: десятки или сотни запросов с одного IP мгновенно выглядят подозрительно. Также некоторые сайты показывают разный контент для разных регионов — без прокси вы не сможете собрать полные данные.
Плохое решение — бесплатные прокси или случайные VPN. Они обычно нестабильны, медленны и могут сами воровать ваши данные.
Как не допустить эту ошибку?
Используйте качественные прокси. Оптимально — ротация IP-адресов через пул резидентных или мобильных прокси (динамических). Специализированные провайдеры (например, Froxy) предоставляют большие пулы адресов, в том числе по конкретным странам и городам.
Настройте парсер на работу через прокси: большинство библиотек (Python requests, Scrapy и др.) поддерживают указание прокси-сервера. Рекомендуется чередовать IP как можно чаще — либо на каждый запрос новый, либо хотя бы на каждую новую сессию.
Слишком частые запросы
Реальный пользователь не делает десятки запросов в секунду, и сайты отслеживают подобные всплески. Ошибка особенно часто встречается при параллельном парсинге (много потоков сразу штурмуют сайт) или при отсутствии каких-либо задержек в коде.
- Во-первых, если перестараться, можно действительно перегрузить слабый сайт — он начнет отвечать ошибками или ляжет, что негативно и неэтично (может рассматриваться как DoS-атака).
- Во-вторых, подавляющее большинство сайтов имеют встроенные ограничения: например, не более N запросов с одного IP в минуту. При превышении включается либо throttling (искусственное замедление ответа), либо outright блокировка.
Многие сайты намеренно ограничивают скорость соединения и число запросов в секунду от одного клиента. Нарушите лимит — получите либо код ошибки 429 Too Many Requests, либо вообще временно бан 503. Также сайт может начать требовать CAPTCHA после определенного числа запросов в минуту. Без контроля частоты парсинг быстро упрется в блокировку.
Как избежать?
Простейшее решение — ставить time.sleep() между запросами. Желательно с рандомизацией: не ровно 1 секунда каждый раз, а случайный интервал в диапазоне 1-3 сек. Так вы снизите риск быть распознанным ботом по равномерным таймингам.
Если используете фреймворки (Scrapy, etc.), посмотрите настройки AutoThrottle. Также следите за ответами сервера: если вдруг пошли ответы 429/503, скрипт должен стать на паузу и ждать несколько минут.
Еще полезно мониторить заголовки ответов — некоторые сайты посылают X-RateLimit-Limit и X-RateLimit-Remaining, указывая максимальную частоту.
И, конечно, одно из решений - это распараллеливание через прокси: 100 запросов, разбитые по 10 IP, выглядят как 10 запросов с каждого — куда менее заметно.
Игнорирование JavaScript-контента
Будет ошибкой попытаться спарсить страницу лишь статическими методами (запросом HTML и разбором через BeautifulSoup, например) и игнорировать то, что часть данных загружается динамически скриптами (пагинация). Первоначальный HTML может не содержать нужной информации, она подтягивается через JavaScript (AJAX-запросы) после загрузки страницы или при прокрутке.
Почему это критично? Вы можете получить неполные или нулевые данные. Например, парсите интернет-магазин — скрипт ищет цены в HTML, а на сайте цены подгружаются JSом из API после загрузки страницы. В результате ваш код не увидит цен вообще. Другая проблема — бесконечная прокрутка: список товаров или постов может подгружаться порциями при скролле. Обычный парсер этого не сделает и соберет лишь первые элементы.
Как работать с пагинацией?
Используйте инструменты эмуляции браузера. Так называемые headless-браузеры (безголовые) способны загрузить страницу полностью, выполнить JavaScript и предоставить итоговый HTML для парсинга. Популярные варианты — Selenium для скрапинга, парсинг с Puppeteer, сбор данных с Playwright.
Например, можно с помощью Selenium открыть страницу и дождаться, пока скрипты загрузят цены, затем получить page_source. Также можно ловить сетевые запросы: часто динамический контент грузится через XHR, и можно напрямую запросить тот же URL (из DevTools видно).
Для «бесконечной прокрутки» — либо скриптом прокручивать страницу вниз (в Selenium/Puppeteer есть функции скролла), либо вызывать JS-функции загрузки. В любом случае, нужно заложить паузы ожидания, пока контент появится.
Пренебрежение защитой от ботов и CAPTCHA
Многие сайты оснащены системами anti-bot: от простейших (CAPTCHA при подозрении) до комплексных (Cloudflare, динамический анализ поведения, honeypot-ловушки). Ошибка скрапера — игнорировать наличие такой защиты.
Игнорирование бот-защиты ведет либо к блокировкам, либо к тому, что парсинг застопорится. Например, скрипт пытается перейти по невидимой для людей ссылке <a style="display:none" href="/honeypot">…</a> — сайт сразу определит нарушителя и заблокирует его.
Или после нескольких десятков запросов вам начинают выдаваться страницы с CAPTCHA, которую бот сам решить не может — сбор данных прекращается. Современные системы (Cloudflare, Datadome и пр.) могут даже без CAPTCHA блокировать по совокупности факторов (нехватка правильных заголовков, отсутствие движений мыши и т.д.). Если не предпринимать мер, автоматизация далеко не уйдет: либо соберете только малую часть данных, либо придется постоянно вручную вмешиваться (разгадывать капчи и разблокировать).
Как обойти защиту?
Вот несколько направлений:
- Honeypot: фильтровать из DOM все элементы, скрытые стилями (display:none, visibility:hidden и т.п.) — никогда не «кликать» по ним и не заполнять их. Соблюдать robots.txt — некоторые ловушки специально размещены в разделах, запрещенных для ботов.
- CAPTCHA: интегрировать сервисы распознавания капчи. Существуют API (Anticaptcha, ruCaptcha, 2Captcha и др.), где реальные люди за небольшую плату разгадывают капчи в режиме онлайн.
- Имитация поведения: использовать случайные задержки между действиями, ввод случайных пауз (чтобы не было четкого интервала между запросами). Менять порядок действий, не обходить сайт по предсказуемому паттерну. В браузерных скриптах — прокручивать страницу, двигать мышь (можно программно).
- Технические заголовки и отпечатки: обязательно ставить реальный User-Agent браузера, возможно эмулировать набор других заголовков (Accept-Language, Encoding, DoNotTrack и т.п.).
- Ротация прокси и идентификаторов: не делать сотни запросов с одного IP, а также при веб-автоматизации менять цифровой отпечаток (fingerprint).
Но не забывайте о том, что такой обход также может иметь последствия, если ваш сбор данных неэтичен или явно нарушает правила пользования сайтом.
Мобильные прокси
Мобильные IP-адреса обеспечивают максимальную гибкость и бесперебойную связь.
Парсинг HTML без учета изменений
Написали парсер «под текущую верстку» сайта, не предусматривая возможные изменения? Однако сайты не статичны — разработчики могут обновить дизайн, поменять класс имен с "price" на "cost" или переставить блоки местами.
В один «прекрасный» день парсер начинает либо собирать пустые данные, либо не работает как надо. Например, вы извлекали цены по селектору .product > .price, а сайт изменил класс на .product > .new-price. Ваш код не найдет элемент и вернет пустое значение или None — в результате набор данных искажен (цены просто отсутствуют).
Что может помочь?
Лучше использовать не самые хрупкие привязки — например, ориентироваться на атрибуты или тексты, которые менее вероятно поменяются, чем имена CSS-классов. Если доступен уникальный идентификатор или название элемента, использовать его. Также хорошо иметь несколько стратегий поиска: например, если элемент не найден по одному селектору, попробовать альтернативный.
Если вкратце, то обратите внимание на эти техники:
- Парсинг по ID. Если элементы имеют устойчивые id (которые реже меняются), лучше опираться на них, а не на глубину вложенности.
- Регулярные выражения. В случаях, когда меняются только числовые значения или незначительная часть текста, re помогает вычленить нужное без привязки к конкретному тегу.
- Системы отслеживания изменений. Сторонние сервисы (VisualPing, Wachete) могут мониторить страницу и уведомлять об изменении контента/верстки. Получив уведомление, вы сразу проверите, не сломало ли это ваш парсер.
Сбор HTML-данных при наличии API
Не нужно парсить HTML «по старинке», когда сайт уже предоставляет официальный API для доступа к данным. Например, вместо того чтобы разбирать HTML страницы с погодой, можно вызвать открытое API этого сервиса и получить аккуратный JSON без лишнего «мусора» разметки, что упрощает обработку.
Как проверить наличие API?
Мониторьте разделы «Для разработчиков» на сайте, публичную документацию. Если API есть — оцените возможность его использования: возможно, потребуется зарегистрировать ключ или платить за повышенные лимиты, но это может окупиться стабильностью. Если API платное или ограниченное, а данных нужно много — взвесьте, что выгоднее: риск блокировок при HTML-скрапинге или официальная подписка.
Отсутствие этапа обработки ошибок и логов
Парсер написан без должной обработки исключительных ситуаций — не ловятся ошибки запросов, не ведется лог. Например, если сайт вернет 500 или соединение таймаут, скрипт сразу падает или пропускает silently. Нету записи, что, где и почему случилось. Также не фиксируется ход выполнения (сколько страниц уже обработано, сколько осталось), а в этот момент парсер тихо пропустил 20% страниц из-за ошибок подключения — и вы об этом не узнаете, получив неполный датасет.
Как избежать проблем?
Используйте готовые решения, например, tenacity для Python — гибко настраивает ретраи (повторы) при исключениях. В Python стандартный модуль logging позволяет выводить сообщения разных уровней (INFO, WARNING, ERROR) с указанием времени.
Сбор нерелевантных или дублированных данных
Парсер захватывает все подряд, не фильтруя данные по нужному признаку, либо собирает одни и те же сущности по нескольку раз. Например, в HTML-странице помимо основного контента есть меню, футер, реклама — скрипт все выдирает, хотя это не относится к целевым данным.
Лишние данные усложняют последующую обработку. Вам придется потом тратить время на очистку: убирать HTML-теги, отбросить навигацию, рекламу, повторяющиеся элементы. Если этого не сделать, последующий анализ будет искажен.
Дубликаты могут привести к завышению результатов, а в случае, если дубли не очевидны, можно вообще сделать неправильные выводы. Кроме того, хранение лишних данных расходует память/место и ваше время.
Какие инструменты использовать?
- Библиотеки для очистки HTML. Например, BeautifulSoup умеет извлекать только текст, без тегов. Также можно использовать bleach для удаления скриптов и опасных тегов.
- Dedupe-пакеты. Есть библиотека python-dedupe для поиска дублирующихся записей по похожести, если прямая идентификация затруднена.
Большинство парсинг-библиотек позволяют выбирать по CSS-селекторам конкретную часть DOM. Также можно предварительно очистить HTML от скриптов, стилей, комментариев, чтобы не мешали. Применяйте пост-фильтрацию: например, если вы собираете адреса электронной почты, отфильтруйте полученный список регуляркой, чтобы там остались только валидные email (лишний текст уйдет).
Чтобы избежать дедупликации, используйте структуры данных, обеспечивающие уникальность (например, Python set, или уникальный ключ в базе). Если у сущности есть идентификатор (артикул, ID новости) — храните его и проверяйте, не собирали ли уже.
Пропуск нормализации и дедупликации
Получив сырые данные, сразу отправляться их анализировать или хранить, но не выполнили нормализацию (приведение к единому стандарту) и удаление дублей. Например, вы спарсили цены: в одном месте у вас "$1 234", в другом "$ 1234" — без нормализации эти значения не сопоставимы. Или собрали имена компаний, где одна и та же компания написана то полностью, то сокращенно — без выравнивания вы посчитаете их разными. А пропущенные значения (NaN, None) без обработки могут привести к сбоям в скриптах анализа.
Как избежать ошибки?
- Нормализация форматов. Числа привести к числовому типу (убрать пробелы, валютные символы, привести все цены к одной валюте если нужно), даты — к единому формату (например ISO-8601 или Unix timestamp). Тексты — обрезать лишние пробелы, спецсимволы.
- Единообразие единиц. Если один сайт выдает вес в фунтах, другой в килограммах — сконвертировать к одной системе.
- Удаление дубликатов. Применяйте либо алгоритмическое удаление (по ID, по полной строке), либо при слиянии данных из разных источников — агрегировать по ключу.
- Заполнение пропусков. Возможно, стоит предусмотреть значения по умолчанию или пометки, если каких-то данных нет, чтобы дальше не ловить NullPointer. Например, для отсутствующих цен поставить 0 или специальную метку.
И только после таких преобразований загружать в финальное хранилище или передавать в аналитику.
Резидентные прокси
Лучшие прокси-серверы для доступа к ценным данным со всего мира.
Отсутствие стратегии хранения данных
Парсер полученные данные складывает «как попало»: например, пишет все в один огромный CSV-файл, или в память программы, или вообще не сохраняет толком, выводя на экран. И здесь все зависит от вас.
Какие инструменты использовать?
Оцените, какой объем данных ожидается и как они будут использоваться. Если это разовая небольшая выгрузка — может хватить и CSV/JSON файлов.
Если данные нужно активно запросами обрабатывать — лучше сразу строить базу данных (SQL или NoSQL). Например, для структурированных таблиц подойдет PostgreSQL/MySQL, для документов — MongoDB, для поисковых задач — Elasticsearch.
Если собираете разово очень большой объем, возможно лучше хранить как parquet/orc файлы и обрабатывать по необходимости (например, с Pandas или Spark).
Обязательно учитывайте резервное копирование: важные данные храните не в одном экземпляре. Если объем большой, рассмотреть хранилища типа S3 (для файлов) или Hadoop.
Отсутствие плана по обновлению данных
Многие данные со временем теряют актуальность. Цены, наличие товаров, курсы валют, новости, контакты организаций — все меняется. Без плана обновления ваша информационная база постепенно перестает соответствовать реальности. Это может привести к неправильным решениям (вы реагируете на действия конкурента с запозданием, потому что ваши данные устарели). В конце концов, отсутствие автоматизированного обновления приводит к авралам: вы вдруг понимаете, что данные нужны свежие, и запускаете парсинг с нуля в спешке, вместо равномерного планового обновления.
Здесь решение довольно однозначное — разработать стратегию обновления. Определите типы данных по частоте их изменений, решите, как совмещать новые и старые данные, настройте мониторинг изменений.
Вы можете использовать cron (Linux) или Task Scheduler (Windows) для периодического запуска парсеров. Либо более сложные сервисы как Apache Airflow для управления расписанием скрапинга множества источников.
Инструменты типа Scrapy поддерживают режим, когда они обходят только новые или изменившиеся страницы (при помощи FEED export с опцией delta, либо с middleware, отмечающим старые URL).
Подводя итоги
Скрапинг давно перестал быть просто способом сбора данных с сайтов. Теперь он требует системного подхода, в котором сочетаются юридическая осведомленность, архитектура, масштабируемость, качество данных и особое распределение ресурсов в виде времени и трудозатрат.
К сбору данных стоит относиться как проекту. А если учитывать возможные ошибки и вовремя внедрять правильные инструменты, то как к успешному проекту.