parse(html)
.select()
Учебное руководство по Python

Парсинг HTML на Pythonруководство по библиотекам 2025

Сравнение практических компромиссов Beautiful Soup, lxml, html5lib и PyQuery в задачах веб-скрапинга и сбора данных. Включая масштабируемые паттерны, стратегии работы с прокси и гигиену сессий.Для тех, кто занимается данными, скрапингом и сбором информации, - как выбрать парсер и как гарантировать, что полученный HTML будет чистым и стабильным.

30 октября 2025 г.
Чтение 15 минут

Техническое резюме

Beautiful Soup 4 с бэкендом lxml - выбор по умолчанию для большинства команд в последние пару лет. Хорошая устойчивость к ошибкам, быстрый в написании API, знаком практически всем. Производительность в основном определяется бэкендом - lxml самый быстрый.

lxml силён скоростью, поддержкой XPath 1.0 и CSS-селекторов (через cssselect). iterparse позволяет вести событийно-ориентированный разбор XML, а вот возможности потоковой обработки HTML ограничены.

html5lib - это чистый Python-парсер, который разбирает HTML строго по спецификации HTML5, ровно как браузер. Предназначен специально для работы с особенно ужасной вёрсткой, но по своей конструкции медленный.

html.parser входит в стандартную библиотеку Python. Его плюс - отсутствие зависимостей: в ограниченных окружениях он без проблем обрабатывает чистый HTML, но функций у него меньше, чем у lxml и Beautiful Soup.

PyQuery надстраивает над lxml слой jQuery-подобных селекторов. Подойдёт командам с сильной привычкой к мышлению в стиле jQuery, но экосистема у него меньше, чем у Beautiful Soup.

Главное: скорость парсинга редко становится решающим фактором успеха. На практике гораздо важнее обработка кодировки, устойчивость селекторов и гигиена сессий (ограничение частоты запросов, заголовки, отпечаток TLS) - именно эти вещи.

1) Какую задачу реально решают современные парсеры

Если говорить просто, веб-страница - это древовидная структура, обёрнутая в HTML. Парсер превращает исходную строку HTML в дерево, по которому можно перемещаться, чтобы выбирать элементы - цену товара, заголовок, ссылки пагинации - без кучи хрупких регулярных выражений.

Хороший парсер изящно справляется с несовершенной разметкой. Незакрытые теги, несовпадающая вложенность, проблемы с кодировкой символов - всё это ему по силам. Вы просто извлекаете нужное содержимое и не задумываетесь о том, как выжить в кривом HTML.

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

2) Быстрый выбор (шпаргалка)

По умолчанию: Beautiful Soup 4 с бэкендом lxml

Хорошая устойчивость к ошибкам, быстро писать, знаком всем. Скорость обеспечивается лежащим в основе lxml.

Нужен XPath: сразу берите lxml

Есть XPath 1.0, CSS-селекторы (cssselect) и событийно-ориентированный разбор XML (iterparse).

Особенно кривой HTML: html5lib

Разбирает по спецификации HTML5, ровно как браузер. Медленный, но справляется с особенно кривой разметкой. Используйте, только когда страница действительно ужасна, - по умолчанию не берите.

Ограниченное окружение: html.parser (стандартная библиотека)

Ценен лишь тем, что не требует зависимостей, - но не самый удобный. С чистым HTML справляется без проблем.

Команда привыкла к jQuery: PyQuery

Надстраивает над lxml jQuery-подобные селекторы. Если у вашей команды сильна привычка мыслить в стиле jQuery - подойдёт, иначе специально брать не стоит.

3) Сценарии из реальной практики

На практике при сборе данных команды в основном используют Python-парсеры HTML для следующих задач:

  • Мониторинг цен и наличия: отслеживание страниц товаров, SKU и показателей запасов для конкурентной разведки.
  • Массовый SEO-аудит: извлечение заголовков, meta-тегов, внутренних ссылок и canonical-тегов из тысяч URL для поиска возможностей оптимизации.
  • Агрегация новостей и разведданных: сбор заголовков, авторов и меток времени с новостных сайтов для мониторинга и оповещений.
  • Формирование исследовательских наборов данных: построение текстовых корпусов для анализа из HTML-списков статей, нормативных актов и научных баз.
  • QA рекламы и партнёрских программ: проверка рекламных тегов и их размещения; масштабное выявление отвалившихся партнёрских параметров на сайтах партнёров.
  • Мониторинг соответствия и бренда: сбор дисклеймеров, уведомлений о cookie и упоминаний бренда по доменам партнёров для обеспечения соответствия требованиям.
  • Нормализация скрапинга товарных категорий: приведение разнородных карточек списков с сайтов вакансий, недвижимости и автомобилей к единой схеме.

Все эти сценарии требуют устойчивых селекторов, корректной обработки кодировки и ответственного поведения при скрапинге.

4) Углублённо: сравнение библиотек

Beautiful Soup 4 (bs4)

Позиционирование: дружелюбная обёртка, которая может использовать в качестве бэкенда lxml, html.parser или html5lib. Предоставляет CSS-селекторы через метод select.

Когда использовать: когда нужно быстро получить результат на реальном хаотичном HTML при низком пороге входа. Команда ценит читаемость кода, а не предельную скорость.

Компромисс: это тонкая абстракция поверх лежащего в основе парсера. Поведение и производительность зависят от выбранного вами бэкенда.

lxml (etree/html)

Позиционирование: Python-привязки к libxml2 и libxslt. Поддерживает XPath 1.0, CSS-селекторы (cssselect) и событийно-ориентированный разбор XML (iterparse).

Когда использовать: когда нужен XPath для сложных запросов, требуется максимальная скорость либо вы обрабатываете большие XML-ленты и хотите снизить потребление памяти.

Компромисс: требует установки C-расширения, что в некоторых окружениях (например, AWS Lambda) требует внимания при сборке и развёртывании. Терпимость к кривому HTML ниже, чем у связки Beautiful Soup + html5lib.

html.parser (стандартная библиотека)

Позиционирование: чистый Python-парсер HTML, входящий в стандартную библиотеку Python. Beautiful Soup может использовать его как бэкенд.

Когда использовать: в заблокированном окружении, где нельзя выполнить pip, либо в простых скриптах, где нужны нулевые внешние зависимости.

Компромисс: медленнее lxml, ниже терпимость к некорректно оформленной разметке. Меньше функций для сложных задач извлечения.

html5lib

Позиционирование: чистый Python-парсер, полностью реализующий спецификацию HTML5. Формирует дерево разбора точно такое же, как у браузера.

Когда использовать: при работе с действительно ужасным HTML - незакрытые теги, несовпадающая вложенность, выдача CMS десятилетней давности, - когда нужен разбор с точностью, как у браузера.

Компромисс: по своей конструкции намного медленнее lxml. Нет ускорения на C. Держите его для случаев, когда все остальные парсеры не справляются.

PyQuery

Позиционирование: jQuery-подобная обёртка поверх lxml. Позволяет писать привычные селекторы, не изучая XPath или API lxml.

Когда использовать: когда команда уже хорошо знакома с jQuery и всё равно работает поверх lxml.

Компромисс: по сравнению с Beautiful Soup сообщество меньше, документация беднее. Добавляется ещё один слой абстракции, который нужно понимать.

5) Масштабируемые паттерны

Предпочитайте CSS-селекторы, при необходимости откатывайтесь к XPath

CSS-селекторы вроде div.product > span.price читаемы и справляются с большинством задач извлечения. Когда вам нужно подниматься вверх по дереву, проверять несколько условий или использовать сложные предикаты, применяйте XPath.

Нормализуйте ввод перед разбором

Многие сайты указывают неверную кодировку в Content-Type, поэтому проверяйте и переопределяйте кодировку ответа, опираясь на фактическое содержимое. Перед разбором нормализуйте пробелы и HTML-сущности, чтобы избежать ошибок извлечения ниже по конвейеру.

Используйте устойчивые селекторы

Избегайте хрупких позиционных селекторов вроде nth-child(3), которые ломаются при малейшем изменении структуры страницы. Ориентируйтесь на устойчивые class или ID. Добавьте зонд или оповещение, чтобы при пустом результате select фиксировать это в журнале, а не обнаруживать проблему, когда хранилище уже забито пустыми данными.

Мыслите записями, а не страницами

Определяйте контейнерные элементы, содержащие повторяющиеся сущности - карточки товаров, строки статей, блоки списков. Извлекайте все поля каждого элемента в словарь. Проверяйте данные сразу же, чтобы уловить изменения структуры до того, как некорректные данные попадут в конвейер.

Контролируйте извлечение и оповещайте при сбоях

Быстро завершайте работу с ошибкой, когда отсутствуют обязательные поля. Выводите ошибки разбора в систему мониторинга. Тихие сбои извлечения со временем ухудшают качество данных.

6) Антипаттерны, которых стоит избегать

Разбор структуры DOM регулярными выражениями

Не используйте регулярные выражения для разбора структуры HTML. Для навигации применяйте селекторы по дереву. Применять регулярные выражения после извлечения для очистки полученного текста - удалить символы валют, нормализовать пробелы и тому подобное - вполне допустимо.

Жёстко заданные таймеры ожидания

Замените жёстко заданные задержки между запросами экспоненциальной выдержкой с джиттером. Когда платформа присылает заголовок Retry-After, соблюдайте его. Фиксированные паузы тратят время на быстрых эндпоинтах и приводят к сбоям на медленных.

Один парсер на все случаи

Подбирайте парсер под источник. Для чистых, структурированных страниц используйте lxml. Для сайтов с поломанной разметкой переключайтесь на Beautiful Soup с html5lib. Анализируйте свои документы и выбирайте соответственно.

Игнорирование кодировки символов

Никогда не предполагайте, что это UTF-8. Проверяйте кодировку ответа из HTTP-библиотеки, а если заголовок Content-Type сервера указан неверно, переопределяйте её вручную, не доверяя заголовкам слепо. Фиксируйте несовпадения кодировки в журнале, чтобы обнаруживать проблемы заранее.

7) Производительность, память и параллелизм: на что обратить внимание

Сначала измеряйте, потом оптимизируйте

В веб-скрапинге основное время обычно занимают сетевая задержка и защита от ботов. Время разбора чаще всего пренебрежимо мало. Прежде чем микрооптимизировать выбор парсера, профилируйте свою реальную нагрузку.

Потоковая обработка больших XML-лент

Используйте iterparse из lxml для инкрементальной обработки гигантских XML-дампов. Это снижает пики памяти за счёт обработки элементов по мере их поступления. Возможности настоящей потоковой обработки HTML ограничены - большинство HTML-ответов достаточно малы, чтобы разбирать их в памяти.

Ограничение по вводу-выводу против ограничения по CPU

GIL в Python не блокирует операции ввода-вывода. Используйте ThreadPoolExecutor для параллельных HTTP-запросов - разбор остаётся достаточно быстрым. Переходите к многопроцессности только тогда, когда профилирование докажет, что в вашей нагрузке разбор ограничен CPU.

Кэшируйте скомпилированные селекторы

Предварительно компилируйте часто используемые XPath-выражения в lxml и переиспользуйте их. Централизуйте логику селекторов, а не разбрасывайте её по кодовой базе. Это повышает и производительность, и удобство сопровождения.

8) Прокси, ротация и гигиена сессий

Этот раздел прежде всего о том, что парсер имеет смысл лишь после того, как вы успешно получили HTML. Чтобы получать надёжные ответы, нужно понимать, как платформы обнаруживают и блокируют автоматизированный трафик.

Репутация IP и CGNAT

NAT операторского уровня означает, что тысячи реальных мобильных пользователей делят один публичный IP-адрес. Системы защиты от парсинга знают этот паттерн и могут соответствующим образом корректировать репутационную оценку.

IP-адреса мобильных операторов способны раствориться в массе реальных пользователей, но обращаются с ними разные платформы очень по-разному. Не думайте, что мобильный IP обходит любое обнаружение.

Сигналы помимо IP

Сегодня платформы смотрят не только на IP, но и на множество характеристик запроса: отпечаток TLS (JA3/JA4), форму заголовков, ритм, сигналы согласованности. Не сообщайте с мобильного IP информацию о браузере с явно десктопным User-Agent - платформы соотносят UA с типом IP и разрешением экрана, и всё должно рассказывать одну и ту же историю.

Сохраняйте единый отпечаток TLS в рамках сессии. Смена версии OpenSSL или набора шифров посреди сессии помечает вас как инструмент автоматизации.

Стратегия ротации

  • Ротацию лучше привязывать к событиям, а не чисто ко времени, - меняйте IP после входа в систему, оформления заказа или иных операций повышенного риска.
  • В рамках всей логической сессии сохраняйте один и тот же IP: просмотр, добавление в корзину, оформление. Смена IP посреди сессии выглядит как поведение бота.
  • Добавляйте джиттер к интервалам между запросами, случайный в диапазоне 2-10 секунд. Жёстко заданные паузы порождают обнаруживаемый паттерн.

Соответствие требованиям и границы

  • robots.txt (протокол исключения роботов) выражает предпочтения сайта относительно скрапинга. Это не механизм безопасности, но соблюдать его - проявление добросовестности. Условия использования нужно соблюдать - это договорное обязательство.
  • Скрапьте только публичные страницы: сбор содержимого закрытых разделов или из-за платного доступа без разрешения - это несанкционированный доступ.
  • Разумно ограничивайте частоту: возможность отправлять 1000 запросов в секунду не означает, что так следует делать. Соблюдайте заголовок Retry-After, применяйте выдержку при ошибках и кэшируйте, где это возможно, чтобы снизить нагрузку.
  • Региональное соответствие: конкретика зависит от требований соответствия в вашей отрасли и регионе, здесь приведены лишь общие практики.

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

9) Где взять код

Это руководство сосредоточено на концепциях, компромиссах и паттернах, а не на конкретной реализации. Когда вам понадобится конкретный код, адаптированный под структуру целевой страницы, используйте инструменты для написания кода ChatGPT или Claude.

Попросите этих AI-ассистентов сгенерировать селекторы Beautiful Soup, XPath-запросы lxml или полный скрипт извлечения, подогнанный под ваш HTML. Они могут выдать рабочие примеры с должной обработкой ошибок и управлением кодировкой под ваши конкретные требования.

Такой подход даёт вам свежий, протестированный код, соответствующий текущим версиям библиотек, вместо копирования статических фрагментов, которые могли устареть.

10) Итог

По умолчанию начинайте с Beautiful Soup и бэкенда lxml. Читаемый API, неплохая производительность, без проблем справляется с большей частью реального HTML.

Если нужен XPath для сложных запросов или обработка больших XML-лент (потоковая обработка через iterparse снижает потребление памяти), берите lxml напрямую.

Держите html5lib наготове для тех 5% действительно ужасных HTML-источников, когда точность разбора, как у браузера, важнее скорости.

html.parser используйте только тогда, когда ограничения развёртывания вынуждают обходиться лишь стандартной библиотекой без внешних зависимостей.

Главное: самые трудные проблемы в реальном скрапинге - это устойчивость селекторов, обработка кодировки символов и гигиена сессий, а не сам парсер. Поэтому сначала обеспечьте, чтобы получаемый HTML был чистым и стабильным, и лишь потом ломайте голову над тем, какой именно парсер использовать.

Источники

Документация Beautiful Soup - бэкенды парсеров, CSS-селекторы, навигация по тегам
https://www.crummy.com/software/BeautifulSoup/bs4/doc/
Документация lxml - разбор HTML/XML, XPath 1.0, потоковая обработка iterparse
https://lxml.de/ и https://lxml.de/parsing.html
Документация html5lib - алгоритм разбора HTML5, соответствие спецификации
https://html5lib.readthedocs.io/
Python html.parser - парсер HTML из стандартной библиотеки
https://docs.python.org/3/library/html.parser.html
Python Requests - определение и обработка кодировки символов
https://requests.readthedocs.io/
Документация PyQuery - jQuery-подобные селекторы поверх lxml
https://pyquery.readthedocs.io/
Google Search Central - основы robots.txt и протокол исключения роботов
https://developers.google.com/search/docs/crawling-indexing/robots/intro
Документация для разработчиков Cloudflare - сигналы обнаружения ботов, определение отпечатка TLS (JA3/JA4), контекст CGNAT
https://developers.cloudflare.com/ и https://blog.cloudflare.com/

Хотите, чтобы парсер получал чистый и стабильный HTML?

Попробуйте наши мобильные прокси - IP-адреса операторского уровня, таргетинг по городам, управление сессиями, чтобы парсер получал чистый HTML.

Нужна консультация по решению? Мы поможем спроектировать архитектуру прокси для масштабного скрапинга, стратегию ротации, настройку заголовков и паттерны гигиены сессий под ваш технологический стек.