xpath简介
XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。
<html>
<body>
<div>
<p>Hello world<p>
<a href="/home">Click here</a>
</div>
</body>
</html>
XML文档中常见的节点包括:
- 根节点:html
- 元素节点:html,body,div,p,a
- 属性节点:href
- 文本节点:xpath简介
XML文档中常见的节点间关系:
- 父子关系:例如上面的<p>, <a>都是<div>的子节点,反之,<div>则是<p>,<a>标签的父节点
- 兄弟关系:例如<p>,<a>标签是兄弟节点
- 祖先/后代:例如,<body>、<div>、<p>、<a> 都是 <html> 的后代节点,反之,也称 <html> 是<body>、<div>、<p>、<a> 的祖先节点
对于网页解析来说,xpath 比 re 更加方便简洁,故 Python 中也提供相应的模块 —— lxml.etree
安装
pip3 install lxml
使用
aaa = """
<html>
<head>
<meta charset="UTF-8"/>
<link rel="stylesheet" href="style/base.css"/>
<title>Example website</title>
</head>
<body>
<div id="images" class="content">
<a href="image1.html">Image1<img src="image1.jpg"/></a>
<a href="image2.html">Image2<img src="image2.jpg"/></a>
<a href="image3.html">Image3<img src="image3.jpg"/></a>
</div>
</body>
</html>
"""
导入模块
from lxml import etree
构造对象
html = etree.HTML(aaa) # 构造 lxml.etree._Element 对象
# result = etree.tostring(html) # 代码补全功能
# 假如我们得到的 XML 文档不是规范的文档,该对象将会自动补全缺失的闭合标签
# 我们可以使用 tostring() 方法将对象转化成 bytes 类型的字符串
# 再使用 decode('utf-8') 方法将 bytes 类型的字符串转化为 str 类型的字符串
print(etree.tostring(html).decode('utf-8'))
匹配数据
我们可以使用 xpath() 方法进行匹配
xpath常用规则
nodename | 选择这个节点名的所有子节点 |
/ | 从当前节点选择直接子节点 |
// | 从当前节点选取子孙节点 |
. | 选择当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
E/* | 选取E节点下所有的子节点 |
| | 选取若干个路径 |
E/text() | 获取E节点下子节点的文本内容 |
E/string() | 获取E节点下子孙节点的文本内容,不支持获取数字类型 |
E/data() | 和string()通用,但是不建议使用,除非获取数字类型 |
具体讲解+案例
/
表示子代节点,如获取<head>标签下的<title>子节点test = html.xpath('/html/head/title')
//
表示后代节点,如获取根节点下所有的<a>节点test = html.xpath('//a')
*
表示所有节点,如获取<html>节点下所有的节点test = html.xpath('/html/*')
text()
表示文本节点,例如 获取<title>节点下的子节点中的文本节点test = html.xpath('/html/head/title/text()')
@attr
表示属性节点,如获取<a>标签的href属性test = html.xpath('//a/@href')
|
代表选取多个标签,如获取<head>标签下的<title>子节点 和 获取根节点下所有的<a>节点test = html.xpath('/html/head/title|//a')
谓语
用于匹配指定的标签指定第二个 <a> 标签
test = html.xpath('//a[2]')
指定前两个 <a> 标签
test = html.xpath('//a[position()<=2]')
指定带有 href 属性的<a> 标签
test = html.xpath('//a[@href]')
指定带有 href 属性且值为 image1.html 的 <a> 标签
test = html.xpath('//a[@href="image1.html"]')
指定带有 href 属性且值包含 image 的 <a> 标签
test = html.xpath('//a[contains(@href,"image")]')
指定最后一个<a>标签
test = html.xpath('//a[last()]')
指定倒数第二个<a>标签
test = html.xpath('//a[last()-1]')
_Element 对象
xpath 方法返回字符串或者匹配列表,匹配列表中的每一项都是 lxml.etree._Element 对象
下面主要介绍一下 _Element 对象的常用属性与方法:
我们先用 xpath 方法得到匹配列表 tests 作为测试样例,tests 中的每一项都是一个 _Element 对象
test = html.xpath('//a[@href="image1.html"]')
obj = test[0]
tag
返回标签名obj.tag # 'a'
attrib
返回属性与值组成的字典obj.attrib # {'href': 'image1.html'}
get()
返回指定属性的值obj.get('href') # 'image1.html'
text
返回文本值obj.text # 'Image1'