Pull to refresh

Html парсер на Python или моя первая программа

Привет, хабр!

Так получилось, что поступление в университет пришлось отложить на год, и все свободное время я уделяю программированию (в основном на Python).

И в один прекрасный день мне пригодился html парсер. Я набрел на Beautiful Soup и Lxml. Посмотрел документацию, исходный код, и понял, что они мне совершенно не нравятся. Такое случилось со мной первый раз, обычно находился хотя бы один удовлетворяющий вариант. Поразмышляв, я решил написать свой.

Для ленивых, сразу ссылка на исходники: github.com/rrr3371/Rarara

Так почему же я решил писать велосипед?

  • Мне нужно было набраться опыта, ведь это стало бы моей первой законченной библиотекой/программой
  • Мне было интересно проверить себя, изучить github, написать пост на хабре в конце концов
  • Мне ведь не понравились существующие, а времени много. Почему бы и нет?


Таким образом, я убедился, что хочу этого. Несколько дней — и набросок готов. Три недели — готова бета версия.
Еще пару дней ушло на разборки с github'ом. Для человека, понятия не имеющего, что такое git, это было довольно непросто.

Название парсера — Rarara. Почему? Да просто нравятся мне эти буквы.

Итак, вода закончилась, перехожу к описанию.

Что необычного в Rarara?

  • Он меньше, чем Soup и Lxml
  • Он не использует регулярные выражения


А как же скорость? Чтобы проверить скорость, необходимо по крайней мере запустить Soup и Lxml. Rarara несовместим с Python 2.x, а попытка запустить setup.py с ключом install в Beautiful Soup постоянно проваливается. То есть полноценный тест я провести не смог.

Но увидел этот пост с тестом производительности разных парсеров. К сожалению, у нас с автором совершенно разные ОС (Ubuntu 3.5.0-19-generic x86_64 у автора и Windows 7 Max x86_32 у меня).

Поэтому результаты по скорости у меня лишь приблизительные, но они близки к остальным парсерам, проходящим тест.

Ну, пора уже и к примерам переходить
Простой пример:
from Rarara import *

parser = Parser("<div id='smth' class='smth else'></div>")
parser.parse()

print(parser.getElementsByAttrName('id', 'smth')[0] is parser.roots[0])
#True

tag = Element('a')
tag.attributes['href'] = 'https://github.com'
tag.childNodes.add(Text('Github here'))
parser.roots[0].childNodes.add(tag)
printer = Printer(parser)
printer.pprint()
#<div id="smth" class="smth else">
#    <a href="https://github.com">
#        Github here
#    </a>
#</div>

a = parser.getElementsByTagName('a').elements[0]
printer.print_node(a, deep=False)
#<a href="https://github.com">...</a>

Больше примеров и документация здесь.

В заключение

В общем, цели я достиг. Со временем буду обновлять, например, в парсере еще нет поиска по регулярным выражениям и по CSS-селекторам.

И да, у меня есть несколько просьб к сообществу

  • Если у кого установлен Beautiful Soup или Lxml на Python 3.x, очень прошу хотя бы приблизительно сравнить данные о скоростях
  • Поскольку это первая программа, я не уверен, что код «чистый», хотя думаю, что это так. Прошу взглянуть на исходники хоть одним глазком и описать мнение в комментариях

Пожалуй, все. Спасибо, что дочитали до конца.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.