1. xPath介绍
xPath全称为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。同时,它完全适用于html的文档搜索。
XPath基于XML的树状结构,他提供了非常简洁明了的路径选择表达式,能够在数据结构树中找寻指定节点。
对于爬虫,我们完全可以利用xpath进行数据筛选和数据提取。
2、xPath常用规则
xpath常用语法规则,在接下来的内容中我们会经常用到:
- *:选取此节点下的所有节点
- //: 从当前节点选取子孙节点
- /: 从当前节点选取直接子节点
- . : 选取当前节点
- . . : 选取当前节点的父节点
- @ :选取属性
- [ ] : 指定属性
其中://和/分绝对路径和相对路径.
2.1、绝对路径
绝对路径就是在整个html树结构中,以html节点为根节点。即从根节点开始,依据树形结构对目的节点进行查找 。如,我们想要查找html文档中的所有的p标签:
//p
2.2、相对路径
相对路径就是从当前路径开始,依据树形结构对目的节点进行查找。如,若当前节点是ul标签,我们要选择其子孙标签中的img标签,可以这样做
/path/p
3、xPath的使用
所有内容都使用此文本
text = '''
<html>
<head>
<meta charset="utf-8">
<title>案例</title>
</head>
<body>
<div class="nav">
<ul>
<li><a href="">这是1</a></li>
<li><a href=""></a>这是2</li>
<li><a href="" id="text">这里有个text链接</a></li>
<li><img src="123" class="myImg" >嗯,图片</li>
<li class="li li-first" name="item"><a href="link.html">first item</a></li>
<li class="li li-first" ><a href="link.html">first item</a></li>
<li>无</li>
</ul>
</div>
<div id="content sentence">
<p class="p1 " id= "content1">是以泰山不让土壤,故能成其大;河海不择细流,故能就其深;王者不却众庶,故能明其德。</p>
<p class="p2">治大者不可以烦,烦则<strong>乱</strong>;治小者不可以怠,怠则废</p>
</div>
</body>
</html>
'''
3.1、初始化
#声明html文本,会自动修正html文本
html = etree.HTML(text)
#得到修正后的html代码,但是是bytes类型
result = etree.tostring(html)
#转换成str类型
print(result.decode('utf-8'))
3.2、获取节点
3.2.1、所有节点
一般会用//
开头的XPath规则来选取所有符合要求的节点。这里以前面的HTML文本为例
#所有节点,包括祖先节点,以及祖先节点下的子节点
result = html.xpath('//*')
for list in result:
print(etree.tostring(list, encoding='utf-8').decode('utf-8'))
print("============================")
3.2.2、指定节点
可以使用//
,然后直接加上节点名称即可
result = html.xpath('//li')
#result = html.xpath('//li[2]')#指定元素位置
#result = html.xpath('//li[position()<3]')#指定元素范围
for list in result:
print(etree.tostring(list, encoding='utf-8').decode('utf-8'))
print("============================")
3.2.3、子孙节点
通过/
或//
即可查找元素的子节点或子孙节点
result = html.xpath('//li/a')#子节点
result = html.xpath('//ul//a')#子孙节点
for list in result:
print(etree.tostring(list, encoding='utf-8').decode('utf-8'))
print("============================")
3.2.4、父节点
可以用..
来实现查找父节点,先找到子节点再找父节点
result = html.xpath('//img/../..')#查找了两次父亲节点,节点后面跟/..
for list in result:
print(etree.tostring(list, encoding='utf-8').decode('utf-8'))
print("============================")
3.3、属性获取
3.3.1、属性单值匹配
属性匹配是中括号加属性名和值来限定某个属性,而下面的这个是获取节点的某个属性
result = html.xpath('//li/img/@src')
print(result)
属性匹配的是
result = html.xpath('//li/img[@src]')#选取所有拥有src的元素
#result = html.xpath('//li/img[@src="123"]')#选取所有拥有src且值为123的元素
for list in result:
print(etree.tostring(list, encoding='utf-8').decode('utf-8'))
print("============================")
3.3.2、属性多值匹配
HTML文本中li节点的class
属性有两个值li
和li-first
,就需要用contains()
函数了:
result = html.xpath('//li[contains(@class, "li")]/a/text()')
print(result)
3.3.3、多属性匹配
根据多个属性确定一个节点,这时就需要同时匹配多个属性。此时可以使用运算符and
来连接,另外还有or,mod等等
result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')
print(result)
3.4、选取若干路径
通过在路径表达式中使用"|"运算符,您可以选取若干个路径
result = html.xpath('//li/img[@src="123"] | //li/a')
for list in result:
print(etree.tostring(list, encoding='utf-8').decode('utf-8'))
print("============================")