Парсинг на Python без блокировок: законно и по правилам
Как собирать данные с сайтов на Python, не нарушая закон и не выжигая чужой сервер: robots.txt, rate limiting, легальные источники и разбор частых заблуждений про «обход защиты».

Вы написали парсер на requests, запустили в 50 потоков — и через минуту получаете 429 Too Many Requests, а потом и 403 на весь диапазон IP. Первое желание — подключить пул прокси и менять User-Agent на каждый запрос. Это ведёт в две стороны сразу: технически хрупко (защиты умнеют быстрее ваших обходов) и юридически мутно. Разберём, где проходит граница между легальным сбором данных и тем, за что можно получить претензию, и как настроить парсер, который не блокируют, потому что он ведёт себя прилично.
Материал — про практику сбора публичных данных на Python (актуально для requests и httpx, версии 2024–2025 годов). Мы сознательно не разбираем обход капчи, антибот-систем и авторизации: это ровно та зона, где «этично и законно» заканчивается.
Что вообще считается нарушением
Технический факт: HTTP-запрос к публичной странице ничем не отличается от того, что делает браузер. Проблема возникает не от самого запроса, а от того, что и как вы делаете с результатом и с сервером.
- Нагрузка. Тысячи запросов в секунду с одного источника — это уже не «чтение сайта», а фактически мини-DDoS. Здесь вопрос не только этики, но и возможной ответственности за нарушение работы информационной системы.
- Обход технических средств защиты. Если сайт закрыл данные авторизацией, капчей или платным доступом, а вы это обходите — вы преодолеваете защиту. Это принципиально другая история, чем чтение открытой страницы.
- Персональные данные. Собирать ФИО, телефоны, адреса и раскладывать их в свою базу — отдельно регулируемая деятельность. Публичность данных на чужом сайте не делает вас законным оператором.
- Авторские права и условия использования. Тексты, фото, структурированные базы данных охраняются. Пользовательское соглашение сайта может прямо запрещать автоматический сбор.
Точные квалификации и статьи (по составам о неправомерном доступе к информации, о персональных данных, об авторском праве) зависят от юрисдикции, характера данных и объёма — это вопрос к юристу, а не к парсеру. Здесь важно инженерное следствие: чем меньше вы похожи на атаку и чем публичнее данные, тем спокойнее вы спите.
Хороший парсер не «обходит» сервер. Он не создаёт ему проблем настолько, что обходить нечего.
Первый шаг: robots.txt и Crawl-delay
Перед тем как отправить первый запрос, прочитайте robots.txt сайта. Это не закон, но публично заявленная воля владельца о том, какие разделы он не хочет отдавать роботам. Игнорировать её — плохой сигнал и на суде, и для собственной совести.
В стандартной библиотеке Python есть urllib.robotparser, который умеет разбирать файл и проверять доступность пути.
from urllib.robotparser import RobotFileParser
# robotparser входит в стандартную библиотеку, Python 3.x
robots = RobotFileParser()
robots.set_url("https://example.com/robots.txt")
robots.read()
user_agent = "MyResearchBot/1.0"
target = "https://example.com/catalog/page/2"
if robots.can_fetch(user_agent, target):
print("Разрешено правилами robots.txt")
else:
print("Владелец просит не парсить этот раздел")
# crawl_delay возвращает рекомендованную паузу в секундах или None
delay = robots.crawl_delay(user_agent)
print("Рекомендованная пауза:", delay)
Если can_fetch вернул False — это не «непреодолимая стена», а явный отказ. Продолжать против воли владельца — уже осознанное решение, за которое отвечаете вы.
Как не получить 429: вежливый темп вместо прокси-пула
Большинство блокировок — реакция на скорость, а не на факт парсинга. Сервер видит десятки запросов в секунду с одного адреса и включает защиту. Решение не в том, чтобы прятать адрес, а в том, чтобы снизить темп до человеческого.
Базовый rate limiting
Самый простой рабочий приём — пауза между запросами плюс честный User-Agent с контактом. Так владелец сайта при желании может написать вам, а не банить вслепую.
import time
import httpx # httpx 0.27.x
HEADERS = {
# честно называем себя и оставляем контакт
"User-Agent": "MyResearchBot/1.0 (+https://myproject.example/contact)"
}
urls = [
"https://example.com/catalog/page/1",
"https://example.com/catalog/page/2",
]
# минимальная пауза между запросами, секунды
MIN_DELAY = 1.5
with httpx.Client(headers=HEADERS, timeout=10.0) as client:
for url in urls:
response = client.get(url)
print(url, response.status_code)
time.sleep(MIN_DELAY)
Реакция на 429 и Retry-After
Правильный ответ на 429 — не «сменить IP», а притормозить. Сервер часто присылает заголовок Retry-After с числом секунд ожидания. Уважайте его.
import time
import httpx
def fetch_with_backoff(client, url, max_retries=4):
delay = 2.0 # стартовая пауза
for attempt in range(max_retries):
response = client.get(url)
if response.status_code == 429:
# если сервер указал точное время ожидания — берём его
retry_after = response.headers.get("Retry-After")
wait = float(retry_after) if retry_after and retry_after.isdigit() else delay
time.sleep(wait)
delay *= 2 # экспоненциальное увеличение на случай отсутствия заголовка
continue
return response
# исчерпали попытки — сдаёмся, а не долбим дальше
return None
Экспоненциальный backoff — это когда каждая следующая пауза вдвое длиннее предыдущей. Он снимает нагрузку с сервера в момент, когда тому и так тяжело.
Сначала API, потом HTML
Прежде чем парсить HTML, проверьте, нет ли у сайта официального API или машиночитаемых выгрузок. Это почти всегда законнее, стабильнее и быстрее — парсинг разметки ломается при первом же редизайне.
| Источник данных | Стабильность | Юридическая чистота | Когда выбирать |
|---|---|---|---|
| Официальный API с ключом | Высокая | Высокая (есть условия использования) | Всегда, если API отдаёт нужное |
| Открытые данные (data.gov, дампы) | Высокая | Высокая | Статистика, справочники, реестры |
| RSS / Sitemap | Средняя | Высокая | Мониторинг новых материалов |
| Парсинг HTML публичных страниц | Низкая | Зависит от данных и условий сайта | Когда других источников нет |
| Обход авторизации/капчи | — | Красная зона | Не делаем |
Многие сайты публикуют sitemap.xml — это готовый список URL, который избавляет от рекурсивного обхода и лишних запросов. Ищите ссылку на него внутри robots.txt (директива Sitemap:).
Кеширование: не запрашивайте одно и то же дважды
Самый недооценённый способ «не быть заблокированным» — вообще не делать лишних запросов. Если данные меняются раз в сутки, а вы дёргаете страницу каждый час, вы просто жжёте чужой трафик впустую.
Библиотека hishel добавляет HTTP-кеширование поверх httpx и уважает заголовки Cache-Control и ETag. Уточните актуальный синтаксис и имена классов в её документации для вашей версии — API молодой и может меняться. Как минимум используйте условные запросы: сохраняйте ETag из ответа и присылайте его в If-None-Match, чтобы получать 304 Not Modified вместо полного тела.
Когда что выбирать
- Есть API — берите API, даже если придётся регистрировать ключ и мириться с лимитами. Лимиты честнее, чем гадание, когда вас забанят.
- Данные публичны, API нет, robots.txt разрешает — парсите HTML с паузами и честным User-Agent. Держите темп ниже, чем позволяет ваша машина.
- robots.txt запрещает или нужна авторизация — остановитесь и спросите разрешения у владельца или откажитесь от источника. Это дешевле любого суда.
- Данные персональные — отдельно оцените правовые основания сбора, а не только техническую возможность.
Типичные ошибки, которые превращают парсер в проблему
- Параллельность без ограничения.
asyncioс сотней одновременных запросов к одному хосту — прямой путь к бану и к жалобе. Ограничивайте одновременные соединения на хост (например, через семафор). - Ретраи без backoff. Цикл «получил ошибку — сразу повторил» усиливает нагрузку в момент, когда серверу и так плохо.
- Игнор Retry-After. Сервер прямо сказал, сколько ждать, а парсер долбит дальше — это уже похоже на злой умысел.
- Подделка User-Agent под браузер и ротация IP. Технически иногда работает, но это осознанная маскировка обхода защиты — ровно тот сигнал, который на разборе трактуют не в вашу пользу.
Что сделать после запуска
Настройте базовую наблюдаемость: логируйте коды ответов и считайте долю 429 и 403. Их рост — сигнал снизить темп, а не увеличить агрессию. Заведите отдельный e-mail в User-Agent и проверяйте его: адекватный владелец сайта часто просто напишет с просьбой снизить нагрузку, и вопрос закроется без блокировок. И зафиксируйте письменно, откуда и зачем вы берёте данные — если проект вырастет, эта запись пригодится и юристу, и вам.
Инфобез и 152-ФЗ: Аудит политик конфиденциальности, правила сбора cookie.
Спросить за 20 ₽Источники: RFC 9309 — Robots Exclusion Protocol, HTTPX — official documentation
Частые вопросы
А если у меня httpx другой версии или вообще requests — код сработает?
Меня всё равно блокируют, хотя я ставлю паузы. Что не так?
Обязательно ли соблюдать robots.txt по закону?
Можно ли использовать прокси и менять User-Agent?
Данные на сайте публичные — значит, я могу собрать их в свою базу?
Как парсить, не создавая нагрузки на маленький сайт?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.