Xpath全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言,它最初是用来搜索XML文档的,可是它一样适用于HTML文档的搜索html
XPth提供了很是简洁明了的路径选择表达式,还提供了超过100个内建函数,用于字符串,数值,时间的匹配以及节点,序列的处理等。node
XPath经常使用规则函数
表 达 式 | 描 述 |
nodename | 选取此节点的全部子节点 |
/ | 从当前节点选取直接子节点 |
// | 从当前节点选取子孙节点 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
例如://title[@lang='eng'],这就是一个XPath规则,它表明选择全部名称为title ,同时属性lang的值为eng的节点spa
from lxml import etree text=''' <div> <ul> <li class="item-0"><a href="link1.html">first item</a></li> <li class ="item-1"><a href="link2.html">second item</a></li> <li class ="item-inactive"><a href="link3.html">third item</a></li> <li class ="item-1"><a href="link4.html">fourth item</a></li> <li class ="item-0"><a href="link5.html">fifth item</a> </ul> </div> ''' html=etree.HTML(text) result=etree.tostring(html) print(result.decode('utf-8'))
这里首先导入lxml库的etree模块,而后声明一段HTML文本,调用HTML类进行初始化,这样就成功构造了一个XPath解析对象,etree模块能够自动修正HTML文本,调用tostring()方法便可输出修正后的HTML代码,可是结果是bytes类型,因此利用decode()方法将其转化成str类型code
from lxml import etree html=etree.parse('Cookies.text',etree.HTMLParser()) result=etree.tostring(html) print(result.decode('utf-8'))
也能够直接读取文本文件进行解析。xml
from lxml import etree html=etree.parse("Cookies.text",etree.HTMLParser()) result=html.xpath("//*") print(result)
这里使用*表明匹配全部节点,即整个HTML文本中的全部节点都会被获取htm
from lxml import etree html=etree.parse("Cookies.text",etree.HTMLParser()) result=html.xpath("//li") print(result) print(result[0])
也能够匹配指定节点名称,提取的结果是一个列表形式,其中每一个元素都是一个Element对象对象
经过/或//能够查找元素的子节点或子孙节点blog
from lxml import etree html=etree.parse("Cookies.text",etree.HTMLParser()) result=html.xpath("//li/a") print(result)
这里选取了全部li节点的全部直接a子节点索引
/用于选取直接子节点,//用于选取全部子孙节点
from lxml import etree html=etree.parse("Cookies.text",etree.HTMLParser()) result=html.xpath("//ul//a") print(result)
父节点用..来实现
from lxml import etree html=etree.parse('Cookies.text',etree.HTMLParser()) result=html.xpath('//a[@href="link4.html"]/../@class') print(result)
这里首先选取href属性为link4.html的a节点,而后获取其父节点,而后在获取其class属性
也能够用parent::来获取父节点
from lxml import etree html=etree.parse('Cookies.text',etree.HTMLParser()) result=html.xpath('//a[@href="link4.html"]/parent::*/@class') print(result)
在选取时,能够用@符号进行属性过滤
from lxml import etree html=etree.parse('Cookies.text',etree.HTMLParser()) result=html.xpath('//li[@class="item-0"]') print(result)
用XPath中的text()方法获取节点中的文本
from lxml import etree html=etree.parse('Cookies.text',etree.HTMLParser()) result=html.xpath('//li[@class="item-0"]/text()') print(result)
这里并无获取到任何文本,只获取到一个换行符,这是由于text()前面是/,而此处/的含义是选取直接子节点,而li的直接子节点都是a节点,文本都是在a节点内部,因此这里匹配到的结果就是被修正的li节点内部的换行符。
若是想要获取li节点内部的文本,有两种方式,一种是先选取a节点在获取文本,另外一种是使用//。
先选取a节点再获取文本:
from lxml import etree html=etree.parse('Cookies.text',etree.HTMLParser()) result=html.xpath('//li[@class="item-0"]/a/text()') print(result)
返回的两个结果恰好是节点文本。
使用//:
from lxml import etree html=etree.parse('Cookies.text',etree.HTMLParser()) result=html.xpath('//li[@class="item-0"]//text()') print(result)
这里返回3个结果,前两个是节点文本,另一个是最后一个li节点内部的文本,即换行符
用@符号获取
from lxml import etree html=etree.parse('Cookies.text',etree.HTMLParser()) result=html.xpath('//li/a/@href') print(result)
这里html文本中li节点的class属性有两个值li和li-first。此时若是还想用以前的属性匹配获取,就没法匹配了
须要用contains()函数,代码以下
from lxml import etree text=''' <li class="li li-first"><a href="link.html">first item</li> ''' html=etree.HTML(text) result=html.xpath('//li[contains(@class,"li")]/a/text()') print(result)
这里contains()方法,第一个参数传入属性名称,第二个参数传入属性值,只要此属性包含所传入的属性值,就能够完成匹配
根据多个属性肯定一个节点,这时就须要同时匹配多个属性
from lxml import etree text=''' <li class="li li-first" name="item"><a href="link.html">first item</li> ''' html=etree.HTML(text) result=html.xpath('//li[contains(@class,"li")and @name="item"]/a/text()') print(result)
有时一个属性可能同时匹配了多个节点,这时能够根据顺序选取节点
from lxml import etree html=etree.parse("Cookies.text",etree.HTMLParser()) result=html.xpath('//li[1]/a/text()') print(result) result=html.xpath('//li[last()]/a/text()') print(result) result=html.xpath('//li[position()<3]/a/text()') print(result) result=html.xpath('//li[last()-2]/a/text()') print(result)
第一次选择时,选取了第一个li节点,中括号中传入数字1便可
第二次选择时,选取了最后一个节点li节点,中括号中传入last()便可,返回的即是最后一个li节点
第三次选择时,选取了位置小于3的li节点,也就是位置序号为1和2的节点
第四次选择时,选取了倒数第三个li节点,中括号中传入last()-2便可
XPath提供了不少节点轴选择方法,包括获取子元素,兄弟元素,父元素,祖先元素等
from lxml import etree text=''' <div> <ul> <li class="item-0"><a href="link1.html"><span>first item</span></a></li> <li class="item-1"><a href="link2.html">second item</a></li> <li class="item-inactive"><a href="link3.html">third item</a></li> <li class="item-1"><a href="link4.html">fourth item</a></li> <li class="item-0"><a href="link5.html">fifth item</a> </ul> </div> ''' html=etree.HTML(text) result=html.xpath('//li[1]/ancestor::*') print(result) result=html.xpath('//li[1]/ancestor::div') print(result) result=html.xpath('//li[1]/attribute::*') print(result) result=html.xpath('//li[1]/child::a[@href="link1.html"]') print(result) result=html.xpath('//li[1]/descendant::span') print(result) result=html.xpath('//li[1]/following::*[2]') print(result) result=html.xpath('//li[1]/following-sibling::*') print(result)
第一次选择时,调用了ancestor轴,能够获取因此祖先节点,直接使用*表示匹配全部节点,所以返回结果是第一个li节点的全部祖先节点
第二次选择时,加了限定条件div,获得的结果就只有div这个祖先节点
第三次选择时,调用了attribute轴,能够获取全部属性值,后面根据的选择器仍是*,这表明获取节点的全部属性,返回的就是li节点的全部属性值
第四次选择时,调用了child轴,能够获取全部直接子节点
第五次选择时,调用了descendant轴,能够获取全部子孙节点。加了限定条件获取span节点,因此返回的结果只包含span节点不包括a节点
第六次选择时,调用了following轴,能够获取当前节点以后的全部节点,加了索引选择(第一个索引为1,为当前节点)
第七次选择时,调用了following-sibling轴,能够获取当前节点以后的全部同级节点,使用*匹配,获取了全部后续同级节点