Парсинг сайтов на Python: Playwright, ретраи, дедупликация
Какой стек выбрать под задачу, как писать селекторы, которые переживают правки вёрстки, как устроены ретраи и почему дедупликация нужна с самого начала.
Все статьи гида Парсинг данных · 11
Разница между работающим один раз скриптом и парсером, который работает месяцами, - не в библиотеках. Она в обработке того, что идёт не по плану.
Выбор стека
Порядок проверки, экономящий недели:
1. Есть ли API. Иногда есть недокументированный: посмотрите, какие фоновые запросы делает страница. Часто данные приходят готовой структурой, и разбирать разметку не нужно вовсе. Это лучший из возможных сценариев.
2. Есть ли данные в исходном ответе. Запросите страницу обычным HTTP-запросом и посмотрите, есть ли в ней нужное. Если есть - берите связку HTTP-клиента и разборщика разметки. Быстро, дёшево, легко параллелится.
3. Только если данных нет - управление настоящим браузером. Дороже в десятки раз по ресурсам и времени.
Практика показывает: браузер нужен реже, чем к нему прибегают. Проверка занимает пять минут и часто экономит основную часть работы.
Селекторы, которые переживают правки
Вёрстка меняется, и это главная причина поломок.
Опирайтесь на смысл, а не на положение. Атрибуты с осмысленными именами и текстовые метки живут дольше, чем длинные пути по дереву и автоматически сгенерированные имена классов.
Не привязывайтесь к порядку. Третий блок в списке перестанет быть третьим при первом же изменении.
Ищите от устойчивого якоря. Найдите контейнер карточки товара по осмысленному признаку и дальше ищите внутри него.
Проверяйте, что нашли. Пустой результат должен быть явной ошибкой, а не пустой строкой в выгрузке. Парсер, молча собравший тысячу пустых записей, хуже упавшего: об упавшем вы узнаете сразу.
Полезная привычка: отдельная проверка структуры. Небольшой набор эталонных страниц и проверка, что все обязательные поля находятся. Запускается перед основным сбором и ловит изменение вёрстки до того, как вы соберёте мусор.
Ретраи
Сеть ненадёжна, сайты отвечают ошибками, соединения обрываются. Без ретраев парсер не переживёт и часа.
Что важно:
Различайте типы ошибок. Таймаут и временная ошибка сервера повторяются. Ошибка «страница не найдена» - нет: повтор даст тот же результат.
Нарастающая задержка. Повторять сразу означает добить сайт, который и так отвечает плохо.
Ограничение попыток. Иначе один проблемный адрес заберёт всё время.
Повтор с другого адреса, если работаете через прокси: тот же адрес, скорее всего, снова получит отказ - см. ротацию.
Отдельная обработка блокировки. Если вместо данных пришла проверка, повторять бессмысленно - надо менять условия сбора.
Дедупликация и сохранение прогресса
Две вещи, которые кажутся необязательными и становятся критичными на объёме.
Дедупликация. Одна и та же запись приходит несколько раз: пагинация пересекается, ретраи повторяют страницы, возобновление начинается с середины.
Нужен устойчивый ключ: артикул, идентификатор из адреса страницы, штрихкод. Название и цена ключом быть не могут - они меняются. Проверка на существование по ключу перед записью решает проблему целиком.
Сохранение прогресса. Сбор десяти тысяч страниц однажды прервётся: сеть, ошибка, перезапуск. Без сохранения прогресса вы начинаете заново.
Практически: отмечайте обработанные страницы, чтобы возобновление продолжало с места остановки. Это же даёт возможность запускать сбор порциями вместо одного длинного прогона.
Что ещё стоит сделать сразу
- Ограничить темп. Пауза между запросами - и вежливость, и способ не попасть под ограничение.
- Логировать адрес и результат для каждой страницы. Без этого разбор невозможен.
- Проверять данные на выходе. Цена как строка, отрицательное количество, дата из будущего - признаки того, что разбор сломался.
- Сохранять сырой ответ при ошибке разбора. Через день вы не воспроизведёте страницу, на которой упало.
Как выгружать результат - в Excel. Готовые инструменты без кода - программы для парсинга. Обзор - гид по парсингу.
Вопросы и ответы
Что использовать для парсинга на Python?
Для страниц, где данные есть в исходном ответе, - обычные HTTP-запросы с разбором разметки: быстро и дёшево. Для страниц, где содержимое дорисовывается скриптами, - управление настоящим браузером. Проверять надо в этом порядке: браузер нужен реже, чем кажется.
Почему парсер работает и собирает пустые данные?
Потому что селектор не нашёл элемент, а код обработал это как отсутствие значения. Парсер должен различать «поля нет на странице» и «поле пустое»: первое - сбой, требующий внимания, второе - валидные данные. Без этого вы получите тысячи пустых строк и узнаете об этом поздно.
Зачем нужна дедупликация при парсинге?
Потому что одна и та же запись приходит несколько раз: пагинация пересекается, ретраи повторяют страницы, запуск возобновляется с середины. Без устойчивого ключа и проверки на существование вы получите дубликаты, которые потом придётся чистить руками.
Ещё по теме
- Парсинг данных с сайта: как это устроеноГид
- Парсинг сайтов конкурентов: что можно собирать и зачемКакие данные о конкурентах имеет смысл собирать, как построить регулярный мониторинг, что делать с расхождениями и где проходит граница допустимого.
- Защита от парсинга сайта: что работает, а что нетКакие меры защиты от автоматического сбора действительно работают, какие только мешают пользователям, и как выбрать уровень защиты под свою ситуацию.
- Парсинг товаров с сайта: цены, остатки, карточкиКак собирать карточки товаров, почему цена - самое ненадёжное поле, как сопоставлять товары между источниками и что проверять в собранных данных.
Сделаю под ключ
Соберу парсер под ваш источник
С обходом защиты, прокси и выгрузкой в таблицу, базу или Telegram. Работает по расписанию без вас.
от 300 $ · 3-7 дней
«Очень быстрый парсинг, спасибо большое! Даже получилось чуть больше номеров, всем рекомендую! Делал заказ 2 раза, всё устраивает, буду обращаться ещё.»