xpath全称XML Path language, 即xml路径语言,最初用来搜寻xml文档的,一样适用于html文档的搜寻html
经常使用规则:node
nodename | 选取此节点的全部子节点 |
/ | 从当前节点选取直接子节点 |
// | 从当前节点选取子孙节点 |
. | 选取当前节点 |
.. | 选取当前借点的父节点 |
@ | 选取属性 |
from lxml import etree text = ''' <dd> <i class="board-index board-index-1">1</i> <a href="/films/1203" title="霸王别姬" class="image-link" data-act="boarditem-click" data-val="{movieId:1203}"> <img src="//ms0.meituan.net/mywww/image/loading_2.e3d934bf.png" alt="" class="poster-default" /> <img data-src="http://p1.meituan.net/movie/20803f59291c47e1e116c11963ce019e68711.jpg@160w_220h_1e_1c" alt="霸王别姬" class="board-img" /> </a> <div class="board-item-main"> <div class="board-item-content"> <div class="movie-item-info"> <p class="name"><a href="/films/1203" title="霸王别姬" data-act="boarditem-click" data-val="{movieId:1203}">霸王别姬</a></p> <p class="star"> 主演:张国荣,张丰毅,巩俐 </p> <p class="releasetime">上映时间:1993-01-01(中国香港)</p> </div> <div class="movie-item-number score-num"> <p class="score"><i class="integer">9.</i><i class="fraction">6</i></p> </div> </div> </div> ''' html = etree.HTML(text) result = etree.tostring(html) print(result.decode('utf-8'))
这里首先导入lxml库的etree模块,而后声明了一段html文本,使用html类进行初始化,这样就成功的构造了一个xpath解析对象,须要注意的是,html文本中最后一个节点dd是没有闭合的,可是etree模块自动修正了html文本函数
调用tostring()方法便可输出修正后的html代码post
也能够直接读取文本文件进行解析spa
html = etree.aprse('./xpath.html',etree.HTMLParser()) result = etree.tostring(html) print(result.decode('utf-8'))
此次得输出结果略有不一样,多了一个DOCTYPE的声明,可是对解析结果没有任何影响.net
全部节点3d
咱们通常使用//开头的xpath规则来选取全部符合要求的节点code
html = etree.parse('./xpath.html',etree.HTMLParser()) result = html.xpath('//*') print(result)
使用*号来匹配全部节点,也就是整个html文本中的全部节点都会被获取,返回形式是一个列表,每一个元素是Element类型的,其后跟了节点的名称,如html,div,ul等xml
选取全部的a节点,可使用//,后面加上节点名称就行htm
html = etree.parse('./xpath.html',etree.HTMLParser()) result = html.xpath('//a') print(result) #[<Element a at 0x108f47448>, <Element a at 0x108f47488>] print(result[0]) #<Element a at 0x108721488>
可容易看到结果是一个列表形式,每个元素都是一个Element对象,若是要提取其中一个对象能够直接中括号加索引
属性匹配
//li[@class='item'] #获取全部class为item的li节点
属性获取
咱们知道text()获取节点内部文本,那么节点属性该怎样获取呢,其实仍是用@符号就能够了
//li/a/@href #查找全部的li节点的直接子节点的href属性值
属性多值匹配
有些时候某些节点的属性可能有多个值
<li class="li li-first" name="item"><a href="link.html">first</a></li>
这里的li节点的class 属性就有两个值li和li-first,若是还用以前的属性匹配获取,就没法匹配了
须要使用contains()函数
//li[contains(@class,'li')]/a/text()
经过contains()方法,第一个参数传入属性名称,第二个参数传入属性值,只要此属性中包含传入的属性值,就能够完成匹配
多属性匹配
还会遇到一种状况,就是根据多个属性肯定一个节点,这时就须要匹配多个属性,使用运算符and来链接
//li[contains(@class,"li") and @name="item"]/a/text()
这里的and实际上是xpath中的运算符,还有以下
or | 或 |
and | 与 |
mod | 取余 |
| | 返回拥有两边元素节点集 |
+ | |
- | |
* | |
div | 除法 |
= | |
!= |
|
< | |
<= | |
> | |
>= |
按序选择
有时候咱们选择属性时,匹配到了多个节点,可是咱们只想要其中的某个节点,
//li[1]/a/text() #选取第一个节点,中括号传入1便可,序号是以1开头的 //li[last()]/a/text() #选取最后一个节点 //li[position()<3]/a/text #选取序号小于3的,也就是选择1,2 //li[last()-2]/a/text() #选择倒数第三个节点,由于last()是最后一个,因此last()-2是倒数第三个
节点轴选择
//li[1]/ancestor::* #获取全部祖先节点 //li[1]/ancestor::div #获取指定祖先节点div //li[1]/attribute::* #获取节点的全部属性 //li[1]/child::a[@href="like.html"] #获取全部直接子节点,条件:href属性为like.html的a节点 //li[1]/descendant::span #获取全部子孙节点:条件:返回只包含span节点 //li[1]/following::*[2] #当前节点以后的全部节点,但加了索引匹配,只选择第二个后续节点 //li[1]following-sibling::* #返回节点以后的同级节点