web自動化測試第17步:深入xpath元素定位詳解

一、xpath高級用法基礎格式

  • 格式
    /軸方法::標籤名[標籤屬性]
  • 實例
    //div/parent::span[@name=‘interName’]
  • 實例解釋:
    定位span標籤,span標籤是div標籤的父級,且span標籤的name屬性值爲:interlNmae

二、基礎格式詳解

2.1層級路徑格式

  • 詳解
表達式 描述
/ 從根節點選取(絕對路徑)
// 選取匹配的節點
. 選取當前節點
.. 選取當前節點的上級節點
| 並且
  • 實例
表達式 描述
/div 從根節點選取div標籤
//div 選取所有div標籤
//div/.. 選取div標籤的上級標籤
list/tr 選取所有父級爲list的tr標籤
list//tr 選取list標籤節點內的所有tr標籤
/div/span | /div/input 選取div標籤下的span和div標籤下的input

2.2標籤位置以及標籤屬性

備註:ends-with()方法我在使用時發現無效。

  • 詳解
表達式 描述
* 選取任意的節點
@ 選取標籤本身的屬性
@* 選取帶有任何屬性的節點
last() 選取當前層級的最後一個標籤
position() 選取當前層級中標籤的具體位置定位
contains(text(),’’) 選取標籤內容包含匹配文本的節點
starts-with() 選取標籤屬性值開始字段匹配
ends-with() 選取標籤屬性值結束字段匹配
attribute 等同於@,屬於xpath方法
  • 實例
表達式 描述
/div/span[2] 選取div標籤下第二個span標籤
/table/* 選取table標籤下所有子節點
/input[@id=‘userName’] 選取所有id屬性值爲:userName的input標籤
/list[@*] 選取所有帶屬性的list標籤
/span[last()-1] 選取當前層級的倒數第二個span標籤
/li/div[position() < 3] 選取li標籤下前兩個div元素
/input[contains(text(),‘密碼’)] 選取節點中內容包含:密碼的input標籤
//input[contains(@id,‘Name’)] 選取標籤中id屬性包含Name的input的標籤
/div[starts-with(@*,‘na’)] 選取標籤中任意屬性值以na開始的div標籤
/div[ends-with(text(),‘名’)] 選取節點中內容以‘名’結尾的div標籤

2.3xpath軸方法

  • 詳解
表達式 描述
parent 選取當前節點的父節點。
ancestor 選取當前節點的所有前輩
child 選取當前節點內的所有子標籤
descendant 選取當前節點內的所有後代
following 選取當前html頁面,這個節點結束標籤之後的所有節點
preceding 選取當前html頁面,這個節點結束標籤之前的所有節點
following-sibling 選取當前節點之後的所有同級節點
preceding-sibling 選取當前節點之前的所有同級節點
  • 實例
表達式 描述
/parent::div 選取當前節點的div父標籤。
/ancestor::div 選取當前節點之上的所有div標籤(父、祖父節點)
/td/child::tr 選取td標籤下的所有tr子標籤
/td/descendant::tr 選取td標籤內的所有tr標籤(不限層級)
/table/following:: * 選取當前html頁面,table標籤結束之後的所有標籤(無視層級)
/table/preceding :: * 選取當前html頁面,table標籤之前的所有標籤(無視層級)
/div/following-sibling::div 選取div標籤之後的所有同級div標籤
/div/preceding-sibling::div 選取當前節點之前的所有同級div標籤

2.4常用運算符

表達式 示例
and /input[@id=‘name’ and @weight=‘10’]
or /input[@id=‘name’ or @weight=‘10’]
= /input[@name=‘test’]
!= /ipnut[@name!=‘test’]

2.5 附錄:一些等價的寫法

建議書寫表達式 等價表達式
/input[@name=‘test’] /input[attribute::name=‘text’]
/a[5] /a[position()=5]
div/parent::span div/..

三、實例演示

  • 常見場景:輸入框定位
    有時候經常遇到輸入框表單很多,也沒有唯一標識id等,chrome複製的xpath非常的長,而且容易失效,但是如果根據輸入框前的字段名稱來作爲標識,那定位就比較穩定了。
    這裏我來演示的是百度的註冊頁面,這裏輸入框的輸入通過字段名稱來作爲唯一標識,來定位輸入框
    xpath = //label[text()=‘用戶名’]/following-sibling::input[last()]
    百度註冊源碼
    代碼示例:
from selenium import webdriver

driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.set_page_load_timeout(15)
driver.get("https://passport.baidu.com/v2/?login")

# 點擊註冊
driver.find_element("xpath", "//a[text()='立即註冊']").click()

# 切換頁籤
all_handle = driver.window_handles
driver.switch_to.window(all_handle[1])

# 定位標籤
driver.find_element("xpath", "//label[text()='用戶名']/following-sibling::input[last()]").send_keys("用戶西城")
driver.find_element("xpath", "//label[text()='手機號']/following-sibling::input[last()]").send_keys("18888888888")
driver.find_element("xpath", "//label[text()='密碼']/following-sibling::input[last()]").send_keys("U1sd23456")

四、常見問題和經驗總結

  • 問題:parent定位父級,還是包含父級、伯父級等
    答:parent只定位到父級

  • 問題:符合xpath路徑的元素有多個,此時driver如何判斷對哪一個元素進行操作呢
    答: find_element方法中,如果符合路徑的元素有多個,默認取第一個元素

  • contains(text(),’‘要查找的文字’),定位時只能定位當前標籤層級中的文本

  • Unable to locate element
    方法1:加入time.sleep() (ui自動化中操作過快會多導致無法定位到元素)
    方法2:加入顯示等待:WebDriverWait、expected_conditions
    方法3:可能是由於操作導致層級結構改變,重新排查定位元素路徑
    方法4:可能是頁面中包含frame嵌套,加入switch_to.frame

  • Element is not currently visible and may not be manipulated exception
    方法1:下拉框沒有成功選擇數據,此時對於下拉框的定位取消顯式等待

  • unexpected EOF while parsing
    方法1:運行報錯,檢查是否是class中函數格式是否正確

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章