使用XPath

Xpath全稱XML Path Language,即XML路徑語言,它是一門在XML文檔中查找信息的語言,它最初是用來搜索XML文檔的,可是它一樣適用於HTML文檔的搜索html

一.XPth概覽

XPth提供了很是簡潔明瞭的路徑選擇表達式,還提供了超過100個內建函數,用於字符串,數值,時間的匹配以及節點,序列的處理等。node

二.XPath經常使用規則

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

相關文章
相關標籤/搜索