【基於Python的Selenium2自動化測試】02 -Webdriver之元素定位
文章目錄
說明:
WebDriver屬於Selenium體系中用來操作瀏覽器的一套API,同時,WebDriver也是Python的一個用於實現Web自動化的第三方庫。
首先來看一下百度首頁的Web頁面,如下:
在這張web頁面上,我們看到有 輸入框、按鈕和文字連結,還有圖片、頁面底部的文字等。自動化要做的就是模擬滑鼠和鍵盤來操作這些元素,或單擊,或輸入,或滑鼠懸停等操作。
操作這些頁面元素的前提就是要找到它們,自動化工具不可能像人一樣可以通過肉眼就可以分辨這些元素,並且知道它們是幹什麼用的,那麼自動化工具如何找到它們呢?
接下來我們通過前端工具來看一下這些元素的真實面目。
對於谷歌瀏覽器,我們只需要按 F12 就可以啟用開發者工具檢視頁面元素,如下:
我們可以看到頁面上的元素都是由一行行的程式碼組成的,它們之間是層級關係組織起來的,每個元素有不同的標籤名和屬性值。WebDriver就是通過這些資訊來找到不同的元素的。
WebDriver提供了8種元素定位方法,在Python中,其對應的方法如下:
元素 | 方法 |
---|---|
id | name |
class name | tag name |
link text | partial link text |
xpath | css selector |
find_element_by_id() | find_element_by_name() |
find_element_by_class_name() | find_element_by_tag_name() |
find_element_by_link_text() | find_element_by_partial_tag_name() |
find_element_by_xpath() | find_element_by_css_selector() |
下面是百度首頁的前端程式碼(Chrome開發者工具檢視所得)
<!--STATUS OK-->
<html>
<head>…</head>
<body link=”#0000cc”>
<div data-for="result" id="swfEveryCookieWrap" style="width: 0px; height: 0px; overflow: hidden;">...</div>
<script>…</script>
<div id="wrapper" style="display: block;">
<script>
if(window.bds&&bds.util&&bds.util.setContainerWidth){bds.util.setContainerWidth();}
</script>
<div id=”head”>
<div class=”head_wrapper”>
<div class=”s_form”>
<div class="s_form_wrapper soutu-env-nomac soutu-env-index">
<div id="lg">
<img hidefocus="true" src="//www.baidu.com/img/bd_logo1.png" width="270" height="129">
</div>
<a href="/" id="result_logo" onmousedown="return c({'fm':'tab','tab':'logo'})">
<img src="//www.baidu.com/img/baidu_jgylogo3.gif" alt="到百度首頁" title="到百度首頁">
</a>
<form id="form" name="f" action="/s" class="fm">
<input type="hidden" name="ie" value="utf-8">
<input type="hidden" name="f" value="8">
<input type="hidden" name="rsv_bp" value="0">
<input type="hidden" name="rsv_idx" value="1">
<input type="hidden" name="ch" value="">
<input type="hidden" name="tn" value="baidu">
<input type="hidden" name="bar" value="">
<span class="bg s_ipt_wr quickdelete-wrap">
<span class="soutu-btn"></span>
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
<a href="javascript:;" id="quickdelete" title="清空" class="quickdelete" style="top: 0px; right: 0px; display: none;"></a>
</span>
<span class="bg s_btn_wr">
<input type="submit" id="su" value="百度一下" class="bg s_btn">
</span>
……
</body>
<html>
從上面的程式碼我們可以看到
- 它們都是由標籤組成:
<html></html>
<body></body>
<div></div>
<form></form>
……
- 標籤有各種屬性
<div id=”head” class=”s_down”>
<from class=”well”>
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
就像人也會有各種屬性一樣,如身份證(id)、姓名(name)、職業(class)等
- 標籤對之間可以有文字資料:
<a>新聞</a>
<a>地圖</a>
<a>視訊</a>
<a>貼吧</a>
- 標籤有層級關係
<html>
<body>
</body>
</html>
<div>
<form>
<input />
</form>
</div>
2.1 id定位
HTML規定id屬性在HTML文件中必須是唯一的,這類似於公民的身份證號,具有很強的唯一性。
Webdriver提供的id
定位方法就是通過元素的id
屬性來查詢元素。
例如:通過id定位百度輸入框與百度搜索按鈕,
用法如下:
find_element_by_id(“kw”)
find_element_by_id(“su”)
說明: find_element_by_id()
方法通過id
屬性來定位元素。
2.2 name定位
HTML規定name
來指定元素的名稱,因此它的作用就像是人的姓名。
name
的屬性值在當前頁中可以不唯一。
例如:通過name定位百度輸入框,
用法如下:
find_element_by_name(“wd”)
說明: find_element_by_name()
方法通過name屬性來定位元素。
注意:由於百度搜索按鈕並沒有提供name
屬性,因此就不能通過name
屬性來定位它。
2.3 class定位
HTML規定class
用來指定元素的類名。
例如:通過class
屬性來定位百度輸入框和搜尋按鈕,
用法如下:
find_element_by_class_name(“s_ipt”)
find_element_by_class_name(“bg s_btn”)
說明: find_element_by_class_name()
方法通過class
屬性來定位元素。
2.4 tag定位
HTML的本質就是通過tag
來定義實現不同的功能,每個元素本質上就是一個tag
。
因為一個tag
往往用來定義一類功能,所以通過tag
識別某個元素的概率很低。
例如,我們開啟任意一個頁面,檢視前端都會發現有大量的<div>、<input>、<a>
等tag
,所以很難通過tag name
去區分不同的元素。
例如:通過tag name
去定位百度的輸入框和搜尋按鈕,你會發現它們完全一樣
用法如下:
find_element_by_tag_name(“input”)
說明: find_element_by_tag_name()
方法通過元素的tag name來定位元素。
2.5 link定位
link
專門用來定位文字連結。
例如:百度首頁上的幾個文字連結如下
其文字連結的程式碼如下:
<a href="http://news.baidu.com" name="tj_trnews" class="mnav">新聞</a>
<a href="http://www.hao123.com" name="tj_trhao123" class="mnav">hao123</a>
<a href="http://map.baidu.com" name="tj_trmap" class="mnav">地圖</a>
<a href="http://v.baidu.com" name="tj_trvideo" class="mnav">視訊</a>
<a href="http://tieba.baidu.com" name="tj_trtieba" class="mnav">貼吧</a>
<a href="http://xueshu.baidu.com" name="tj_trxueshu" class="mnav">學術</a>
根據上面的程式碼,我們發現,其實通過name
屬性來定位是一個更好的選擇。不過這裡為了演示link
定位的使用,用法如下:
find_element_by_link_text(“新聞”)
find_element_by_link_text(“hao123”)
find_element_by_link_text(“地圖”)
find_element_by_link_text(“視訊”)
find_element_by_link_text(“貼吧”)
find_element_by_link_text(“學術”)
說明: find_element_by_link_text()
方法通過元素標籤對之間的文字資訊來定位元素。
2.6 partial link定位
partial link
定位是對link
定位的一種補充,有些文字連結較長,這個時候可以取文字連結的一部分進行定位,只要這部分資訊可以唯一的標識這個連結即可。
例如:
<a class="mnav" name=”tj_long” href=”#”>一個很長的文字連結</a>
通過partial link定位如下:
find_element_by_partial_link_text(“一個很長的”)
find_element_by_partial_link_text(“文字連結”)
說明: find_element_by_partial_link_text()
方法通過元素標籤對之間的部分文字資訊來定位元素。
2.7 XPath定位
XPath
是一種在XML文件中定位元素的語言。因為HTML可以看做XML的一種實現,所以Selenium使用者可以使用XPath
在web應用中來定位元素。
- 方法1:絕對路徑定位
參考前面的前端展示的程式碼,我們可以通過下面的方法來定位到百度輸入框和百度搜索按鈕
find_element_by_xpath(“/html/body/div/div/div/div/div/form/span/input”)
find_element_by_xpath(“/html/body/div/div/div/div/div/form/span[2]/input”)
說明: find_element_by_xpath()
方法使用XPath
語言來定位元素。
XPath
主要用標籤名的層級關係來定位元素的絕對路徑,最外層的是html
語言。然後在body
文字內,一級一級往下查詢,如果一個層級下有多個相同的標籤名,那麼就按照上下順序確定是第幾個,例如span[2]
表示當前層級下的第2個span
標籤。
- 方法2:利用元素屬性定位
同樣以百度輸入框和百度搜索按鈕為例,用法如下:
find_element_by_xpath(“//input[@id=’kw’]”)
find_element_by_xpath(“//input[@id=’su’]”)
說明:
//
表示當前頁面下某個目錄,input
表示定位元素的標籤名,[@id=’kw’]
表示這個元素的id
屬性值等於kw
下面通過id
、name
和class
屬性值來定位,方法如下:
find_element_by_xpath(“//input[@id=’kw’]”)
find_element_by_xpath(“//input[@name=’wd’]”)
find_element_by_xpath(“//input[@class=’s_ipt’]”)
find_element_by_xpath(“//input[@class=’bg s_btn’]”)
說明: 如果不指定標籤名,則也可以使用星號(*
)來代替。
使用XPath
不侷限於id
,name
,class
這三個屬性值,元素的任意屬性值都可以使用,只要它能唯一的標識這個元素。
例如:
find_element_by_xpath(“//input[@maxlength=255]”)
find_element_by_xpath(“//input[@autocomplete=’off’]”)
find_element_by_xpath(“//input[@type=’submit’]”)
- 方法3:層級與屬性結合
如果一個元素本身沒有可以唯一標識這個元素的屬性值,那麼我們可以找其上一級元素,如果它的上一級元素有可以唯一標識的屬性值,也可以拿來使用。
還是以定位百度輸入框和百度搜索按鈕為例,用法如下:
find_element_by_xpath(“//span [@class=’bg s_ipt_wr’]/input”)
find_element_by_xpath(“//span [@class=’bg s_btn_wr’]/input”)
說明: span [@class=’bg s_ipt_wr’]
通過class
元素定位到父元素,後面的/input
就是父元素下面的子元素。如果父元素沒有可利用的屬性值,那麼可以繼續向上找“爺爺”元素,如:
find_element_by_xpath(“//form [@id=’form’]/span/input”)
find_element_by_xpath(“//form [@id=’form’]/span[2]/input”)
- 方法4:使用邏輯運算子
如果一個屬性不能唯一區分一個元素,我們可以使用邏輯運算子連線多個屬性來定位元素。
…….
<input id=”kw” class=”su” name=”ie”>
<input id=”kw” class=”aa” name=”ie”>
<input id=”bb” class=”su” name=”ie”>
…….
如上面的三行元素,假設我們現在要定位第一行的元素,如果使用id
將會與第二行元素重名,如果使用class
將會與第三行元素重名,而如果同時使用id
和class
就會唯一的標識第一行元素,這個時候就可以通過邏輯運算子“and”
來連線這兩個條件,用法如下:
find_element_by_xpath(“//input[@id=’kw’ and class=’su’]”)
2.8 CSS定位
CSS(Cascading Style Sheets)
是一種語言,它用來描述HTML和XML文件的表現。CSS使用選擇器來為頁面元素繫結屬性。
CSS選擇器的常見語法如下:
選擇器 | 例子 | 描述 |
---|---|---|
.class | .intro | class選擇器,選擇class=“intro”的所有元素 |
#id | #firstname | id選擇器,選擇id=“firstname”的所有元素 |
* | * | 選擇所有元素 |
element | P | 元素所有 <p> 元素 |
element > element | div > input | 選擇父元素為<div> 的所有<input> 元素 |
element+ element | div + input | 選擇同一級中緊接在<div> 元素之後的所有<input> 元素 |
[attribute=value] | [target=_blank] | 選擇target=“_blank”的所有元素 |
下面同樣以百度輸入框和百度搜索按鈕為例介紹CSS定位的用法
……
<span class="bg s_ipt_wr quickdelete-wrap">
<span class="soutu-btn"></span>
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
<a href="javascript:;" id="quickdelete" title="清空" class="quickdelete" style="top: 0px; right: 0px; display: none;"></a>
</span>
<span class="bg s_btn_wr">
<input type="submit" id="su" value="百度一下" class="bg s_btn">
</span>
……
1)通過class屬性定位
find_element_by_css_selector(“.s_ipt”)
//選擇class=“s_ipt”
的元素,即百度輸入框
find_element_by_css_selector(“.bg s_btn”)
//選擇class=“bg s_btn”
的元素,即百度搜索按鈕
2)通過id屬性定位
find_element_by_css_selector(“#kw”)
//選擇id=“kw”
的元素,即百度輸入框
find_element_by_css_selector(“#su”)
//選擇id=“su”
的元素,即百度搜索按鈕
3)