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::* #返回節點以後的同級節點