python3 + selenium 之元素定位
8種定位方式
定位一個元素
webdriver提供了一系列的物件定位方法,常用的有以下幾種
- driver.find_element_by_name()——最常用,簡單
- driver.find_element_by_id()——最常用,簡單
- driver.find_element_by_class_name()
- driver.find_element_by_tag_name()——最不靠譜
- driver.find_element_by_link_text()——定位文字連線好用
- driver.find_element_by_partial_link_text()——定位文字連線好用
- driver.find_element_by_xpath()——最靈活,萬能
- driver.find_element_by_css_selector()
定位一組元素
- driver.find_elements_by_name()
- driver.find_elements_by_id()
- driver.find_elements_by_class_name()
- driver.find_elements_by_tag_name()
- driver.find_elements_by_link_text()
- driver.find_elements_by_partial_link_text()
- driver.find_elements_by_xpath()
- driver.find_elements_by_css_selector()
id 和 name
id 和 name 是我們最最常用的定位方式,因為大多數控制元件都有這兩個屬性,而且在對控制元件的id 和name命名時一般使其有意義也會取不同的名字。通過這兩個屬性使我們找一個頁面上的屬性變得相當容易
我們通過前端工具,找到了百度輸入框的屬性資訊,如下:
<input id="kw" class="s_ipt" type="text" maxlength="100" name="wd" autocomplete="off">
id=”kw”
通過find_element_by_id("kw") 函式就是捕獲到百度輸入框
name=”wd” 通過find_element_by_name("wd")函式同樣也可以捕獲百度輸入框
tag name 和class name
從上面的百度輸入框的屬性資訊中,我們看到,不單單隻有id 和 name兩個屬性,比如class 和 tag name(標籤名)
<input>
input 就是一個標籤的名字,可以通過find_element_by_tag_name("input") 函式來定位。
class="s_ipt"
通過find_element_by_class_name("s_ipt")函式捕獲百度輸入框。
但是,碰下面的一組控制元件屬性,我們就哭了。
<th width="95"></th><th width="">檔名</th>
<th class="c1">建立時間</th><th class="c1">狀態</th>
<th class="c1">檔案大小</th><th class="c1">時長</th>
下面的css 和 XPath就沒有上面的那麼直觀,如果不懂前端的話可能不太好理解
CSS定位
CSS(Cascading Style Sheets)是一種語言,它被用來描述HTML和XML文件的表現。CSS使用選擇器來為頁面元素繫結屬性。這些選擇器可以被selenium用作另外的定位策略。
CSS的比較靈活可以選擇控制元件的任意屬性,上面的例子中:
find_element_by_css_selector("#kw")
通過find_element_by_css_selector( )函式,選擇取百度輸入框的id屬性來定義
也可以取name屬性
<a href="http://news.baidu.com" name="tj_news">新 聞</a>
driver.find_element_by_css_selector("a[name=\"tj_news\"]").click()
可以取title屬性
<a onclick="queryTab(this);" mon="col=502&pn=0" title="web" href="http://www.baidu.com/">網頁</a>
driver.find_element_by_css_selector("a[title=\"web\"]").click()
也可以是取…:
<a class="RecycleBin xz" href="javascript:void(0);">
driver.find_element_by_css_selector("a.RecycleBin xz").click()
CSS的定位是看上去應該是一種非常靈活和牛X 的定位方式
擴充套件閱讀
cssSelector也是一種常用的選擇器,CSS locator比XPath locator速度快,用CSS Selector能非常精準的定位到想測試的Elements
cssSelector常用符號說明
# 表示id
. 表示class
> 表示子元素,層級
一個空格也表示一個子元素,但是所有的子元素相當於xpath中的相對路徑
cssSelector的常用用法
#input 選擇id為input的節點
.Volvo 選擇class為Volvo的節點
div#radio>input 選擇id為radio的div下的所有的input節點
div#radio input 選擇id為radio的div下的所有的子孫後代input節點
div#radio>input:nth-of-type(4) 選擇id為radio的div下的第4個input節點
div#radio>nth-child(1) 選擇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)~labe 選擇id為radio的div下的第4個input節點之後的所有label節點
input.Vovlo[name='identity'] 選擇class為.Volvo並且name為identity的input節點
input[name='identity'][type='radio']:nth-of-type(1) 選擇name為identity且type為radio的第1個input節點
input[name^='ident'] 選擇以ident開頭的name屬性的所有input節點
input[name$='entity'] 選擇以'entity'結尾的name屬性的所有input節點
input[name*='enti'] 選擇包含'enti'的name屬性的所有input節點
div#radio>*.not(input) 選擇id為radio的div的子節點中不為input的所有子節點
input:not([type='radio']) 選擇input節點中type不為radio的所有節點
cssSelector這種元素定位方式跟xpath比較類似,但執行速度較快,而且各種瀏覽器對它的支援都相當到位,所以功能也是蠻強大的。
下面是一些常見的cssSelector的定位方式:
定位id為flrs的div元素,可以寫成:#flrs 注:相當於xpath語法的//div[@id=’flrs’]
定位id為flrs下的a元素,可以寫成 #flrs > a 注:相當於xpath語法的//div[@id=’flrs’]/a
定位id為flrs下的href屬性值為/forexample/about.html的元素,可以寫成: #flrs > a[href=”/forexample/about.html”]
如果需要指定多個屬性值時,可以逐一加在後面,如#flrs > input[name=”username”][type=”text”]。
XPath
XPath是一種在XML文件中定位元素的語言。因為HTML可以看做XML的一種實現,所以selenium使用者可是使用這種強大語言在web應用中定位元素。
XPath擴充套件了上面id和name定位方式,提供了很多種可能性,比如定位頁面上的第三個多選框。
xpath:attributer (屬性)
driver.find_element_by_xpath("//input[@id='kw']").send_keys("selenium")
#input標籤下id =kw的元素
xpath:idRelative (id相關性)
driver.find_element_by_xpath("//div[@id='fm']/form/span/input").send_keys("selenium")
#在/form/span/input 層級標籤下有個div標籤的id=fm的元素
driver.find_element_by_xpath("//tr[@id='check']/td[2]").click()
# id為'check' 的tr ,定閃他裡面的第2個td
xpath:position (位置)
driver.find_element_by_xpath("//input").send_keys("selenium")
driver.find_element_by_xpath("//tr[7]/td[2]").click()
#第7個tr 裡面的第2個td
xpath: href (水平參考)
driver.find_element_by_xpath("//a[contains(text(),'網頁')]").click()
#在a標籤下有個文字(text)包含(contains)'網頁' 的元素
xpath:link
driver.find_element_by_xpath("//a[@href='http://www.baidu.com/']").click()
#有個叫a的標籤,他有個連結href='http://www.baidu.com/ 的元素
實踐記錄:
driver.find_element_by_xpath("//[@id='TANGRAM__PSP_10__submitWrapper']/a[text() = '立即註冊']").click() #中括號中的文字為全部文字,不是部分
link 定位
有時候不是一個輸入框也不是一個按鈕,而是一個文字連結,我們可以通過link
示例程式碼:
#coding=utf-8
from selenium import webdriverimport time
browser = webdriver.Firefox()
browser.get("http://www.baidu.com")
time.sleep(2)
browser.find_element_by_link_text("貼 吧").click()
time.sleep(2)
browser.quit()
一般一個那頁面上不會出現相同的檔案連結,通過文字連結來定位也是一種簡單有效的定位方式。
Partial Link Text 定位
driver.find_element_by_xpath("//*[text()=‘新聞’]").click()也可這樣寫
通過部分連結定位,這個有時候也會用到,我還沒有想到很好的用處。拿上面的例子,我可以只用連結的一部分文字進行匹配:
browser.find_element_by_partial_link_text("貼").click()
#通過find_element_by_partial_link_text() 函式,我只用了“貼”字,指令碼一樣找到了"貼 吧" 的連結
注:
- 當頁面元素有id屬性時,最好儘量用id來定位。但由於現實專案中很多程式設計師其實寫的程式碼並不規範,會缺少很多標準屬性,這時就只有選擇其他定位方法。
- xpath很強悍,但定位效能不是很好,所以還是儘量少用。如果確實少數元素不好定位,可以選擇xpath或cssSelector。
- 當要定位一組元素相同元素時,可以考慮用tagName或name。
- 當有連結需要定位時,可以考慮linkText或partialLinkText方式。
各定位方式demo
接下來我們將使用8種定位方式向百度的搜尋輸入框中輸入selenium
#coding=utf-8 #編碼格式
from selenium import webdriver #匯入webdriver
import time #匯入時間模組
browser = webdriver.Firefox() #指定使用Firefox執行
browser.get("http://www.baidu.com") #獲取百度page
time.sleep(2) #等待2秒
#########百度輸入框的定位方式##########
#通過id方式定位
browser.find_element_by_id("kw").send_keys("selenium")
#通過name方式定位
browser.find_element_by_name("wd").send_keys("selenium")
#通過tag name方式定位
browser.find_element_by_tag_name("input").send_keys("selenium")
#通過class name 方式定位
browser.find_element_by_class_name("s_ipt").send_keys("selenium")
#通過CSS方式定位
browser.find_element_by_css_selector("#kw").send_keys("selenium")
#通過xphan方式定位
browser.find_element_by_xpath("//input[@id='kw']").send_keys("selenium")
############################################
browser.find_element_by_id("su").click() #點選搜尋
time.sleep(3)
browser.quit() #退出瀏覽器並關閉驅動
browser.close() #退出瀏覽器
定位後不能向文字輸入資訊
有時候我們可以通過id 的方式將其進行定位,但卻不能通過sendKeys()向文字框中輸入文字資訊
參考連結1
參考連結2
實踐參考程式碼:
text = “input text”
js = “var” sum=document.getElementById(‘id’);sum.value=’” + text + “’;”
driver.execute_script(js)
首先定義了要輸入的內容text,然後將text與JavaScript程式碼通過“+”進行拼接。這樣做的目的是為了使輸入內容變得可自定義。最後通過execute_script()執行JavaScript程式碼。