1.使用XPath
XPath概览
XPath的选择功能强大,它提供了简洁明了的路径选择表达式。用于字符串,数值,时间的匹配以及节点,序列的处理等。
XPath常用规则
nodename —————-选取此节点的所有子节点
/ —————-从当前节点选取直接子节点
// —————-从当前节点选取直接子孙节点
. —————-选取当前节点
.. —————–选取当前节点的父节点
@ —————–选取属性
//title[@lang=’eng’]
这就是一个XPath规则,代表选择所有名称为title,同时属性lang值为eng的节点
实例引入
from lxml import etree #导入lxml库的etree模块,声明一段HTML文本,调用HTML类进行初始化, # 自动补充缺失节点,成功构造一个XPath解析对象 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'>thrid 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)#输出修正后的HTML代码,返回结果是bytes类型 print(result.decode('utf-8'))#利用decode()方法转成str
所有节点
from lxml import etree content=''' <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'>thrid 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(content) #result=etree.tostring(html) result=html.xpath('//*') #*匹配所有节点,返回结果是一个列表每个元素是Element类型 #res_li=html.xpath('//li')#获取所有li节点 print(result)
子节点
from lxml import etree html=etree.parse('./test.html',etree.HTMLParser()) result=html.xpath('//*/li/a') # /a表示所有li元素下的直接a元素,/用于取直接子节点 #result=html.xpath('//li//a') # //a表示所有li元素下的所有a元素 print(result)
from lxml import etree html=etree.parse('./test.html',etree.HTMLParser()) result=html.xpath('//ul/a')#/ul下的直接a元素 print(result) #输出:[]
//用于获取直接子节点,,//用于获取子孙节点
父节点
已知子节点,查找父节点,用..来实现
from lxml import etree html=etree.parse('./test.html',etree.HTMLParser()) #首先选中href属性为link4.html的a节点,再获取其父节点,然后在获取其class属性 res=html.xpath('//a[@href="link4.html"]/../@class') print(res)
属性匹配
用@符进行属性过滤。
from lxml import etree html=etree.parse('./test.html',etree.HTMLParser()) res=html.xpath('//li[@class="item-0"]') #选取class为item-0的li节点 print(res)
文本获取
from lxml import etree html=etree.parse('./test.html',etree.HTMLParser()) res=html.xpath('//li[@class="item-0"]/text()') '''结果是['\r\n'] 原因:获取的节点是 <li class='item-1'><a href='link4.html'>fourth item</a></li> <li class='item-0'><a href='link5.html'>fifth item</a> </li> 因为匹配的结果是修正过的,而自动修正的li节点的尾标签换行了,所以提取的文本是换行符 ''' print(res)
可改为:
from lxml import etree html=etree.parse('./test.html',etree.HTMLParser()) res=html.xpath('//li[@class="item-0"]//a/text()') print(res)
或者
from lxml import etree html=etree.parse('./test.html',etree.HTMLParser()) #res=html.xpath('//li[@class="item-0"]//a/text()') res=html.xpath('//li[@class="item-0"]//text()') print(res)
属性获取
获取所有a节点的href属性
from lxml import etree html=etree.parse('./test.html',etree.HTMLParser()) res=html.xpath('//a/@href') print(res)
属性多值匹配
适用于某个节点属性有多个值
from lxml import etree content=''' <li class='li li-first'><a href="link1.html">first item</a></li> ''' html=etree.HTML(content) res=html.xpath('//li[contains(@class,li)]/a/text()') print(res)
多属性匹配
根据多个属性确定一个节点,可使用and来连接
from lxml import etree content=''' <li class='li li-first' name='item'><a href="link1.html">first item</a></li> ''' html=etree.HTML(content) res=html.xpath('//li[contains(@class,li) and @name="item"]/a/text()') print(res)
and是xpath中的运算符,还有or,mod等等。
按序选择
利用[]传入索引的方法获取特定次序的节点
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'>thrid 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]/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)
节点轴选择
XPath提供了很多节点轴选择方法,包括获取子元素,兄弟元素,父元素,祖先元素等。