Привет, Хабр!
Меня зовут Вадим Москаленко и я разработчик инновационных технологий Страхового Дома ВСК. В этой статье хочу поделиться с вами информацией по проведенному сравнению производительности нескольких популярных библиотек для простого HTML-парсинга.
При необходимости сбора данных с HTML или XML, многим python-разработчикам сразу вспомнятся две популярные библиотеки «BeautifulSoup4» и «lxml» — они весьма удобны и стали широко применяемыми. Но что, если в нашем проекте важна скорость сбора данных? Возникает вопрос: кто из них быстрее и есть ли еще более быстрые библиотеки? При поиске данной информации на Хабре, я нашел подобные статьи, но им уже несколько лет. Так как прогресс не стоит на месте и появляются новые инструменты или те, о которых еще не слышали, мне было интересно провести личное исследование и поделиться информацией.
Ремарка: выбор библиотеки зависит от конкретных требований проекта, также существует еще множество инструментов, которые не были освещены в данной статье, к примеру «Scrapy» — это мощный асинхронный фреймворк. В исследовании акцентируется внимание на более простой задаче, поэтому я не гарантирую что лидер бенчмарка подойдет именно вам. Помните о важности проведения собственных тестов и анализа требований вашего проекта перед принятием решения.
В качестве задачи используем поисковик нашего любимого habr.com, в который отправим запрос с ключевыми словами «html parsing python» и соберем следующие данные по каждой статье: имя автора, заголовок, дату создания статьи, количество просмотров и голоса (оценки).
Участники
BeautifulSoup4, версия 4.12.2 (документация)
lxml, версия 4.9.3 (документация)
requests-html, версия 0.10.0 (документация)
parsel, версия 1.8.1 (документация)
selectolax, версия 3.17 (документация)
Python: 3.12.0
CPU: AMD Ryzen 7 3700X
Дополнительно протестируем разницу в применении парсеров «html» и «lxml» у BeautifulSoup4, использование «HTMLParser» или «LexborHTMLParser» у selectolax, разницу в применении поиска по CSS или XPath селекторам у requests-html, а также использование метода «find_class» у lxml, вместо привычного XPath.
Бенчмарк
Принцип работы скрипта: с помощью requests осуществляем запрос на получение страницы, сохраним content ответа и поочередно проведем парсинг различными методами, фиксируя время выполнения с помощью декоратора.
Запустим прогонный тест на парсинг первой страницы и при 1 раунде:
Результаты:
requests-html: несмотря на то, что использует «под капотом» BeautifulSoup, показывает наиболее худшие результаты. Если использовать XPath, вместо CSS результат улучшается примерно на 25%, на даже такой метод хуже варианта BeautifulSoup с использование парсера «lxml» 59,8 %
BeautifulSoup4: использование парсера «lxml», вместо «html.parser» ускоряет работу на 24,5%
lxml: использование метода поиска «find_class», хуже чем использование привычного XPath на 57,75%
selectolax: показывает лидерство
Запустим новый тест, в котором проведем парсинг по 10 страницам и с 10 раундами. Для информативности графика, исключим аутсайдера прошлого теста requests-html, результаты будут в таблице.
10 раундов - 10 страниц |
Среднее время отработки |
Медиана времени отработки |
selectolax lexbor |
0,01814754 |
0,0181863 |
selectolax html |
0,02385281 |
0,02380865 |
lxml parser xpath |
0,06488278 |
0,06480665 |
parsel xpath |
0,09614886 |
0,0957695 |
lxml find class |
0,17416978 |
0,17404505 |
bf4 lxml |
0,40552705 |
0,4089891 |
bf4 html |
0,53442332 |
0,5296515 |
requests-html xpath |
1,04187903 |
1,04476375 |
requests-html |
1,22853292 |
1,2294204 |
Результаты:
позиции участников никак не изменились
BeautifulSoup4: на дистанции, использование парсера «lxml», вместо «html.parser» ускоряет работу на 31,8%
lxml: на дистанции, использование метода поиска «find_class», хуже чем использование привычного XPath на 62,75%
selectolax: показывает лидерство, использование «LexborHTMLParser» быстрее, чем «HTMLParser» на 31,44 %
parsel: показывает средние результаты среди всех участников
Финальное тестирование: так как наш запрос, с ключевыми словами «html parsing python» выдает только 13 страниц, изменим его на «html» и получаем ограничение в 50 страниц поиска. Проведем парсинг всей информации с таким же количеством раундов. Для информативности графика, исключим аутсайдера прошлого теста BeautifulSoup4, результаты будут в таблице.
50 раундов - 50 страниц |
Среднее время отработки |
Медиана времени отработки |
selectolax lexbor |
0,08957974 |
0,08876955 |
selectolax html |
0,1192404 |
0,11853815 |
lxml parser xpath |
0,340518342 |
0,33733555 |
parsel xpath |
0,503992694 |
0,5000295 |
lxml find class |
0,931354268 |
0,92578665 |
bf4 lxml |
2,195235648 |
2,194097 |
bf4 html |
2,912655096 |
2,9080528 |
requests-html xpath |
5,63474603 |
5,6141935 |
requests-html |
6,595035754 |
6,5675001 |
Результаты и выводы:
-
используя selectolax с «LexborHTMLParser» вы получите информацию быстрее, по сравнению с:
selectolax с «HTMLParser» в 1,33 раза
lxml в 3,8 раза
parsel в 5,6 раза
BeautifulSoup4 в 24,5 раза
requests-html в 62,9 раза
-
используя lxml на XPath вы получите информацию быстрее, по сравнению с:
parsel в 1,5 раза
BeautifulSoup4 в 6,4 раза
requests-html в 16,5 раз
парсеры selectolax HTML и Lexbor невероятно быстры и является лидерами во всех тестах
парсер lxml используется и в BeautifulSoup4, и в parsel, но parsel превосходит BeautifulSoup4 с lxml «под капотом»
кроме selectolax, использующего CSS селекторы, во всех остальных случаях применение XPath (при поддержке) давало прирост скорости
Заключение
HTML-парсинг — важная часть работы с веб-данными, и выбор эффективной библиотеки может существенно повлиять на производительность. Надеюсь, данные в этой статье помогут вам сделать выбор или помогли его расширить.
Если вам понравилась подобная подача информации, возможно вас заинтересует: «Лучший формат данных для хранения pandas.DataFrame».
Весь проект бенчмарка: ссылка на GitHub
Чтобы оставаться в курсе всех IT-новостей Страхового Дома ВСК, подписывайся на наши социальные сети:
Сообщество VK: IT-ВСК
Блог на Хабр: Страховой Дом ВСК
YouTube-канал: ВСК Страховой Дом
Sazonov
А сравнения по скорости и памяти с RapidXML можно?
V-Moskalenko Автор
Добрый день! Библиотека на Python очень давно не обновлялась и нужно подготовить хорошие XML-кейсы для бенчмарка, как найду на это время - обязательно отпишусь
Sazonov
Ну часто обновлять то что работает не обязательно. Просто в целом, RapidXml на си очень быстрый. И если у вас парсинг является узким местом, то возможно нужно вынести этот код из питона?