『心善淵』Selenium3.0基礎 — 10、使用Seleniun定位頁面元素歸納總結(超詳細)

繁華似錦Fighting發表於2021-06-30

我們在做Web自動化測試時,最根本的就是操作頁面上的元素。因此我們對元素的定位是最基礎的工作,只有準確的定位到對應元素,才能進行後續的自動化控制,也就時操作這些元素。

我們之前用了好幾篇文章,介紹在Selenium中如何進行元素的定位:

這也同時說明了在自動化測試中,元素定位是非常重要且必須掌握的技能。那麼本篇文章是對Selenium中進行元素定位的歸納總結。

1、Selenium中8種基本元素定位方式

提示:基本元素定位方式,可以結合前面文章【Selenium基本元素定位】一起看,有詳細說明。

(1)單數形式

# webdriver提供的基本元素定位方法。
# 1. 通過元素的id屬性進行定位。
find_element_by_id("id屬性值")

# 2. 通過元素的name屬性進行定位。
find_element_by_name("name屬性值")

# 3. 通過元素的class屬性進行定位。
find_element_by_class_name("class屬性值")

# 4.通過元素標籤進行定位。
find_element_by_tag_name("標籤名")

# 5. 通過超連結中全部文字定位超連結。
find_element_by_link_text("完整超連結文字")

# 6. 通過超連結中部分連續文字定位超連結。
find_element_by_partial_link_text("部分超連結文字")

# 7. 通過XPath定位元素。
find_element_by_xpath("XPath路徑表示式")

# 8. 通過css選擇器定位元素。
find_element_by_css_selector("css選擇器定位策略")

(2)複數形式

# webdriver提供的基本元素定位方法。
# 1. 通過元素的id屬性進行定位。
find_elements_by_id("id屬性值")

# 2. 通過元素的name屬性進行定位。
find_elements_by_name("name屬性值")

# 3. 通過元素的class屬性進行定位。
find_elements_by_class_name("class屬性值")

# 4.通過元素標籤進行定位。
find_elements_by_tag_name("標籤名")

# 5. 通過超連結中全部文字定位超連結。
find_elements_by_link_text("完整超連結文字")

# 6. 通過超連結中部分連續文字定位超連結。
find_elements_by_partial_link_text("部分超連結文字")

# 7. 通過XPath定位元素。
find_elements_by_xpath("XPath路徑表示式")

# 8. 通過css選擇器定位元素。
find_elements_by_css_selector("css選擇器定位策略")

2、By類定位的8種定位方式

提示:By類定位元素,可以結合前面文章【使用Seleniun中的By類定位元素】一起看,有詳細說明。

(1)單數形式

# 1. 通過元素的id屬性進行定位。
# ("id"," ")
find_element(By.ID, "id屬性值")

# 2. 通過元素的name屬性進行定位。
# ("name", " ")
find_element(By.NAME, "name屬性值")

# 3. 通過元素的class屬性進行定位。
# ("class name", " ")
find_element(By.CLASS_NAME, "class屬性值")

# 4.通過元素標籤進行定位。
# ("tag name", " ")
find_element(By.TAG_NAME, "標籤名")

# 5. 通過超連結中全部文字定位超連結。
# ("link text", " ")
find_element(By.LINK_TEXT, "完整超連結文字")

# 6. 通過超連結中部分連續文字定位超連結。
# ("partial link text", " ")
find_element(By.PARTIAL_LINK_TEXT, "部分超連結文字")

# 7. 通過XPath定位元素。
# ("xpath", " ")
find_element(By.XPATH, "XPath路徑表示式")

# 8. 通過css選擇器定位元素。
# ("css selector", " ")
find_element(By.CSS_SELECTOR, "css選擇器定位策略")

(2)複數形式

# 1. 通過元素的id屬性進行定位。
# ("id"," ")
find_elements(By.ID, "id屬性值")

# 2. 通過元素的name屬性進行定位。
# ("name", " ")
find_elements(By.NAME, "name屬性值")

# 3. 通過元素的class屬性進行定位。
# ("class name", " ")
find_elements(By.CLASS_NAME, "class屬性值")

# 4.通過元素標籤進行定位。
# ("tag name", " ")
find_elements(By.TAG_NAME, "標籤名")

# 5. 通過超連結中全部文字定位超連結。
# ("link text", " ")
find_elements(By.LINK_TEXT, "完整超連結文字")

# 6. 通過超連結中部分連續文字定位超連結。
# ("partial link text", " ")
find_elements(By.PARTIAL_LINK_TEXT, "部分超連結文字")

# 7. 通過XPath定位元素。
# ("xpath", " ")
find_elements(By.XPATH, "XPath路徑表示式")

# 8. 通過css選擇器定位元素。
# ("css selector", " ")
find_elements(By.CSS_SELECTOR, "css選擇器定位策略")

3、XPath定位總結

提示:

頁面程式碼片段

<bookstore id='zc'>
    <book id='b1'>
        <title lang="eng">Harry Potter</title>
        <price>29.99</price>
    </book>

    <book id='b2'>
        <title lang="eng">Learning XML</title>
        <price>39.95</price>
    </book>
</bookstore>

(1)基礎定位語法

XPath 使用路徑表示式在 XML 文件中選取節點。節點是通過沿著路徑或者 step(步) 來選取的。

下面列出了最常用的路徑表示式:

表示式 描述
nodename 選取此節點的所有子節點。
/ 從根節點選取。
// 從匹配選擇的當前節點選擇文件中的節點,而不考慮它們的位置。
. 選取當前節點。
.. 選取當前節點的父節點。
@ 選取屬性。

示例

路徑表示式 說明
bookstore 選取 bookstore 元素的所有子節點。
/bookstore 選取根元素 bookstore。註釋:假如路徑起始於正斜槓(/),則此路徑始終代表到某元素的絕對路徑!
bookstore/book 選取屬於 bookstore 的子元素的所有 book 元素。
//book 選取所有 book 子元素,而不管它們在文件中的位置。
bookstore//book 選擇屬於 bookstore 元素的後代的所有 book 元素,而不管它們位於 bookstore 之下的什麼位置。
//@lang 選取名為 lang 的所有屬性。

(2)屬性定位語法

路徑表示式 說明
//標籤名[@屬性值=屬性名] 語法格式說明
//title[@lang] 選取所有擁有名為 ang 的屬性的 title 元素。
//title[@lang='eng'] 選取所有 title 元素,且這些元素擁有值為 englang 屬性。

(3)層級定位語法

路徑表示式 說明
//父標籤名[@父標籤屬性名='屬性值']/子標籤 最終定位的是子標籤
//book[@id='b1']/title 定位id屬性為b1book標籤下的title標籤
//bookstore[@id='zc']/book[@id='b1']/title 以此類推,可以增加多層

(4)索引定位語法

路徑表示式 說明
//bookstore/book 定位到bookstore標籤下所有book子節點
//bookstore/book[1] 選取屬於bookstore子元素的第一個book元素。
//bookstore/book[last()] 選取屬於 bookstore子元素的最後一個book元素。
//bookstore/book[last()-1] 選取屬於bookstore子元素的倒數第二個book元素。
//bookstore/book[last()-n] 選取屬於bookstore子元素的倒數第n個book元素。
//bookstore/book[position()=2] 定位到結果集中第n個節點。
//bookstore/book[position()<3] 選取最前面的兩個屬於bookstore元素的子元素的book元素。
//bookstore/book[position()>3] 定位到結果集中索引大於n的節點。

(6)邏輯定位語法

XPath可以支援定位條件的與(and)、或(or)、非(not)。(我們絕大部分都使用and

路徑表示式 說明
//標籤名[@屬性名1='屬性值1'and@屬性名2=屬性值2] 使用多屬性定位元素
input[@type='text'and@name='user'and@class='login-test'] and表示多定位條件同時匹配
input[@name='user'or@class='login-test'] or表示定位條件有一個匹配即可
//book[not(@id='b1')] not()方法表示條件取反
//input[@type='submit' and not(contains(@name,'fuck'))] not()方法練習

(6)模糊定位語法

XPath 萬用字元可用來選取未知的 XML 元素。

萬用字元 描述
* 匹配任何元素節點。
@* 匹配任何屬性節點。
node() 匹配任何型別的節點。

示例

在下面的表格中,我們列出了一些路徑表示式,以及這些表示式的結果:

路徑表示式 說明
//bookstore/* 選取 bookstore 元素的所有子元素。
/* 匹配絕對路徑最外層元素
//* 選取頁面中的所有元素。
//title[@*] 選取所有帶有屬性的 title 元素。
//*[@*] 匹配所有有屬性的節點(屬性模糊查詢使用很少)
/bookstore/node()/title 匹配bookstore節點所有孫子輩的title節點,代表任意節點名。

(7)其他定位語法

1)其他常用定位

路徑表示式 說明
//*[text()=“xxx”] 標籤之間的文字內容是xxx的元素
//*[contains(@attribute,’xxxxx’)] 屬性值中含有xxx的元素
//*[starts-with(@attribute,’xxx’)] 屬性值以xxx開頭的元素

2)選取若干路徑

通過在路徑表示式中使用|運算子,您可以選取若干個路徑。

例項

路徑表示式 結果
//book/title | //book/price 選取book元素的所有 titleprice 元素。
//title | //price 選取文件中的所有 titleprice 元素。
/bookstore/book/title | //price 選取屬於 bookstore 元素的 book 元素的所有 title 元素,以及文件中所有的 price 元素。

3)...

路徑表示式 說明
/bookstore/book/title/./.. 使用.定位到title本身,再使用..定位到title的父節點book
/bookstore/book/title/./../price 上邊過程後,再定位到price子節點

4)XPath 表示式中的運算子

運算子 描述 示例 返回值
| 計算兩個節點集 //book | //cd 返回所有擁有 book 和 cd 元素的節點集
+ 加法 6 + 4 10
- 減法 6 - 4 2
* 乘法 6 * 4 24
div 除法 8 div 4 2
= 等於 price=9.80 如果 price 是 9.80,則返回 true。如果 price 是 9.90,則返回 false。
!= 不等於 price!=9.80 如果 price 是 9.90,則返回 true。如果 price 是 9.80,則返回 false。
< 小於 price<9.80 如果 price 是 9.00,則返回 true。如果 price 是 9.90,則返回 false。
<= 小於或等於 price<=9.80 如果 price 是 9.00,則返回 true。如果 price 是 9.90,則返回 false。
> 大於 price>9.80 如果 price 是 9.90,則返回 true。如果 price 是 9.80,則返回 false。
>= 大於或等於 price>=9.80 如果 price 是 9.90,則返回 true。如果 price 是 9.70,則返回 false。
or price=9.80 or price=9.70 如果 price 是 9.80,則返回 true。如果 price 是 9.50,則返回 false。
and price>9.00 and price<9.90 如果 price 是 9.80,則返回 true。如果 price 是 8.50,則返回 false。
mod 計算除法的餘數 5 mod 2 1

用於XPath定位中的示例:

路徑表示式 說明
/bookstore/book[price>35.00] 選取 bookstore 元素的所有 book 元素,且其中的 price 元素的值須大於 35.00。
/bookstore/book[price>35.00]/title 選取 bookstore 元素中的 book 元素的所有 title元素,且其中的 price 元素的值須大於 35.00。

4、CSS選擇器定位總結

提示:

(1)屬性定位

CSS選擇器策略 示例 說明
#id #telA 選擇id="telA"的所有元素。
.class .telA 選擇 class="telA”的所有元素。
[屬性名=屬性值] [name=telA] 除了idclass屬性,其他屬性的定位格式
[attribute] [target] 選擇帶有target 屬性所有元素。
* * 選擇所有元素。

(2)屬性值模糊匹配定位

CSS選擇器策略 示例 說明
[attribute^=value] a[src^="https"] 選擇其src 屬性值以"https”開頭的每個<a>元素。
[attribute$=value] a[src$=".pdf"] 選擇其src屬性以".pdf“結尾的所有<a>元素。
[attribute*=value] a[src*="abc"] 選擇其src 屬性中包含“abc"子串的每個<a>元素。
[attribute~=value] a[title~=flower] 定位標籤屬性title值中有獨立flower詞彙的節點
[attribute|=value] a[lang|=en] 用於選取帶有以指定值開頭的屬性值的元素。

注意:[attribute|=value]

該值必須是整個單詞,比如 lang="en",或者後面跟著連字元,比如 lang="en-us"

(3)標籤定位

CSS選擇器策略 示例 說明
element p 定位所有<p>元素。
標籤名[屬性名=屬性值] input#telA 定位id屬性值為telA的所有<input>元素

(4)層級關係定位

CSS選擇器策略 示例 說明
element,element div,p 選擇所有<div> 元素和所有 <p> 元素。
element element div p 選擇 <div> 元素內部的所有 <p> 元素。包括子孫後代。
element>element div>p 選擇父元素為 <div> 元素的所有 <p> 元素。只包括子代。
element+element div+p 選擇緊接在 <div> 元素之後的所有 <p> 元素。同輩元素。

示例

CSS選擇器策略 示例 說明
需要使用 > 或 空格表示層級關係 此行為語法說明
父標籤名[父標籤屬性名=屬性值]>子標籤名 p#p1>input 定位id屬性值為p1<input>元素
父標籤名[父標籤屬性名=屬性值] 子標籤名 p#p1 input 同上

(5)索引定位

CSS選擇器策略 示例 說明
:only-child p:only-child 選擇屬於其父元素的唯一子元素的每個 <p> 元素。
:nth-child(n) p:nth-child(2) 選擇屬於其父元素的第二個子元素的每個 <p> 元素。
:nth-last-child(n) p:nth-last-child(2) 同上,從最後一個子元素開始計數。
:nth-of-type(n) p:nth-of-type(2) 選擇屬於其父元素第二個 <p>元素的每個 <p> 元素。
:nth-last-of-type(n) p:nth-last-of-type(2) 同上,但是從最後一個子元素開始計數。

(6)邏輯運算定位

CSS選擇器策略 示例 說明
標籤名[屬性名1=屬性值1][屬性名2=屬性值2] input[type='telA'][placeholder='電話A'] 同時匹配多個屬性,無需寫and關鍵字

(7)元素狀態定位

CSS選擇器策略 示例 說明
:empty p:empty 選擇沒有子元素的每個 <p> 元素(包括文字節點)。
:target #news:target 選擇當前活動的 #news 元素。
:enabled input:enabled 選擇每個啟用的 <input> 元素。
:disabled input:disabled 選擇每個禁用的 <input> 元素
:checked input:checked 選擇每個被選中的 <input>元素。
:not(selector) :not(p) 選擇非 <p> 元素的每個元素。

5、總結

  • 如果元素有明確idnameclass屬性時,使用對應的基本定位方法。

  • 如果沒有idnameclass屬性時,或idnameclass屬性是動態/不唯一的時候,使用XPathCSS Selector定位。

  • 定位頁面超連結使用link_textpartial_link_text定位

  • 可使用XPathCSS Selector定位的時候,優先使用CSS Selector

    CSS Selector定位的速度和效率比XPath高。

  • 沒有最好的,只有最精簡的,怎麼簡單怎麼來。

擴充套件:為什麼CSS Selector定位的速度和效率比XPath高?

結論:因為你無論用那種方式定位,最終都會轉換到CSS Selector進行元素定位。

我們可以在PyCharm中,安裝ctrl點選對應的方法,進行檢視原始碼,最終都會定位到如下程式碼:

    def find_element(self, by=By.ID, value=None):
        """
        Find an element given a By strategy and locator. Prefer the find_element_by_* methods when
        possible.

        :Usage:
            element = driver.find_element(By.ID, 'foo')

        :rtype: WebElement
        """
        if self.w3c:
            if by == By.ID:
                by = By.CSS_SELECTOR
                value = '[id="%s"]' % value
            elif by == By.TAG_NAME:
                by = By.CSS_SELECTOR
            elif by == By.CLASS_NAME:
                by = By.CSS_SELECTOR
                value = ".%s" % value
            elif by == By.NAME:
                by = By.CSS_SELECTOR
                value = '[name="%s"]' % value
        return self.execute(Command.FIND_ELEMENT, {
            'using': by,
            'value': value})['value']

說明:可以看到上面程式碼中的if語句中,所有用到的定位方式,最後都轉為對應的CSS Selector定位。

提示:我們也可以通過jsjQuery進行元素的定位,但推薦用以上總結的方式進行元素定位。

相關文章