Введение в библиотеку Python lxml

lxml - это библиотека Python, которая позволяет легко обрабатывать файлы XML и HTML, а также может использоваться для парсинга веб-страниц. Существует множество стандартных анализаторов XML, но для достижения лучших результатов разработчики иногда предпочитают писать свои собственные анализаторы XML и HTML. Именно тогда в игру вступает библиотека lxml. Ключевые преимущества этой библиотеки заключаются в том, что она проста в использовании, чрезвычайно быстра при синтаксическом анализе больших документов, очень хорошо документирована и обеспечивает легкое преобразование данных в типы данных Python, т.е.

lxml - это библиотека Python, которая позволяет легко обрабатывать файлы XML и HTML, а также может использоваться для парсинга веб-страниц. Существует множество стандартных анализаторов XML, но для достижения лучших результатов разработчики иногда предпочитают писать свои собственные анализаторы XML и HTML. Именно тогда в игру вступает библиотека lxml. Ключевые преимущества этой библиотеки заключаются в том, что она проста в использовании, чрезвычайно быстра при синтаксическом анализе больших документов, очень хорошо документирована и обеспечивает легкое преобразование данных в типы данных Python, что упрощает манипулирование файлами.

В этом руководстве мы глубоко погрузимся в библиотеку Python lxml, начав с того, как настроить ее для различных операционных систем, а затем обсудим ее преимущества и широкий спектр предлагаемых функций.

Монтаж

Есть несколько способов установить lxml в вашу систему. Мы рассмотрим некоторые из них ниже.

Использование Pip

Pip - это менеджер пакетов Python, который используется для простой загрузки и установки библиотек Python в вашу локальную систему, т.е. он также загружает и устанавливает все зависимости для пакета, который вы устанавливаете.

Если в вашей системе установлен pip, просто выполните следующую команду в терминале или командной строке:

 $ pip install lxml 

Использование apt-get

Если вы используете MacOS или Linux, вы можете установить lxml, выполнив эту команду в своем терминале:

 $ sudo apt-get install python-lxml 

Использование easy_install

Вероятно, вы не дойдете до этой части, но если ни одна из вышеперечисленных команд по какой-то причине у вас не работает, попробуйте использовать easy_install :

 $ easy_install lxml 

Примечание. Если вы хотите установить какую-либо конкретную версию lxml, вы можете просто указать ее при запуске команды в командной строке или в терминале, например, lxml==3.xy

К настоящему времени у вас должна быть установлена копия библиотеки lxml на вашем локальном компьютере. Давайте теперь запачкаем руки и посмотрим, какие классные вещи можно делать с помощью этой библиотеки.

Функциональность

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

 from lxml import etree as et 

Это импортирует etree , представляющий интерес, из библиотеки lxml.

Создание документов HTML / XML

Используя etree , мы можем создавать элементы XML / HTML и их подэлементы, что очень полезно, если мы пытаемся писать или манипулировать файлом HTML или XML. Попробуем создать базовую структуру HTML-файла с помощью etree :

 root = et.Element('html', version="5.0") 
 
 # Pass the parent node, name of the child node, 
 # and any number of optional attributes 
 et.SubElement(root, 'head') 
 et.SubElement(root, 'title', bgcolor="red", fontsize='22') 
 et.SubElement(root, 'body', fontsize="15") 

В приведенном выше коде вам необходимо знать, что для Element требуется как минимум один параметр, а для SubElement требуется как минимум два. Это связано с тем, что Element требует только имени создаваемого элемента, тогда как SubElement требует создания имени как корневого узла, так и дочернего узла.

Также важно знать, что обе эти функции имеют только нижнюю границу количества аргументов, которые они могут принимать, но не имеют верхней границы, потому что вы можете связать с ними столько атрибутов, сколько захотите. Чтобы добавить атрибут к элементу, просто добавьте дополнительный параметр к функции (Sub) Element и укажите свой атрибут в форме attributeName='attribute value' .

Давайте попробуем запустить код, который мы написали выше, чтобы лучше понять эти функции:

 # Use pretty_print=True to indent the HTML output 
 print (et.tostring(root, pretty_print=True).decode("utf-8")) 

Выход:

 <html version="5.0"> 
 <head/> 
 <title bgcolor="red" fontsize="22"/> 
 <body fontsize="15"/> 
 </html> 

Есть еще один способ создания и организации ваших элементов в иерархическом порядке. Давайте также исследуем это:

 root = et.Element('html') 
 root.append(et.SubElement('head')) 
 root.append(et.SubElement('body')) 

Поэтому в этом случае всякий раз, когда мы создаем новый элемент, мы просто добавляем его к корневому / родительскому узлу.

Анализ документов HTML / XML

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

 print(root.tag) 

Выход:

 html 

Теперь, чтобы перебрать все дочерние элементы в root узле и распечатать их теги:

 for e in root: 
 print(e.tag) 

Выход:

 head 
 title 
 body 

Работа с атрибутами

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

Используя тот же root элемент, что и раньше, попробуйте следующий код:

 root.set('newAttribute', 'attributeValue') 
 
 # Print root again to see if the new attribute has been added 
 print(et.tostring(root, pretty_print=True).decode("utf-8")) 

Выход:

 <html version="5.0" newAttribute="attributeValue"> 
 <head/> 
 <title bgcolor="red" fontsize="22"/> 
 <body fontsize="15"/> 
 </html> 

Здесь мы видим, что newAttribute="attributeValue" действительно был добавлен к корневому элементу.

Давайте теперь попробуем получить значения атрибутов, которые мы установили в приведенном выше коде. Здесь мы получаем доступ к дочернему элементу, используя индексирование массива по root элементу, а затем используем метод get() для получения атрибута:

 print(root.get('newAttribute')) 
 print(root[1].get('alpha')) # root[1] accesses the `title` element 
 print(root[1].get('bgcolor')) 

Выход:

 attributeValue 
 None 
 red 

Получение текста из элементов

Теперь, когда мы ознакомились с основными функциями etree , давайте попробуем сделать еще несколько интересных вещей с нашими файлами HTML и XML. Почти всегда в этих файлах между тегами есть текст. Итак, давайте посмотрим, как мы можем добавить текст к нашим элементам:

 # Copying the code from the very first example 
 root = et.Element('html', version="5.0") 
 et.SubElement(root, 'head') 
 et.SubElement(root, 'title', bgcolor="red", fontsize="22") 
 et.SubElement(root, 'body', fontsize="15") 
 
 # Add text to the Elements and SubElements 
 root.text = "This is an HTML file" 
 root[0].text = "This is the head of that file" 
 root[1].text = "This is the title of that file" 
 root[2].text = "This is the body of that file and would contain paragraphs etc" 
 
 print(et.tostring(root, pretty_print=True).decode("utf-8")) 

Выход:

 <html version="5.0">This is an HTML file<head>This is the head of that file</head><title bgcolor="red" fontsize="22">This is the title of that file</title><body fontsize="15">This is the body of that file and would contain paragraphs etc</body></html> 

Проверить, есть ли у элемента дочерние элементы

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

Сделаем это для узлов, которые мы создали выше:

 if len(root) > 0: 
 print("True") 
 else: 
 print("False") 

Приведенный выше код выведет «True», поскольку у корневого узла есть дочерние узлы. Однако, если мы проверим то же самое для дочерних узлов корневого узла, как в приведенном ниже коде, на выходе будет «False».

 for i in range(len(root)): 
 if (len(root[i]) > 0): 
 print("True") 
 else: 
 print("False") 

Выход:

 False 
 False 
 False 

Теперь давайте сделаем то же самое, чтобы увидеть, является ли каждый из узлов Element или нет:

 for i in range(len(root)): 
 print(et.iselement(root[i])) 

Выход:

 True 
 True 
 True 

Метод iselement полезен для определения того, есть ли у вас действительный Element и, следовательно, можно ли продолжить его обход, используя методы, которые мы показали здесь.

Проверьте, есть ли у элемента родительский элемент

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

 print(root.getparent()) 
 print(root[0].getparent()) 
 print(root[1].getparent()) 

Первая строка не должна возвращать ничего (иначе None ), поскольку сам корневой узел не имеет родителя. Два других должны указывать на корневой элемент, то есть на HTML-тег. Давайте проверим вывод, чтобы убедиться, что он соответствует нашим ожиданиям:

Выход:

 None 
 <Element html at 0x1103c9688> 
 <Element html at 0x1103c9688> 

Получение братьев и сестер элемента

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

Боковое перемещение по дереву очень похоже на перемещение по нему по вертикали. Для последнего мы использовали getparent и длину элемента, для первого мы будем использовать функции getnext и getprevious . Давайте попробуем их на ранее созданных узлах, чтобы увидеть, как они работают:

 # root[1] is the `title` tag 
 print(root[1].getnext()) # The tag after the `title` tag 
 print(root[1].getprevious()) # The tag before the `title` tag 

Выход:

 <Element body at 0x10b5a75c8> 
 <Element head at 0x10b5a76c8> 

Здесь вы можете видеть, что root[1].getnext() извлек тег «body», поскольку это был следующий элемент, а root[1].getprevious() извлек тег «head».

Точно так же, если бы мы использовали getprevious для root, она вернула бы None , а если бы мы использовали getnext для root [2], она также вернула бы None .

Разбор XML из строки

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

 root = et.XML('<html version="5.0">This is an HTML file<head>This is the head of that file</head><title bgcolor="red" fontsize="22">This is the title of that file</title><body fontsize="15">This is the body of that file and would contain paragraphs etc</body></html>') 
 root[1].text = "The title text has changed!" 
 print(et.tostring(root, xml_declaration=True).decode('utf-8')) 

Выход:

 <?xml version='1.0' encoding='ASCII'?> 
 <html version="5.0">This is an HTML file<head>This is the head of that file</head><title bgcolor="red" fontsize="22">The title text has changed!</title><body fontsize="15">This is the body of that file and would contain paragraphs etc</body></html> 

Как видите, мы успешно изменили текст в HTML-документе. Объявление XML doctype также было автоматически добавлено из-за xml_declaration который мы передали функции tostring

Поиск элементов

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

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

 print(root.find('a')) # No <a> tags exist, so this will be `None` 
 print(root.find('head').tag) 
 print(root.findtext('title')) # Directly retrieve the the title tag's text 

Выход:

 None 
 head 
 This is the title of that file 

Заключение

В приведенном выше руководстве мы начали с базового введения в то, что такое библиотека lxml и для чего она используется. После этого мы узнали, как установить его в различных средах, таких как Windows, Linux и т. Д. Двигаясь дальше, мы исследовали различные функции, которые могли бы помочь нам перемещаться по дереву HTML / XML как в вертикальном, так и в боковом направлении. В конце мы также обсудили способы поиска элементов в нашем дереве, а также получения информации из них.

comments powered by Disqus