1. 程式人生 > >WebDriver API之元素定位

WebDriver API之元素定位

CSS定位

CSS 可以比較靈活選擇控制元件的任意屬性,一般情況下定位速度要比 XPath 快。

css選擇器常見語法
image

<span class="bg s_ipt_wr">
<input id="kw" class="s_ipt" autocomplete="off"
maxlength="100" value="" name="wd">
</span>
<span class="bg s_btn_wr">
<input id="su" class="bg s_btn" type="submit"
value="百度一下">
</span>

通過 class 屬性定位:

find_element_by_css_selector(".s_ipt")
find_element_by_css_selector(".bg s_btn")

find_element_by_css_selector()方法用於 CSS 語言定位元素,點號(.)表示通過 class 屬性來定位元素。

通過 id 屬性定位:

find_element_by_css_selector("#kw")
find_element_by_css_selector("#su")

井號(#)表示通過 id 屬性來定位元素。

通過標籤名定位:

find_element_by_css_selector(“input”)
在 CSS 語言中用標籤名定位元素不需要任何符號標識,直接使用標籤名即可,但我們前面已經瞭解到
標籤名重複的概率非常大,所以通過這種方式很難唯一的標識一個元素。

通過父子關係定位:

find_element_by_css_selector(“span>input”)
上面的寫法表示有父親元素,它的標籤名叫 span,查詢它的所有標籤名叫 input 的子元素。

通過屬性定位:

find_element_by_css_selector("input[autocomplete='off']")
find_element_by_css_selector("input[maxlength='100']")
find_element_by_css_selector("input[type='submit']")

在 CSS 當中也可以使用元素的任意屬性,只要這些屬性可以唯一的標識這個元素。

組合定位:

我們當然可以把上面的定位策略組合起來使用,這樣就大大加強了元素的唯一性。

find_element_by_css_selector("span.bg s_ipt_wr>input.s_ipt")
find_element_by_css_selector("span.bg s_btn_wr>input#su")

有一個父元素,它的標籤名叫 span,它有一個 class 屬性值叫 bg s_ipt_wr,它有一個子元素,標籤名
叫 input,並且這個子元素的 class 屬性值叫 s_ipt。好吧!我們要找的就是具有這麼多特徵的一個子元素。

XPath定位

利用元素屬性定位

find_element_by_xpath("//input[@id='kw']")

find_element_by_xpath("//input[@id='su']")
//表示當前頁面某個目錄下,input 表示定位元素的標籤名,[@id='kw'] 表示這個元素的 id 屬性值等於
kw。

下面通過 name 和 class 屬性值來定位。
find_element_by_xpath("//input[@id='wd']")
find_element_by_xpath("//input[@class='s_ipt']")
find_element_by_xpath("//*[@class='bg s_btn']")

如果不想指定標籤名也可以用星號(*)代替。當然,使用 XPath 不僅僅只侷限在 id、name 和 class 這
三個屬性值,元素的任意屬性值都可以使用,只要它能唯一的標識一個元素。

find_element_by_xpath("//input[@maxlength='100']")
find_element_by_xpath("//input[@autocomplete='off']")
find_element_by_xpath("//input[@type='submit']")

層級與屬性結合

如果一個元素本身並沒有可以唯一標識這個元素的屬性值,我們可以找其上一級元素,如果它的上級
有可以唯一標識屬性的值,也可以拿來使用。參考 baidu.html 文字。

……
<form id="form" class="fm" action="/s" name="f">
    <input type="hidden" value="utf-8" name="ie">
    <input type="hidden" value="8" name="f">
    <input type="hidden" value="1" name="rsv_bp">
    <input type="hidden" value="1" name="rsv_idx">
    <input type="hidden" value="" name="ch">
    <input type="hidden" value="02.." name="tn">
    <input type="hidden" value="" name="bar">
    <span class="bg s_ipt_wr">
    <input id="kw" class="s_ipt" autocomplete="off"
    maxlength="100" value="" name="wd">
    </span>
    <span class="bg s_btn_wr">
    <input id="su" class="bg s_btn" type="submit"
    value="百度一下">
    </span>
……

假如百度輸入框本身沒有可利用的屬性值,我們可以查詢它的上一級屬性。

ind_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 也就表示父元素下面標籤名為
input 的子元素。如果父元素沒有可利用的屬性值,那麼可以繼續向上查詢“爺爺”元素。

find_element_by_xpath("//form[@id='form']/span/input")
find_element_by_xpath("//form[@id='form']/span[2]/input")

我們可以通過這種方法一級一級的向上打找,直到找到最外層的html標籤,那麼就是一個絕對路徑
的寫法了。

使用邏輯運算子

如果一個屬性不能唯一的區分一個元素,我們還可以使用邏輯運算子連線多個屬性來區別於其它屬
性。

……
<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 就會唯一的標識這個元素。那麼這個時候就
可以通過邏輯運算子號連線。

find_element_by_xpath("//input[@id='kw' and @class='su']/span/input")

當然,我們也可以用 and 連線更多的屬性來唯一的標識一個元素。

id和name定位

find_element_by_id("kw")
find_element_by_name("wd")

class定位

find_element_by_class_name()方法用於元素中 class 屬性的定位。

find_element_by_class_name("s_ipt")

tag定位

tag 定位取的是一個元素的標籤名,通過標籤名去定位單個元素的唯一性最底,因為在一個頁面中有太多的元素標籤為< div>和了,所以很難通過標籤名去區分不同的元素。

通過標籤名定位百度首頁上的輸入框與百度搜索按鈕:

find_element_by_tag_name("input")

find_element_by_tag_name()方法通過元素的 tag name 來定位元素。通過上面的例子,我們並不能區別
不同的元素,因為在一個頁面上標籤名相同很難以避免。

link定位

ink 定位與前面介紹的幾種定位方法有所不同,它專門用來定位本連結。百度輸入框上面的幾個文字
連結的程式碼如下:

<a class="mnav" name="tj_trnews" href="http://news.baidu.com">新聞</a>
<a class="mnav" name="tj_trhao123" href="http://www.hao123.com">hao123</a>

通過檢視上面的程式碼,我們發現通過 name 屬性定位是個不錯的選擇。不過我們這裡為了要學習 link
定位,通過 link 定位實現如下:

find_element_by_link_text("新聞")
find_element_by_link_text("hao123")

find_element_by_link_text()方法通過元素標籤對之間的文字資訊來定位元素。不過,需要強調的是
Python2 對於中文的支援並不好,如查 Python 在執行中文的地方出現在亂碼,可以在中檔案字串的前面
加個小“u”可以有效的避免亂碼的問題,加 u 的作用是把中文字串轉換中 unicode 編碼,如:

find_element_by_link_text(u"新聞")

parial link 定位是對 link 定們的一個種補充,有些文字連線會比較長,這個時候我們可以取文字連結的有一部分定位,只要這一部分資訊可以唯一的標識這個連結。

<a class="mnav" name="tj_lang" href="#">一個很長很長的文字連結</a>

通過 partial link 定位如下:

find_element_by_partial_link_text("一個很長的")
find_element_by_partial_link_text("文字連線")

find_element_by_link_text()方法通過元素標籤對之間的==部分文字資訊==來定位元素。

用 By 定位元素

from selenium.webdriver.common.by import By

find_element(By.ID,"kw")
find_element(By.NAME,"wd")
find_element(By.CLASS_NAME,"s_ipt")
find_element(By.TAG_NAME,"input")
find_element(By.LINK_TEXT,u"新聞")
find_element(By.PARTIAL_LINK_TEXT,u"新")
find_element(By.XPATH,"//*[@class='bg s_btn']")
find_element(By.CSS_SELECTOR,"span.bg s_btn_wr>input#su")