前戲
前面介紹過了七種定位方式,今天來介紹最后一種,也是最強大,本人最常用的定位方式xpath
Xpath 即為 xml 路徑語言,它是一種用來確定 xml 文檔中某部分位置的語言。Xpath 基於 xml 的樹狀結構,提供在數據結構樹中找尋節點的能力,html 也屬於 xml
先來看一個簡單的xpath定位
from selenium import webdriver from time import sleep driver = webdriver.Chrome() driver.get('http://www.baidu.com') sleep(3) driver.find_element_by_xpath('//*[@id="kw"]').send_keys('selenium') # //表示當前頁面,@id="kw" 表示id為kw了 sleep(2) driver.find_element_by_xpath('//*[@id="su"]').click() sleep(2) driver.quit()
看起來是不是比較麻煩,為什么不通過id直接定位,因為在前端網頁開發中,不是每個元素都有id屬性的,或者id值是動態變化的。不能直接通過id定位,就要用到xpath定位了
被測網頁HTML代碼如下:
XPath絕對路徑定位
查找第一個div標簽下的“查詢”按鈕
driver.find_element_by_xpath('/html/body/div/inpu[@value="查詢"]')
XPath相對路徑定位
查找第一個div標簽下的“查詢”按鈕
driver.find_element_by_xpath('//input[@value="查詢"]')
//表示從匹配選擇的當前節點開始選擇文檔中的節點,定位到value值為查詢的input頁面,使用@表明后面接的是屬性
使用索引號定位元素
查找第一個div標簽下的“查詢”按鈕
driver.find_element_by_xpath('//input[2]')
定位到第二個input標簽,從1開始
使用頁面元素的屬性值定位元素
定位被測試網頁中的第一張img元素
//img[@href='http://www.baidu.com'] //input[@type='button']
使用模糊屬性值定位元素
頁面上某些元素的屬性值是動態生成的,也就是說每次訪問的屬性值都不一樣,使用模糊屬性值可以解決一部分此類問題,前提是屬性中有一部分內容保持不變
查找屬性alt的屬性值以“div1”關鍵字開始的頁面元素
//img[starts-with(@alt,'div1')]
查找alt屬性的屬性值包含“img”關鍵字的頁面元素,只要包含即可,無須考慮位置
//img[contains(@alt,'img')]
實例:
上面頁面中id值中后面的數字是動態變化的
fr = driver.find_element_by_xpath("//iframe[contains(@id,'x-URS-iframe')]")
driver.switch_to.frame(fr)
使用XPath軸(Axes)定位元素
先找到一個相對好定位的元素,讓他作為軸,根據他和要定位的相對位置關系進行定位
XPath軸關鍵字 | 軸的含義說明 | 定位表達式實例 | 表達式解釋 |
parent | 選擇當前節點的上層父節點 |
//img[@alt='div2-img2']/parent::div
|
查找到屬性alt的屬性值為div2-img2的img元素並
基於該img元素的位置找到他上一級的div元素
|
child |
選擇當前節點的下層所有
子節點
|
//div[@id='div1']/child::img
|
查找到id屬性值為div1的div元素,並基於該div
元素的位置找到他下層節點中的img元素
|
ancestor | 選擇當前節點所有上層的節點 |
//img[@alt='div2-img2']/ancestor::div
|
查找到屬性alt的屬性值為div2-img2的img元素
並基於該img元素的位置找到他上一級的div元素
|
descendant |
選擇當前節點所有下層的節點
(子,孫等)
|
//div[@name='div2']descendant::img
|
查找到屬性name的屬性值為div2的div元素並基於該元素的
位置找到他下級所有節點中的img頁面元素
|
following |
選擇在當前節點之后顯示的
所有節點
|
//div[@id='div1']/following::img
|
查找到id屬性值為div1的div元素,並基於該div
元素的位置找到他后面節點中的img元素
|
following-sibling |
選擇當前節點后續所有
兄弟節點
|
//a[@href='http://www.sogou.com']/following-sibling::input
|
查找到鏈接地址為
http://www.sogou.com的鏈接頁面元素a,
並基於鏈接的位置找到它后續兄弟節點中的input頁面元素
|
preceding | 選擇當前節點前面的所有節點 |
//img[@alt='div2-img2']/preceding::div
|
查找到屬性alt的屬性值為div2-img2的圖片元素img,
並基於該圖片元素的位置找到他前面節點中的div頁面元素
|
preceding-sibling |
選擇當前節點前面的所有
兄弟節點
|
//input[@value='查詢']/preceding-sibling::a[1]
|
查找到value屬性值為“查詢”的輸入框頁面元素
,並基於該輸入框的位置找到它前面同級節點中
的第一個鏈接元素
|
有時候我們會在軸后面加一個星號(*),表示通配符,比如//input[@value='查詢']/preceding-sibling::*,它表示查找屬性value的值為“查詢”的輸入框input元素前面所有的同級元素,但不包括input元素本身
使用頁面元素的文本定位元素
通過text()函數可以定位到元素文本包含某些關鍵字的頁面元素
(1) //a[text()='搜狗搜索'] (2) //a[.='搜狗搜索'] (3) //a[contain(.,"百度")] (4) //a[contain(text(),"百度")] (5) //a[contain(text(),"百度")]/preceding::div (6) //a[contain(.,"百度")]/..
pytho定位語句
driver.find_element_by_xpath("//a[text()='搜狗搜索']") driver.find_element_by_xpath('//a[contain(text(),"百度")]/preceding::div')
表達式1和表達式2等價,都是查找文本內容為“搜狗搜索”的鏈接頁面元素,使用的是精准定位,不能多也不能少
表達式3和表達式4等價,都是查找文本內容里包含“百度”關鍵字的鏈接頁面,使用的是模糊匹配
表達式5和表達式6等價,都是查找文本內容里包含“百度”關鍵字的鏈接頁面元素a的上層父元素div,表達式6最后使用了兩個點,它表示選取當前節點的父節點,等價於preceding::div
xpath定位實例
實例一
先定位到name='wd'的標簽上,..返回父級標簽,也就是span標簽,在找到span標簽的a標簽
實例二
//*[contains(@id,"cjm_dialog")]/div/div[2]/button[1]/span
實例三
//div[@class="hidden-columns"]/following-sibling::div[4]/div/table/tbody/tr[1]/td[12]/div/button[5]/span
實例四
//span[@class='el-input__suffix']/preceding-sibling::input[1]
實例五
//div[text()="溯源節點"]/../div/button/span/i
實例六
//label[text()="選項名稱"]/following::div/div/input
實例七
//label[contains(text(),"單選1")]/following-sibling::div/div/div/input
實例八
//span[text()="所屬機構"]/../following-sibling::div/span/input