Скрапер блокируется, когда его трафик не соответствует тому, что целевой сайт ожидает от реального посетителя. Запрос приходит с адреса с плохой репутацией, несёт скудный или противоречивый набор заголовков, срабатывает быстрее, чем может кликнуть любой человек, или запрашивает страницу, которую сайт никогда не отдаёт ботам. Любого из этих признаков достаточно для современной антибот-системы, чтобы вернуть 403, CAPTCHA или пустую страницу вместо нужных данных.
Это руководство охватывает практические тактики, которые помогут скраперу выглядеть как браузер: ротация резидентских IP, отправка реалистичных заголовков и user-agent'ов, регулирование и рандомизация тайминга, соблюдение robots.txt, рендеринг JavaScript при необходимости, обработка CAPTCHA, управление сессиями и куки, а также отслеживание статус-кодов для своевременного отступления до того, как мягкое ограничение превратится в бан. Ни одна из тактик не является панацеей, но применённые в правильном порядке они превращают большинство целей из стены блоков в стабильный поток 200.
Почему скраперы блокируются
Прежде чем перейти к тактикам, полезно понять, с чем вы имеете дело. Антибот-системы помечают автоматизированный трафик по трём широким сигналам, и почти каждая блокировка восходит к одному из них.
- Отпечаток. Настоящий браузер несёт согласованный набор сигналов: полный набор заголовков, TLS-рукопожатие, соответствующее заявленному user-agent, среду выполнения JavaScript, куки, сохраняющиеся между запросами. Стандартный HTTP-клиент почти ничего из этого не несёт, а частично подделанный несёт сигналы, противоречащие друг другу. В любом случае он выделяется.
- Частота. Сайты считают запросы на IP и на сессию во времени. Трафик, поступающий быстрее, чем человек мог бы его генерировать, или с идеально регулярным интервалом, выглядит как скрипт, сколь бы чистым ни был каждый отдельный запрос.
- Репутация IP. Адреса из известных диапазонов дата-центров, в общих чёрных списках или с историей злоупотреблений вызывают подозрение с первого же запроса. IP, с которого вы приходите, определяет вашу стартовую доверенность ещё до отправки единственного заголовка.
Каждая из приведённых ниже тактик работает, восстанавливая один из этих сигналов. Сначала применяйте дешёвые, измеряйте частоту блокировок и обращайтесь к тяжёлой артиллерии только тогда, когда цель действительно вынуждает вас.
Ротация резидентных IP
Самая распространённая блокировка проста: слишком много запросов с одного адреса. Сайт считает обращения по IP и начинает возвращать 429 или страницу блокировки, как только вы превысите порог. Распределите тот же объём запросов по множеству IP, и ни один адрес не достигнет лимита. Именно поэтому инфраструктура скрапинга в основном и есть прокси-инфраструктура: прокси делает запрос вместо вас, так что цель видит его адрес, а не ваш.
Тип IP важен не меньше, чем ротация. IP дата-центров быстры и дёшевы, но находятся в диапазонах хостинга, которые любая цель может определить одним запросом, поэтому на защищённых сайтах они выглядят как автоматизированные. Резидентские IP выходят через реальные потребительские соединения и выглядят как обычные посетители, при более высокой стоимости и меньшей скорости. Полное сравнение приведено в статье о прокси дата-центров и резидентских прокси. Покупайте ровно столько доверия, сколько требует цель: резидентские для строгих сайтов, дата-центры для лояльных.
Ручная ротация означает поддержание пула адресов, перебор их по запросу и удаление заблокированных. Ротационный шлюз скрывает это за единственной точкой входа и сам меняет выходной IP, либо свежий на каждый запрос, либо закреплённый за сессией, когда нужно сохранить одну личность на нескольких страницах.
Отправляйте реалистичные заголовки и user-agent
Стандартный HTTP-клиент выдаёт себя с первой же строки. Библиотека Python requests объявляет User-Agent: python-requests/2.x и почти не отправляет других заголовков, тогда как настоящий браузер отправляет дюжину в определённом порядке. Сайты, которые делают не больше чем читают этот заголовок, заблокируют первый запрос и пропустят второй.
Установите актуальный user-agent реального браузера и ротируйте небольшой пул строк, а не гоняйте одну вечно. Затем отправляйте заголовки, которые всегда сопровождают его: Accept, Accept-Language, Accept-Encoding и правдоподобный Referer. Цель не в одном магическом заголовке, а во внутренней согласованности. Chrome user-agent в паре со значениями Accept в стиле Firefox подозрительнее, чем полное отсутствие спуфинга.
import requests headers = { "User-Agent": ( "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/124.0 Safari/537.36" ), "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.9", "Accept-Encoding": "gzip, deflate, br", "Referer": "https://www.google.com/", } resp = requests.get("https://example.com", headers=headers)
На уровень глубже находится TLS-отпечаток. До отправки первого HTTP-байта клиент открывает TLS-рукопожатие, точная форма которого образует сигнатуру, часто суммируемую в JA3-хэш. Настоящий Chrome выдаёт одну хорошо известную сигнатуру; Python-клиент выдаёт совершенно другую. Когда вы отправляете Chrome user-agent поверх TLS-стека Python, они расходятся, и проверка отпечатка помечает несоответствие, сколь бы идеальными ни были ваши заголовки. Устранить этот разрыв можно только с помощью клиента, имитирующего рукопожатие браузера, или с помощью настоящего движка браузера, который генерирует подлинное рукопожатие бесплатно.
Регулируйте и рандомизируйте тайминг запросов
Даже распределённый по множеству IP скрапер, посылающий запросы с фиксированной частотой, выглядит автоматизированным. Идеально регулярный интервал в 500 мс между запросами сам по себе является отпечатком, поскольку люди не кликают как метроном. Добавьте случайные задержки между запросами вместо постоянных и держите параллелизм на уровне, который цель может поглотить незаметно для себя.
Старый совет использовать нерегулярный, похожий на человеческий паттерн скрапинга по-прежнему актуален: варьируйте интервалы, не обходите страницы в жёсткой последовательности и избегайте одновременной отправки большого числа запросов к одному хосту. Другая часть тайминга состоит в сокращении нагрузки, которую вы вообще не должны создавать. Кэшируйте уже полученные страницы, чтобы никогда не запрашивать их дважды, и скрапьте только тот контент, который вам действительно нужен, а не весь сайт.
Соблюдайте robots.txt и избегайте ловушек
До любой техники обхода прочитайте robots.txt сайта. В нём указано, какие пути оператор готов разрешить к обходу и, как правило, Crawl-delay, сообщающий минимальный интервал между запросами. Соблюдение этого правила отчасти является вежливостью, а отчасти самозащитой: игнорирование объявленных правил самый быстрый способ попасть под подозрение, и именно здесь начинаются вопросы о соответствии условиям использования. Также проверяйте условия использования сайта; если там явно запрещён скрапинг, это сигнал пересмотреть выбор цели.
Связанная ловушка называется honeypot: ссылка, скрытая от человеческих глаз с помощью CSS (display:none, нулевой размер или вынесенная за пределы экрана), но присутствующая в HTML. Наивный краулер, следующий за каждым тегом <a>, прямиком попадает в него и мгновенно обнаруживает себя как бот, поскольку ни один реальный пользователь не мог бы кликнуть на невидимую ссылку. Переходите только по ссылкам, которые отображал бы рендеренный браузер, и пропускайте всё визуально скрытое.
Рендеринг JavaScript как в браузере
Многие страницы возвращают почти пустой HTML и строят реальный контент с помощью JavaScript после загрузки. Получите одну из них обычным HTTP-клиентом, и вы получите оболочку без данных. Некоторые сайты идут дальше и раздают JavaScript-задачу: небольшой скрипт, который должен выполниться и пройти проверку до выдачи реальной страницы, с чем не-браузерный клиент никогда не справится.
В обоих случаях вам нужен настоящий браузерный движок. Безголовый браузер, такой как Playwright, Puppeteer или Selenium, управляющий Chrome, загружает страницу, выполняет её скрипты и передаёт вам DOM, который видел бы пользователь. Он также создаёт подлинный TLS-отпечаток браузера и настоящий объект navigator, поэтому проходит класс проверок, недоступных для обычного клиента. Цена, ресурсоёмкость: безголовый браузер потребляет гораздо больше CPU и памяти на страницу, чем простой запрос, поэтому используйте его только для страниц, которым действительно нужен рендеринг. За более полным руководством обратитесь к статье как обходить JavaScript-сайты и специальному руководству по скрапингу JavaScript-страниц на Python.
Обработка CAPTCHA
CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart), это задача, которую сайт показывает, когда подозревает, что запрос автоматизирован. Многие сайты интегрируют алгоритмы, оценивающие каждого посетителя и запускающие CAPTCHA, когда оценка выглядит роботоподобно. Столкнувшись с ней, никакая настройка заголовков не поможет получить данные по этому запросу.
Устойчивое решение состоит в том, чтобы вообще не провоцировать их появление: чистый резидентский IP, согласованный отпечаток и человекоподобная частота держат ваш «роботный» рейтинг достаточно низким, чтобы задача никогда не срабатывала. Когда цель всё равно их показывает, управляемая конечная точка скрапинга, решающая или обходящая CAPTCHA на стороне сервера, гораздо надёжнее, чем встраивание решателя в собственный стек. Подробности в статье как обходить CAPTCHA при веб-скрапинге.
Когда цели нужно больше, чем чистый IP, Crawling API берёт весь стек на себя: ротирует большой пул выходов дата-центра, резидентских и мобильных, отправляет достоверный отпечаток, рендерит JavaScript при необходимости и обрабатывает CAPTCHA и блоки на стороне сервера. Если вам нужен только слой ротации IP, Smart AI Proxy направляет обычные запросы через ту же сеть с одной конечной точки. Вы отправляете URL и получаете готовый результат. Протестируйте на вашей реальной цели на бесплатном тарифе.
Управление сессиями и cookie
Многие сайты устанавливают куки при первом посещении и ожидают их при каждом последующем запросе. Удаляя куки между запросами, вы выглядите как новый, подозрительно не имеющий состояния посетитель каждый раз, что срабатывает поведенческие проверки, предполагающие, что реальный пользователь накапливает состояние при просмотре. Используйте сессию, сохраняющую куки между запросами, чтобы многоэтапный поток (поиск, пагинация, открытие страницы детали) нёс одну и ту же идентичность на протяжении всего процесса.
Сессии взаимодействуют с ротацией IP, поэтому координируйте их. Если вы переключаетесь на новый IP в середине сессии, куки, выданные для старого адреса, теперь приходят с другого, что само по себе является признаком подозрения. Держите закреплённый IP на протяжении всей логической сессии, затем ротируйте при начале новой. Пример ниже использует requests.Session для сохранения куки и заголовков между вызовами.
import requests session = requests.Session() session.headers.update(headers) # Cookies set on the first call ride along on the rest. session.get("https://example.com/search?q=phones") session.get("https://example.com/search?q=phones&page=2")
Следите за кодами статуса и сбавляйте темп
Ваш скрапер должен относиться к HTTP-статус-кодам как к живой обратной связи, а не просто как к успеху или неудаче. Серия ответов 429 (Too Many Requests) или 503 означает, что сервер говорит вам замедлиться. Соблюдайте это: откатывайтесь экспоненциально, уважайте заголовок Retry-After, когда сервер его отправляет, и воспринимайте всплеск 429 как сигнал снизить общую частоту, а не делать больше повторных попыток. Бомбардировка ограниченной конечной точки на полной скорости, это именно то, как мягкое ограничение превращается в жёсткий бан.
Другие коды несут собственное значение. 403 обычно означает блокировку по отпечатку или репутации IP, поэтому изменение частоты запросов не поможет; вам нужен лучший IP или более достоверный отпечаток. Внезапный 200, возвращающий страницу CAPTCHA вместо контента, является замаскированной блокировкой, поэтому проверяйте тело ответа, а не только код.
import time, random def fetch(session, url, tries=4): for attempt in range(tries): resp = session.get(url) if resp.status_code == 200: return resp if resp.status_code in (429, 503): wait = int(resp.headers.get("Retry-After", 2 ** attempt)) time.sleep(wait + random.uniform(0, 1)) continue resp.raise_for_status() raise RuntimeError("exhausted retries")
Ответственный скрапинг
Оставаться незаблокированным и вести скрапинг ответственно, это одна и та же дисциплина, рассматриваемая с двух сторон. Читайте условия использования каждого сайта и его robots.txt, уважайте то, что они декларируют, ограничивайтесь публичными страницами, а не теми, что за логином, и держите частоту запросов на уровне, который цель может обслуживать без напряжения. Кэшируйте уже полученное, чтобы не запрашивать повторно, и собирайте только те данные, которые вам действительно нужны. Скрапер, ведущий себя как вежливый посетитель, гораздо реже блокируется и гораздо реже создаёт проблему, достойную блокировки.
Ключевые выводы
- Блокировки восходят к трём сигналам. Отпечаток, частота и репутация IP охватывают почти каждую блокировку, и каждая тактика работает, восстанавливая один из них.
- Сначала ротируйте резидентские IP. Большинство блокировок, это лимиты на IP, поэтому распределение запросов по пулу достоверных адресов является самым дешёвым и наиболее эффективным решением.
- Поддерживайте согласованность сигналов. Реалистичные заголовки, совпадающий TLS-отпечаток, постоянные куки и рандомизированная частота убедительнее вместе, чем любой из них по отдельности.
- Уважайте сайт. Соблюдайте robots.txt и условия использования, избегайте ловушек-honeypot, оставайтесь на публичных данных и отступайте, как только 429 или 503 говорит вам об этом.
- Передавайте на аутсорсинг, когда становится сложно. Когда цель сопротивляется одновременно через рендеринг, CAPTCHA и репутацию, управляемый crawling API или smart proxy берут весь стек на себя, чтобы вы не поддерживали его самостоятельно.
Часто задаваемые вопросы
Почему мой веб-скрапер постоянно блокируется?
Потому что его трафик не похож на трафик настоящего браузера хотя бы по одному из трёх параметров: отпечаток, частота или репутация IP. Запрос может приходить с заблокированного IP дата-центра, нести скудный или противоречивый набор заголовков или поступать быстрее и регулярнее, чем может кликать человек. Антибот-системам достаточно одного из этих признаков, чтобы вернуть 403, CAPTCHA или пустую страницу.
Какой самый эффективный способ избежать блокировок при веб-скрапинге?
Ротация по пулу хороших IP, желательно резидентских для строгих целей. Самая распространённая блокировка, лимит на IP, и распределение одного и того же объёма запросов по множеству адресов гарантирует, что ни один из них не превысит порог. Это самое дешёвое решение с наибольшим эффектом, поэтому его обычно применяют первым, до настройки заголовков или тайминга.
Достаточно ли смены user-agent, чтобы избежать блокировок?
На наименее защищённых сайтах иногда да; на серьёзных, нет. Реалистичный user-agent должен сопровождаться полным набором заголовков, которые отправляет браузер, TLS-отпечатком, соответствующим этому браузеру, постоянными куки и правдоподобной частотой запросов. Подделанный user-agent поверх TLS-стека стандартного HTTP-клиента является противоречием, которое проверки отпечатков легко обнаруживают.
Как обрабатывать ответ 429 Too Many Requests?
Замедляйтесь, а не делайте больше повторных попыток. Откатывайтесь экспоненциально, уважайте заголовок Retry-After, когда сервер его отправляет, и воспринимайте серию 429 как сигнал снизить общую частоту запросов. Бомбардировка ограниченной конечной точки на полной скорости, это именно то, как временное ограничение превращается в постоянный бан.
Нужен ли мне безголовый браузер, чтобы не попасть в блок?
Только когда страница строит контент с помощью JavaScript после загрузки или раздаёт JavaScript-задачу, которую обычный клиент не может пройти. Безголовый браузер рендерит страницу и создаёт подлинный браузерный отпечаток, что открывает доступ к проверкам, недоступным для обычного запроса, но стоит значительно больше CPU и памяти на страницу. Для статического HTML хорошо настроенный HTTP-запрос быстрее, дешевле и столь же незаблокирован.
Когда управляемый scraping API имеет больше смысла, чем самостоятельная разработка?
Когда цель отражает атаки сразу на нескольких уровнях. Поддержка пула резидентских прокси, ротации заголовков и TLS, сессий с куки, логики отступления, безголового флота и пути решения CAPTCHA, это реальная инженерная нагрузка, и новая задача может сломать всё за одну ночь. Crawling API или smart proxy берут всё это на себя за один запрос, так что вы платите за запрос и частичную потерю контроля в обмен на то, что не запускаете антибот-инфраструктуру самостоятельно.
Обходите любой сайт в масштабе, без борьбы с инфраструктурой.
Crawlbase берёт на себя прокси, отпечатки и CAPTCHA, чтобы ваша команда выпускала конвейеры данных вместо поддержки обвязки краулинга. 1 000 запросов бесплатно, без карты.
