目录
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