Scarnox · Blog

Как избежать капчи при парсинге (без нарушения правил)

Большинство капч при парсинге — это реакция на трафик, который выглядит автоматизированным. Самый дешёвый способ с ними справиться — перестать их провоцировать. Для этого нужно сначала искать легитимный источник данных, узнать, что разрешают правила сайта, отправлять меньше и медленнее запросы и не загружать одну и ту же страницу дважды. Решение капчи — запасной вариант для случаев, которых нельзя избежать, а не основной план.

Сначала проверьте официальный API или фид

Многие сайты, которые парсят, уже предлагают способ получить те же данные без капчи: публичный API, экспорт данных, RSS- или sitemap-фид либо партнёрскую программу. Официальный источник надёжнее, реже меняется без предупреждения и даёт владельцу сайта право голоса в том, как вы его используете. Ищите:

Если один из этих вариантов покрывает вашу задачу, используйте его. Большинства капч удастся избежать, если вообще не запрашивать HTML.

Уважайте robots.txt и заданную в нём паузу

robots.txt говорит, какие пути автоматические клиенты могут запрашивать и иногда сколько ждать между запросами. Стандартная библиотека Python может прочитать его за вас:

import time
from urllib.robotparser import RobotFileParser
import requests

USER_AGENT = "ExampleBot/1.0 (+https://example.com/bot)"

parser = RobotFileParser()
parser.set_url("https://example.com/robots.txt")
parser.read()

delay = parser.crawl_delay(USER_AGENT) or 5  # если не задано, берём осторожные 5 секунд
urls = [
    "https://example.com/products?page=1",
    "https://example.com/products?page=2",
]

last_request = 0.0
for url in urls:
    if not parser.can_fetch(USER_AGENT, url):
        print("skipped by robots.txt:", url)
        continue
    wait = delay - (time.monotonic() - last_request)
    if wait > 0:
        time.sleep(wait)
    resp = requests.get(url, headers={"User-Agent": USER_AGENT}, timeout=30)
    last_request = time.monotonic()
    print(url, resp.status_code)

Если robots.txt запрещает путь, честный ответ — не трогать его или спросить владельца. Обход этого запрета через браузер ничего не меняет в том, о чём просил сайт.

Замедляйтесь и распределяйте запросы

Ровный умеренный темп редко вызывает проверку, а всплеск почти всегда её вызывает. Несколько привычек дают большую разницу:

Кешируйте и не загружайте повторно

Каждый запрос, который вы не сделали, — это запрос, который сайту не нужно обработать. Сохраняйте загруженные страницы вместе с датой и хешем тела и запрашивайте их снова только тогда, когда содержимое, вероятно, изменилось. Условные запросы с заголовками If-Modified-Since или ETag позволяют серверу дешёво ответить «не изменилось», если он это поддерживает.

Переиспользуйте сессии и отправляйте обычные заголовки

Сессия, которая сохраняет cookie между запросами, ведёт себя больше как посетитель, чем скрипт, который каждый раз стартует с нуля. Используйте requests.Session() для каждого сайта и отправляйте понятный, честный User-Agent с названием вашего бота и контактом. Не выдавайте себя за браузер, чтобы обойти правило. Если сайту нужен JavaScript для показа контента, используйте инструмент на базе браузера для этих страниц и соблюдайте те же лимиты частоты.

Когда капча всё же появляется

Некоторые сайты покажут капчу, как бы аккуратно вы ни работали. Определите её в коде и остановите задачу, а не долбите страницу. Обнаружение и опциональное решение для PopularCaptcha описаны в гайде капча при парсинге.

Спланируйте обход до старта

Обход, который каждый день загружает всё подряд, — самый простой способ вызвать капчу. Сначала спланируйте работу:

Такой план снижает число запросов, а это самый большой рычаг, который у вас есть.

Запишите план в виде короткого конфиг-файла или таблицы: сайты, разделы, интервал обновления и дневной бюджет запросов для каждого. Когда бюджет исчерпан, задача ждёт следующего окна. Относиться к бюджету как к жёсткому лимиту, а не как к рекомендации — это то, что не даёт краулеру уйти в паттерн трафика, который и вызывает капчу. Пересматривайте бюджет каждые несколько недель: сайт растёт, и его трафик тоже может вырасти, а то, что было деликатным в прошлом квартале, сейчас может таким не быть.

Парсите ответственно

Что дальше