1. 程式人生 > >python3 + selenium 之元素定位

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 的定位方式

擴充套件閱讀

擴充套件閱讀1
擴充套件閱讀2

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() 函式,我只用了“貼”字,指令碼一樣找到了"貼 吧" 的連結

注:

  1. 當頁面元素有id屬性時,最好儘量用id來定位。但由於現實專案中很多程式設計師其實寫的程式碼並不規範,會缺少很多標準屬性,這時就只有選擇其他定位方法。
  2. xpath很強悍,但定位效能不是很好,所以還是儘量少用。如果確實少數元素不好定位,可以選擇xpath或cssSelector。
  3. 當要定位一組元素相同元素時,可以考慮用tagName或name。
  4. 當有連結需要定位時,可以考慮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程式碼。

其他參考文件

參考連結1
參考連結2
參考連結3