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軸,能夠獲取當前節點以後的全部同級節點,使用*匹配,獲取了全部後續同級節點