Все статьи

· Casimiro Ferreira· 3 мин чтения

Robots.txt, карты сайта и этичный веб-скрапинг

  • Web Scraping
  • Sitemaps
  • Ethics
  • Robots.txt
  • Data Collection
  • FOSS

Начните с разведки, а не с грубой силы

Худшие скраперы обходят сайт вслепую. Они молотят по сайту, игнорируют объявления crawl-delay, перебирают все пути в поисках данных и ломаются, когда структура меняется на имя одного-единственного класса. Лучшие скраперы начинают с чтения сайта.

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

  1. Можно ли скрапить этот сайт? Что разрешает robots.txt и в каком темпе?
  2. Где данные? Что раскрывают карты сайта?
  3. Как устроен сайт? Как выглядит топология ссылок?

Именно это и делает sitemapper.

Пассивное обнаружение: robots.txt + карты сайта

discover() получает robots.txt и все карты сайта, которые может найти, — включая директивы Sitemap:, индексы карт сайта, указывающие на подкарты, и сжатые gzip-файлы — не обходя ни одной HTML-страницы:

from sitemapper import discover

info = discover("https://www.python.org")
print(info.summary())
# Base URL:       https://www.python.org
# Blocked:        False
# Sitemaps found: 1
# URLs in sitemaps: 342
# Crawl-delay:    None
# Sitemap directives in robots.txt: 1

# What pace does the site ask for?
if info.robots.crawl_delay:
    print(f"Wait {info.robots.crawl_delay}s between requests")

# May I fetch this path?
info.robots.is_allowed("/api/users")            # True / False
info.robots.is_allowed("/admin", user_agent="MyBot/1.0")

# Every deduplicated URL the site's own sitemaps declare
for url in info.urls:
    print(url.loc, url.lastmod, url.changefreq, url.priority)

Детализация по агентам есть, когда она вам нужна: info.robots.groups содержит каждый блок User-agent с его allows, disallows и crawl_delay, в порядке следования в документе. Если у сайта вообще нет robots.txt, is_allowed() возвращает True для всего — отсутствие политики само по себе является политикой.

Выигрыш от скрапинга, ориентированного на карты сайта: вместо обнаружения URL через обход (медленно, шумно, неполно) вы отталкиваетесь от собственного списка сопровождающих. Вы скрапите то, что сайт объявляет важным, в темпе, который он объявляет приемлемым, за долю от числа запросов.

Активное обнаружение: граф ссылок

Некоторые сайты не публикуют карту сайта. Для них crawl() выполняет ограниченный обход в ширину от базового URL и возвращает LinkGraph внутренних страниц и исходящих ссылок:

from sitemapper import crawl

graph = crawl("https://example.com", max_pages=50, max_depth=2)
print(graph.summary())
# Pages crawled (internal): 50
# External URLs seen: 87
# Top external domains: ...

Это сообщает вам реальную топологию — какие страницы на что ссылаются, — чтобы вы могли решить, стоит ли сайт вообще структурированного скрапера. Обнаружение и обход намеренно разделены на отдельные вызовы: пассивный шаг никогда не получает HTML, поэтому вы всегда можете вежливо провести разведку, прежде чем решить обходить сайт.

Построено на том же устойчивом транспорте

Разведка сайта бесполезна, если саму разведку блокируют анти-бот-стены. Весь HTTP sitemapper идёт через unblock_requests — транспорт с имитацией TLS из нашего материала об анти-бот-транспорте — поэтому robots.txt и карты сайта возвращаются даже на сайтах, защищённых Cloudflare. Экземпляр FlareSolverr или откат к Wayback Machine можно включить переменными окружения (SITEMAPPER_FLARESOLVERR_URL, SITEMAPPER_WAYBACK_FALLBACK=1) или через класс Sitemapper.

Почему это важно

Crawl-delay: сайт, который объявляет Crawl-delay: 2, сообщает вам, с какой скоростью он хочет, чтобы к нему обращались. Проигнорируете — и вас заблокируют, или вы ухудшите работу сайта для всех. Соблюдёте — и ваш скрапер играет честно.

Карты сайта вместо обхода: карта сайта перечисляет то, что сайт хочет проиндексировать. Слепой обход ссылок может затронуть в пять раз больше URL, чтобы найти то же самое содержимое. Начинайте с карты сайта, когда она есть; это быстрее для вас и легче для сервера.

Определите охват до кода: некоторые сайты прямо запрещают скрапинг в robots.txt; у других есть карты сайта, которые уже содержат всё, что вам нужно. Десять секунд discover() подскажут, в какой из ситуаций вы находитесь, прежде чем вы вложитесь в парсер.

Инструмент

pip install sitemapper
pip install sitemapper[stealth]   # adds curl_cffi TLS impersonation

Используйте его как библиотеку или из командной строки — --json FILE записывает полное обнаружение в файл для потребления другими инструментами, --crawl добавляет шаг с графом ссылок:

python -m sitemapper https://example.com
python -m sitemapper https://example.com --crawl --max-pages 50 --json out.json

Это свободное программное обеспечение, и оно работает на вашем собственном оборудовании. Начинайте каждый скрапер с разведки.