Selenium---元素定位之CSS定位
CSS 選擇器:
常見符號:
#表示 id選擇器
.表示 class選擇器
>表示子元素,層級
一個空格也表示子元素,但是是所有的後代子元素,相當於 xpath 中的相對路徑
一、css:屬性定位
1.css可以通過元素的id、class、標籤這三個常規屬性直接定位到
2.如下是百度輸入框的的html程式碼:
<input id="kw" class="s_ipt" type="text" autocomplete="off" maxlength="100" name="wd"/>
3.css用#號表示id屬性,如:#kw
4.css用.表示class屬性,如:.s_ipt
5.css直接用標籤名稱,無任何標示符,如:input
二、css:其它屬性
1.css除了可以通過標籤、class、id這三個常規屬性定位外,也可以通過其它屬性定位
2.以下是定位其它屬性的格式
[name=wd] [autocomplete='off'][maxlength='255']
三、css:標籤
css頁可以通過標籤與屬性的組合來定位元素
input.s_ipt input#kw input[id='kw']
四、css:層級關係
//form的id屬性
form#form>span>input
//form的class屬性
form.fm>span>input
五、css:索引
css也可以通過索引nth-child(1)來定位子元素,直接翻譯過來就是第幾個小孩
總結:選擇標籤後,找第幾個小孩即可
Select控制元件第三個Opel
#select>select>option:nth-child(3)
CheckBox第一個Volvo
#checkbox>input:nth-child(1)
CheckBox第二個Saab
#checkbox>input:nth-child(4)
RadioBox第二個Saab
#radio>input:nth-child(4)
通過索引nth-of-type(2)來定位子元素,按照分類指定
選擇select的saab
#select>select>option:nth-of-type(2);
選擇 id 為 radio 的 div 下的第 1 個子節點
div#radio>input:nth-of-type(4)+label
選擇id 為radio 的div 下的第4 個input 節點之後挨著的 label
節點
div#radio>input:nth-of-type(4)~label
六、css:邏輯運算
css同樣也可以實現邏輯運算,同時匹配兩個屬性,這裡跟xpath不一樣,無需寫and關鍵字
[type='checkbox'][name='checkbox1']
Selenium webdriver是完全模擬使用者在對瀏覽器進行操作,所有使用者都是在頁面進行的單擊、雙擊、輸入、滾動等操作,而webdriver也是一樣,所以需要我們指定元素讓webdriver進行單擊、雙擊、輸入等操作,所以元素定位是UI自動化測試的前提條件。
CSS定位方式和XPATH定位方式基本相同,只是CSS定位表示式有其自己的格式。CSS定位方式擁有比XPATH定位速度快,且比XPATH穩定的特性。下面詳細介紹CSS定位方式的使用方法
其中xpath與css為最常用的定位方式,本文章以百度搜索框為例重點介紹css定位的使用
from selenium import webdriver driver = webdriver.Chrome() driver.get("https://www.baidu.com") # 1)絕對路徑(一般不推薦使用,此處不介紹) # 2)id選擇器 # driver.find_element_by_css_selector("#kw").send_keys("ethon") # 3)class選擇器 # driver.find_element_by_css_selector(".s_ipt").send_keys("ethon") # 4)其他屬性定位 # driver.find_element_by_css_selector("[autocomplete='off']").send_keys("ethon") # 5)通過部分屬性定位 # * 包含某個字元 # ^ 以某個字元開關 # $ 以某個字元結尾 # driver.find_element_by_css_selector("[autocomplete*='f']").send_keys("ethon") # driver.find_element_by_css_selector("[autocomplete^='o']").send_keys("ethon") # driver.find_element_by_css_selector("[autocomplete$='f']").send_keys("ethon") # 6)通過層級定位 # driver.find_element_by_css_selector("form>span>input").send_keys("ethon") # driver.find_element_by_css_selector("form#form>span>input").send_keys("ethon") # 層級與id組合定位 # driver.find_element_by_css_selector("form.fm>span>input").send_keys("ethon") # 層級與class組合定位 # 7)通過兄弟節點定位 # driver.find_element_by_css_selector("div#u1>a:first-child").click() # driver.find_element_by_css_selector("div#u1>a:nth-child(2)").click() driver.find_element_by_css_selector("div#u1>a:last-child").click()
被測網頁的HTML程式碼
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style type="text/css"> input.spread { Font-SIZE:20pt;} input.tight { FONT-SIZE:10pt;} </style> </head> <body onload="document.getElementById('div1input').focus()"> <div id="div1" style="text-align:center"> <input id="div1input" class="spread"/></input> <a href="http://www.sogou.com">搜狗搜尋</a> <img alt="div1-img1" src="http://www.sogou.com/images/logo/new/sogou.png" href="http://www.sogou.com">搜狗圖片</img> <input type="button" value="查詢"></input> </div> <br> <p>第一段文字</p> <p>第二段文字</p> <div name= "div2" style="text-align:center"> <input name="div2input" class="tight"></input> <a href="http://www.baid.com">百度搜索</a> <img alt="div2-img2" src="http://www.baidu.com/img/bdlogo.png" href="http://www.baidu.com">百度圖片</img> <input type="button" value="查詢"></input> </div> <div class="foodDiv"> <ul id="recordlist"> <p>土豆</p> <li>西紅柿</li> </ul> </div> </body> </html>
①使用絕對路徑定位元素
目的
在被測試網頁中,查詢第一個div中的查詢按鈕
CSS定位方式:
html > body > div >input[value="查詢"]
Python定位語句:
element = driver.find_element_by_css_selector('html > body > div >input[value="查詢"]')
程式碼解釋:
上述CSS定位表示式使用絕對路徑定位屬性value的值為“查詢”的頁面元素。從CSS定位表示式可以看出,步間通過“>"分割,區別於XPATH路徑中的正”/“,並且也不再使用@符號選擇屬性。
②使用相對路徑定位元素
目的
在被測試網頁中,查詢第一個div下的查詢按鈕
CSS定位表示式:
input[value="查詢"]
Python定位語句:
element = driver.find_element_by_css_selector('input[value="查詢"]')
程式碼解釋
上述CSS表示式通過相對路徑使用元素名稱和元素的屬性及屬性值進行頁面元素的定位。
③使用class名稱定位元素
目的
在被測網頁中,查詢第一個div元素下的input輸入框
CSS定位表示式:
css.spread
python定位語句:
element = driver.find_element_by_css_selector('css.spread')
程式碼解釋
上述CSS定位表示式使用input頁面元素的class屬性名稱spread來進行定位,用點(.)分割元素名與class屬性名,點號後面是class屬性名稱
④使用ID屬性值定位元素
目的
在被測試網頁中,查詢第一個dic元素下ID屬性值為div1input“的input元素
CSS定位語句:
input#div1input
Python定位語句:
element = driver.find_element_by_css_selector('input#div1input')
程式碼解釋
上述CSS定位表示式使用input頁面元素的ID屬性值div1input進行定位,使用#號分割元素名和ID屬性值,#後面是ID屬性值
⑤使用頁面其他屬性值定位元素
目的
在被測網頁中,查詢div元素下的第一張圖片元素img
CSS定位表示式:
img[alt="div1-img1"] img[alt="div1-img1"][href="http://www.sogou.com"]
Python定位語句:
element = driver.find_element_by_css_selector('img[alt="div1-img1"]') element = driver.find_element_by_css_selector('img[alt="div1-img1"][href="http://www.sogou.com"]')
程式碼解釋:
表示式1和表示式2是等價的,都是定位第一個img元素
表示式1:表示使用img頁面元素的alt元素的屬性值div1-img1進行定位。若定位的頁面元素始終具有唯一的屬性值,此定位方式可以解決很多頻繁變動的頁面元素
表示式2:表示同時使用了img頁面元素的alt和href屬性進行頁面元素的定位。在某些複雜的定位場景,可使用多個屬性來確保定位元素的唯一性。
⑥使用屬性值的一部分內容定位元素
目的
在被測試網頁中,查詢“搜狗搜尋”連結
CSS定位表示式:
1 a[href^="http://www.so"] 2 a[href$="gou.com"] 3 a[href*="sogou"]
Python定位語句:
1 element = driver.find_element_by_css_selector('a[href^="http://www.so"]') 2 element = driver.find_element_by_css_selector('a[href$="gou.com"]') 3 element = driver.find_element_by_css_selector('a[href*="sogou"]')
程式碼解釋
1.表示匹配連結地址開始為http://www.so關鍵字串的連結元素,以字元^指明從字串的開始匹配
2.表示匹配連結地址結尾包含gou.com關鍵字串的連結元素,以字元$指明在字串的結尾匹配
3.表示匹配連結地址包含sogou關鍵字串的連結元素,以字元*指明在需要進行模糊查詢
使用此模糊定位方式,可匹配動態變化的屬性值的頁面元素,只要找到屬性值固定不變的關鍵部分,就可以進行模糊匹配定位。此方法可以解決大部分複雜定位的問題,當然無論是方式都需要靈活使用才能確保能夠準確的定位都想要定位的元素
⑦使用頁面元素進行子頁面元素的查詢
目的
在被測網頁中,查詢第一個div下的第一個input元素
CSS定位表示式:
1 div#div1>input#div1input 2 div input
Python定位語句:
1 element=driver.find_element_by_css_selector("div#div1>input#div1input") 2 element=driver.find_elements_by_css_selector("div input")
程式碼解釋
1.表示式1中的div#div1,表示在被測試網頁上定位到ID屬性值為div1的div頁面元素,> 表示在以查詢到的div元素的子頁面元素中進行查詢,input#div1input表示查詢ID屬性值為div1input的input頁面元素,此方法可實現查詢div下子頁面元素的辦法
2.表示式2表示匹配所有屬於div元素後代的input元素,表示式中父元素div和子元素input中間需用空格分割,注意此表示式是定位一組input元素,並不是單個input元素
⑧使用偽類定位元素
目的
在被測試網頁中查詢第一個div下的指定子頁面元素
CSS定位表示式:
1 div#div1 :first-child 2 div#div1 :nth-child(2) 3 div#div1 :last-child 4 input:focus 5 input:enabled 6 input:checked 7 input:not([id])
Python定位語句:
1 element=driver.find_element_by_css_selector("div#div1 :first-child")
2 element=driver.find_element_by_css_selector("div#div1 :nth-child(2)")
3 element=driver.find_element_by_css_selector("div#div1 :last-child")
4 element=driver.find_element_by_css_selector("input:focus")
5 element=driver.find_elements_by_css_selector("input:enabled")
6 element=driver.find_elements_by_css_selector("input:checked")
7 element=driver.find_elements_by_css_selector("input:not([id])")
程式碼解釋
偽類表示式是CSS語法支援的定位方式,前3個表示式特別注意的是在冒號前一定要有一個空格,否則定位不到想要定位的元素
1.表示式1表示查詢ID屬性值為div1的div頁面元素下的第一個子元素,根據被測試網頁定位的是div下的input元素,first-child表示查詢某個頁面元素下的第一個子頁面元素
2.表示式2表示查詢ID屬性值為div1的div頁面元素下的第二個子元素,參照被測網頁,定位到的頁面元素是一個連結元素
3.表示式3表示查詢ID屬性值為div1的div頁面元素下的最後一個子元素,根據被測試網頁定位的是一個按鈕元素;last-child表示的是查詢某個頁面元素下的最後一個子頁面元素
4.表示式4 表示查詢當前獲取焦點的input頁面元素
5.表示式5表示查詢可操作的input元素
6.表示查詢處於勾選狀態的checkbox頁面元素
7.表示查詢所有無id屬性的input頁面元素
⑨查詢同級兄弟頁面元素
目的
在被測試網頁中,查詢第一個div下第一個input子頁面元素同級兄弟頁面元素
CSS定位表示式:
1 div1#div1 > input + a 2 div1#div1 > input + a + img 3 div1#div1 > input + * + img 4 ul#recordlist > p~li
Python定位語句:
1 element=driver.find_element_by_css_selector("div1#div1 > input + a") 2 element=driver.find_element_by_css_selector("div1#div1 > input + a + img") 3 element=driver.find_element_by_css_selector("div1#div1 > input + * + img")
4 element=driver.find_elements_by_css_selector("ul#recordlist > p~li")
程式碼解釋
1.表示式1表示在ID屬性值為div1的頁面元素下,查詢input頁面元素後的同級的且相鄰的連結元素a
2.表示式2表示在ID屬性值為div1的頁面元素下,查詢input元素和連結元素a後面相鄰的圖片元素img
3.表示式3表示在ID屬性值為div1的頁面元素下,創造找input頁面元素和任意一種頁面元素後面的同級且相鄰的圖片元素img,* 表示任意型別的一個頁面元素,只能表示一個元素,如果想用此方法查詢第一個div下的最後一個input元素,表示式寫法為div#div1 > input + * + * + input或div#div1 > input + a + * + input或div#div1 > input + a + img + input
4.表示式4表示ID屬性值為recordlist的ul頁面元素下,查詢p頁面元素以後所有的li元素
⑩多元素選擇器
CSS定位表示式支援多元素選擇器,也就是一次可以同時選擇多個相同的標籤,也可以同時選擇多個不同的標籤,不同標籤間用英文的逗號隔開
目的
在被測網頁中,同時選擇多個不同的頁面元素
CSS定位表示式:
div#div1,input,a
Python定位語句:
element=find_elements_by_css_selector("div#div1,input,a')
程式碼解釋
上面的css表示式表示同時查詢所有ID屬性值為div1的div元素,所有的input元素,所有的a元素
總結
目前為止,已經整理了自動化測試Python+Selenium中對於web測試定位頁面元素的兩種主流,也是最好的定位方式XPATH和CSS定位方式,在我個人看來兩個方式都很不錯,效率都很高,也很容易解決日常工作中的問題,也能夠減少頁面的變動對於指令碼的維護成本,當然不同問題還需要不同的方式解決,能解決問題的方法都是好方法,希望以後的日子對於定位元素不再是難題。下面我們對這兩種定位方式大概做個對比;
XPATH定位和CSS定位很相似,XPATH功能更強大一些吧,但CSS定位方式執行速度更快,鑑於某些瀏覽器不支援CSS定位方式,並且一般在自動化測試實施過程中使用xpath定位方式要比css更普遍,所以建議大家先掌握xpath,再來看下二者在語法上有什麼區別
定位元素目標 | XPATH | CSS |
所有元素 | //* | * |
所有div元素 | //div | div |
所有div元素子元素 | //div/* | div>* |
根據ID屬性獲取元素 | //*[@id=''] | div#id |
根據class屬性獲取元素 | //*[@class=''] | div.class |
擁有某個屬性的元素 | //*[@href=''] | *[href=''] |
所有div元素的第一個子元素 | //div/*[1] | div>* :first-child |
所有擁有子元素a的div元素 | //div[a] | 無法實現 |
input的下一個兄弟元素 | //input/following-sibling::[1] | input+* |