什么是lxml库
lxml是以Python语言编写的库,主要用于解析和提取HTML或者XML格式的数据,它不仅功能非常丰富,而且便于使用,可以利用XPath语法快速地定位特定的元素或节点。
lxml库中大部分的功能都位于 lxml.etree模块中,导入lxml.etree模块的常见方式如下:
from lxml import etree
lxml库的一些相关类如下:
Element类:可以理解为XML的节点。
ElementTree类:可以理解为一个完整的XML文档树。
ElementPath类:可以理解为XPath,用于搜索和定位节点。
一、Element类简介
Element类是XML处理的核心类,可以直观地理解为XML的节点,大部分XML节点的处理都是围绕着该类进行的。要想创建一个节点对象,则可以通过构造函数直接创建,示例如下:
root = etree.Element('root')
上述示例中,参数root表示节点的名称。
关于Element类的相关操作,主要可分为三个部分,分别是节点操作、节点属性的操作、节点内文本的操作,下面进行逐一介绍。
1. 节点操作
若要获取节点的名称,则可以通过tag属性获取,示例如下:
print(root.tag)
# 输出结果如下
root
2. 节点属性的操作
在创建节点的同时,可以为节点增加属性。节点中的属性是以“key-value”的形式进行存储的,类似于字典的存储方式。通过构造方法创建节点时,可以在该方法中以参数的形式设置属性,其中参数的名称表示属性的名称,参数的值表示为属性的值。创建属性的示例如下:
# 创建root节点,并为其添加属性
root = etree.Element('root', interesting='totally')
print(etree.tostring(root))
# 输出结果如下
b'<root interesting="totally"/>'
此外,可以通过set()方法给已有的节点添加属性。在调用该方法时可以传入两个参数,其中第一个参数表示属性的名称,第二个参数表示属性的值,示例如下:
# 再次给root节点添加age属性
root.set('age', '30')
print(etree.tostring(root))
# 输出结果如下
b'<root interesting="totally" age="30"/>'
在上述两个示例中,都用到了tostring()函数,该函数可以将元素序列化为其XML树的编码字符串表示形式。
3. 节点内文本的操作
一般情况下,可以通过text、tail属性或者xpath()方法来访问文本内容。通过text属性访问节点的示例如下:
root = etree.Element('root') # 创建root节点
root.text = 'Hello, World!' # 给root节点添加文本
print(root.text)
print(etree.tostring(root))
# 输出结果如下
Hello, World!
b'<root>Hello, World!</root>'
二、从字符串或文件中解析XML
为了能够将XML文件解析为树结构,etree模块中提供了如下三个函数:
fromstring()函数:从字符串中解析XML文档或片段,返回根节点(或解析器目标返回的结果)。
XML()函数:从字符串常量中解析XML文档或片段,返回根节点(或解析器目标返回的结果)。
HTML()函数:从字符串常量中解析HTML文档或片段,返回根节点(或解析器目标返回的结果)。
其中,XML()函数的行为类似于fromstring()函数,通常用于将XML字面量直接写入到源代码中,HTML()函数可以自动补全缺少的< html>和< body>标签。关于上述三个函数的示例如下:
xml_data = '<root>data</root>'
# fromstring方法
root_one = etree.fromstring(xml_data)
print(root_one.tag)
print(etree.tostring(root_one))
# XML方法,与fromstring方法基本一样
root_two = etree.XML(xml_data)
print(root_two.tag)
print(etree.tostring(root_two))
# HTML方法,如果没有<html>和<body>标签,会自动补上
root_three = etree.HTML(xml_data)
print(root_three.tag)
上述示例运行的结果如下:
root
b'<root>data</root>'
root
b'<root>data</root>'
html
除了上述三个函数之外,还可以调用parse()函数从XML文件中直接解析。在调用函数时,如果没有提供解析器,那么就使用默认的解析器,函数会返回一个ElementTree 类型的对象,示例如下:
html = etree.parse('./hello.html')
result = etree.tostring(html, pretty_print=True)
print(result)
三、ElementPath类简介
ElementTree类中附带了一个类似于XPath路径语言的ElementPath类。在ElementTree类或Elements类的API文档中,提供了三个常用的方法,可以满足大部分搜索和查询需求,并且这两个方法的参数都是XPath语句,具体如下:
find()方法:返回匹配到的第一个子元素;
findall()方法:以列表的形式返回所有匹配的子元素。
iterfind()方法:返回一个所有匹配元素的迭代器。
从文档树的根节点开始,搜索符合要求的节点,示例如下:
# 从字符串中解析XML,返回根节点
root = etree.XML("<root><a x='123'>aText<b/><c/><b/></a></root>")
# 从根节点查找,返回匹配到的节点名称
print(root.find("a").tag)
# 从根节点开始查找,返回匹配到的第一个节点的名称
print(root.findall(".//a[@x]")[0].tag)
示例的结果如下:
a
A
还可以调用xpath()方法,使用元素作为上下文节点来评估XPath表达式。