什么是 Xpath?
Xpath 是一種用在 XML 文檔中定位元素的語言,同樣也支持 HTML 元素的解析。
所謂 Xpath,是指 XML path language。path 就是路徑,那么 Xpath 主要是通過路徑來查找元素。
我們通過下面一張小圖來了解一下 HTML 中的結構:

HTML 的結構就是樹形結構,HTML 是根節(jié)點,所有的其他元素節(jié)點都是從根節(jié)點發(fā)出的。其他的元素都是這棵樹上的節(jié)點
Node,每個節(jié)點還可能有屬性和文本。
而路徑就是指某個節(jié)點到另一個節(jié)點的路線。
節(jié)點之間存在各種關系:
- 父節(jié)點(Parent): HTML 是 body 和 head 節(jié)點的父節(jié)點;
- 子節(jié)點(Child):head 和 body 是 HTML 的子節(jié)點;
- 兄弟節(jié)點(Sibling):擁有相同的父節(jié)點,head 和 body 就是兄弟節(jié)點。title 和 div 不是兄弟,因為他們不是同一個父節(jié)點。
- 祖先節(jié)點(Ancestor):body 是 form 的祖先節(jié)點,爺爺輩及以上??;
- 后代節(jié)點(Descendant):form 是 HTML 的后代節(jié)點,孫子輩及以下??。
Xpath 中的絕對路徑從 HTML 根節(jié)點開始算,相對路徑從任意節(jié)點開始。
通過開發(fā)者工具,我們可以拷貝到 Xpath 的絕對路徑和相對路徑代碼:

但是由于拷貝出來的代碼缺乏靈活性,也不全然準確。大部分情況下,都需要自己定義 Xpath 語句,因此 Xpath 語法還是有必要學習。
絕對路徑:
Xpath 中最直觀的定位策略就是絕對路徑。
以百度中的輸入框和按鈕為例,通過拷貝出來的 full Xpath:
/html/body/div[2]/div/div/div/div/form/span/input
這就是一個絕對路徑我們可以看出,絕對路徑是從根節(jié)點/html開始往下,一層層的表示出來直到需要的節(jié)點為止。
這明顯不是理智的選項,因此了解以下即可,不用往心里去。
相對路徑
除了絕對路徑,Xpath 中更常用的方式是相對路徑定位方法,以“//”開頭。
相對路徑可以從任意節(jié)點開始,一般我們會選取一個可以唯一定位到的元素開始寫,可以增加查找的準確性。
相對路徑可以通過以下的方式來定位元素:
基本定位語法
定位語法主要依賴于以下特殊符號:
| 表達式 | 說明 | 舉例 |
|---|---|---|
/ |
從根節(jié)點開始選取 | /html/div/span |
// |
從任意節(jié)點開始選取 | //input |
. |
選取當前節(jié)點 | |
.. |
選取當前節(jié)點的父節(jié)點 | //input/.. 會選取 input 的父節(jié)點 |
@ |
選取屬性,或者根據屬性選取 |
//input[@data] 選取具備 data 屬性的 input 元素 //@data 選取所有 data 屬性 |
* |
通配符,表示任意節(jié)點或任意屬性 |
元素屬性定位
屬性定位是通過 @ 符號指定需要使用的屬性。
- 根據元素是否具備某個屬性查找元素
//*[@data-recordid]
選取包含data-recordid屬性的所有節(jié)點??梢远ㄎ坏揭韵略兀?/p>
<tr role="row" data-boundview="gridview-1029" data-recordid="B36BCA33" ></tr>
- 根據屬性是否等于某值查找元素
//span[@role='img']
選取屬性 role 的屬性值為 img 的所有節(jié)點??梢远ㄎ坏揭韵略兀?/p>
<span role="img" class="x-btn-icon-el" unselectable="on" style=""></span>
注意,屬性值必須要加引號,單雙引號都可以。
層級屬性結合定位
遇到某些元素無法精確定位的時候,可以查找其父級及其祖先節(jié)點,找到有確定的祖先節(jié)點后通過層級依次向下定位。
以下面的結構為例:

<form action="search" id="form" method="post">
<span class="bg">
<span class="soutu">搜索</span>
</span>
<span class="soutu">
<input type="text" name="key" id="su">
</span>
</form>
- 根據層級向下找,從 form 找到綠色的 span:
//form[@id="form"]/span/span
- 查找某元素內部的所有元素,選取 form 元素內部的所有 span:
//form[@id="form"]//span
第二個雙斜杠,表示選取內部所有的 span,不管層級關系
- 使用星號找不特定的元素
//*[@id="form"]//*[@type="text"]
選取 id 屬性為 form 的任意屬性內部,并且 type 屬性為 text 的任意元素。這里會找到 input。
- 使用
..從下往上找,根據 input 查找其父節(jié)點 span:
//input[@name="key"]/..
注意最后的兩個點,找到 input 節(jié)點的上級節(jié)點,如果還要再往上再加
/..
- 找同級節(jié)點:
比如我們想通過第一個 span 標簽去 找 div 標簽。樹形結構中,兄弟節(jié)點之間的關系是通過父節(jié)點建立起來的。所以可以先找到父節(jié)點,再通過父節(jié)點找同級節(jié)點。
//span[@class="bg"]/../div
先通過
/..找到 span 的父節(jié)點,再通過父節(jié)點找到 div。
使用謂語定位
謂語是 Xpath 中用于描述元素位置。主要有數字下標、最后一個子元素last()、元素下標函數position()。
- 使用下標的方式,從 form 找到 input :
//form[@id="form"]/span[2]/input
Xpath 中的下標從
1開始。
- 查找最后一個子元素,選取 form 下的最后一個 span:
//form[@id="form"]/span[last()]
- 查找倒數第幾個子元素,選取 form 下的倒數第一個 span:
//form[@id="form"]/span[last()-1]
- 使用 position() 函數,選取 from 下第二個 span:
//form[@id="form"]/span[position()=2]
- 使用 position() 函數,選取下標大于 2 的 span:
//form[@id="form"]/span[position()>2]
使用邏輯運算符
如果元素的某個屬性無法精確定位到這個元素,我們還可以用邏輯運算符 and 連接多個屬性進行定位,以百度輸入框為例。
- 使用
and:
//*[@name='wd' and @class='s_ipt']
查找 name 屬性為 wd 并且 class 屬性為 s_ipt 的任意元素
- 使用
or:
//*[@name='wd' or @class='s_ipt']
查找 name 屬性為 wd 或者 class 屬性為 s_ipt 的任意元素,取其中之一滿足即可。
- 使用
|,同時查找多個路徑,取或:
//form[@id="form"]//span | //form[@id="form"]//input
選取 form 下所有的 span 和所有的 input。
使用文本定位
使用文本定位,是 Xpath 中的一大特色。在自動化測試中,為了讓代碼的可讀性更高,可以使用文本的方式。
以下一個案例:

部分網頁結構如下:
<tr>
<td valign="top">
<input type="radio" name="payment" value="1" checked="" iscod="0">
</td>
<td valign="top">
<strong>支付寶</strong>
</td>
</tr>
其實我們需要點的是前的單選框,但是單選框沒有任何特殊的標識,不夠靈活。我們可以通過后面的名稱,如(支付寶、余額支付等)來找到其對應行的 radio,再去點擊。
我們就需要先通過文本定位到“支付寶”,再去找其同一行(tr)的 input 節(jié)點。如果理不清楚,我們可以先畫一個結構圖:

紅色箭頭表示查找路徑,先定位到“支付寶”所在的 strong,再定位 td -> tr -> td - >input 。那么要定位“支付寶”文本,就需要用到 Xpath 中的函數 text() 或 string(),注意是函數,所以括號不能少。
text():當前元素節(jié)點包含的文本內容;
表達式//div[text()="文本"],能找到:<div>文本</div>不能找到:
<div><span>文本</span></div>
string():當前元素節(jié)點內部所有節(jié)點元素的文本內容。表達式//div[string()="文本"]上述兩種情況都能找到。
好,接著寫上面的內容。先通過 //strong[text()="支付寶"]定位到“支付寶”所在的元素 strong,再找上級 td -> tr,再向下找:
//strong[text()="支付寶"]/../../td[1]/input
也可以寫為:
//td[string()="支付寶"]/../td[1]/input
使用部分匹配函數
Xpath 中有提供了幾個函數,用來進行部分匹配。
| 函數 | 說明 | 舉例 |
|---|---|---|
| contains | 選取屬性或者文本包含某些字符 |
//div[contains(@id, 'data')] 選取 id 屬性包含 data 的 div 元素 //div[contains(string(), '支付寶')] 選取內部文本包含“支付寶”的 div 元素 |
| starts-with | 選取屬性或者文本以某些字符開頭 |
//div[starts-with(@id, 'data')] 選取 id 屬性以 data 開頭的 div 元素 //div[starts-with(string(), '銀聯(lián)')] 選取內部文本以“銀聯(lián)”開頭的 div 元素 |
| ends-with | 選取屬性或者文本以某些字符開頭 |
//div[ends-with(@id, 'require')] 選取 id 屬性以 require 結尾的 div 元素 //div[ends-with(string(), '支付')] 選取內部文本以“支付”結尾的 div 元素 |
驗證 Xpath
驗證 xpath 有兩種方法:
- 在開發(fā)者工具的 Elements 中按
Ctrl + F,在搜索框中輸入 Xpath:

- 在開發(fā)者工具的 Console 中使用
$x()
