目录
1.ElementTree 类
2.Element 类
3.ElementTree 类或 Element 类的查找方法
为方便开发人员在程序中使用 XPath 的路径表达式提取节点对应的内容, Python 提供了
第三方库 lxml 。开发人员通过 lxml 库可以轻松地对 HTML 或 XML 文档中的目标节点进行定
位并提取。这里以 4.6.3 版本的 lxml 库为例进行介绍。
在 lxml 库中,大多数有关解析网页数据的功能都封装到 etree 模块中, etree 模块包含了
两个比较重要的类,它们分别是 ElementTree 类和 Element 类,关于这两个类的相关内容的介
绍如下。
1.ElementTree 类
ElementTree 类的对象可以理解为一个 HTML 或 XML 文档的节点树。为方便开发者将
HTML 或 XML 文档转换为 ElementTree 类的对象, etree 模块中提供了一个 parse() 函数。 parse()
函数的声明如下。
parse(source, parser=None, base_url=None)
上述函数中各参数的含义如下。
- source:必选参数,表示待解析的内容,该参数共支持 4 种类型的取值,它们分别是
打开的文件对象(确保以二进制模式打开)、类似文件的对象、字符串形式的文件名称、字符
串形式的 URL 。
- parser:可选参数,表示解析器。若未指定解析器,则会使用默认的解析器;若希望
指定其他解析器,则可以通过 help(etree.XMLParser) 查看 lxml 支持的解析器。
- base_url:可选参数,表示基础 URL。
下面以 4.3.2 节中的 bookstore.xml 为例,演示如何根据该文档使用 parse() 函数创建
ElementTree 类的对象,示例代码如下。
from lxml import etree
# 根据 bookstore.xml 文件创建 ElementTree 类的对象
ele_tree = etree.parse(r'bookstore.xml')
print(type(ele_tree))
运行代码,输出如下结果。
<class 'lxml.etree._ElementTree'>
此外,etree 模块还提供了 fromstring() 函数、 XML() 函数和 HTML() 函数。这 3 个函数也
可以解析 HTML 或 XML 文档或片段,只不过在解析成功后返回根节点或者解析器目标返回
的结果。其中, fromstring() 函数和 XML() 函数具有相同的功能,都可以从字符串常量中解析
XML 文档或片段; HTML() 函数用于从字符串常量中解析 HTML 文档或片段,并能够自动补
全文档或片段中缺少的 <html> 和 <body> 元素。
例如,使用 fromstring() 函数解析 XML 片段,具体代码如下。
from lxml import etree
xml_doc = '''
<bookstore> <book> <title lang="eng">Harry Potter</title> <price>29.99</price> </book> <book> <title lang="eng">Learning XML</title> <price>39.95</price> </book>
</bookstore>
'''
# 从字符串 xml_doc 中解析 XML 片段
root_node = etree.fromstring(xml_doc)
print(root_node)
运行代码,输出如下结果。
<Element bookstore at 0x33d7a00>
从输出结果可以看出,程序输出了一个 Element 类的对象,该对象是根节点 bookstore 。
2.Element 类
Element 类的对象可以理解为 XML 或 HTML 文档的节点。它与 Python 中的列表非常相
似,可以使用诸如 len() 方法、 append() 方法、 remove() 方法修改节点,也可以使用索引、切片
获取节点集中的子节点。
例如,使用索引或切片获取 root_node 对象中的子节点,具体代码如下。
print(root_node[:]) # 获取所有的子节点
print(root_node[0]) # 获取第 1 个子节点
print(root_node[1]) # 获取第 2 个子节点
运行代码,输出如下结果。
[<Element book at 0x34cae00>, <Element book at 0x34cae80>]
<Element book at 0x34cae00>
<Element book at 0x34cae00>
除此之外,Element 类还提供了一些获取节点的属性,关于这些属性及其说明如表 4-6 所示。
例如,获取 root_node 对象的名称,示例代码如下。
print(root_node.tag)
运行代码,输出如下结果。
bookstore
3.ElementTree 类或 Element 类的查找方法
ElementTree类或 Element 类中提供了 3 个常用的查找方法,它们分别是 find() 方法、 findall()
方法和 xpath() 方法。关于 find() 方法、 findall() 方法和 xpath() 方法的介绍如下。
● find() 方法:从节点树的某个节点开始查找,返回匹配到的第一个子节点。
● findall() 方法:从节点树的某个节点开始查找,以列表的形式返回匹配到的所有子节点。
● xpath() 方法:从节点树的根节点或某个节点开始查找,以列表的形式返回匹配到的所
有子节点。
使用上述 3 个方法都可以接收 XPath 的路径表达式,并在调用成功后返回查找到的最终
结果,不过, find() 方法和 findall() 方法只支持相对路径, xpath() 方法支持相对路径和绝对路径。
需要注意的是,若 find() 方法未找到匹配项,则会返回 None ;若 findall() 方法和 xpath() 方法未
找到匹配项,则会返回一个空列表。
以 root_node 对象为例,分别使用以上 3 个方法查找第一个 price 节点的文本,示例代码
如下。
res1 = root_node.find('.//price').text
print(res1)
res2 = root_node.findall('.//price')[0].text
print(res2)
res3 = root_node.xpath('.//price')[0].text
print(res3)
运行代码,输出如下结果。
29.9929.9929.99