Selenium 系列篇(二):元素定位
點擊上方“AirPython”,選擇“加為星標(biāo)”
第一時間關(guān)注 Python 技術(shù)干貨!

1. 元素定位的重要性
無論是做自動化測試,還是爬蟲,頁面元素定位?永遠(yuǎn)都是第一步,在沒有定位到網(wǎng)頁元素之前,任何自動化操作都沒法進(jìn)行。
Selenium WebDriver API 中提供了大量的方法幫助我們進(jìn)行元素定位。
2. 常用方式
Selenium ?常用的元素定位方式包含:id、name、class。
前端工程師在編寫 Web網(wǎng)站的時候,大部分的網(wǎng)頁標(biāo)簽都會包含 id、name、class?中的其中一個或者多個。
其中,一個頁面內(nèi)的 id 一般具有唯一性,也是使用最多的一種元素定位方式;name、class?分別對應(yīng)網(wǎng)頁標(biāo)簽的name 屬性、class 屬性。
打開目標(biāo)網(wǎng)頁,按?F12?鍵打開開發(fā)者調(diào)試工具,定位到元素標(biāo)簽,如果存在?id 、name、class 屬性,就可以使用?id 、name、class 中的其中一個來定位到元素,

?具體的使用方法如下:
#?使用?id?定位?????
driver.find_element_by_id("element_id")
#?使用?name?定位???
driver.find_element_by_name("element_name")
#?使用?class?定位
driver.find_element_by_class_name("element_class")3. Xpath
Xpath在 XML 文檔中本身是一種元素定位語言,而 HTML 是 XML 是另外一種實現(xiàn),在元素定位的時候會遍歷頁面的所有元素,所以查詢效率不高。
Selenium 中 Xpath 定位方式包含:絕對路徑定位、屬性定位、元素關(guān)系定位、運算符、匹配等。
絕對路徑定位:相當(dāng)于從最頂部的 html 元素標(biāo)簽往子標(biāo)簽追加,一直定位到目標(biāo)元素標(biāo)簽,這種方式不常用。
driver.find_element_by_xpath('/html/body/div/.../div/目標(biāo)元素')
實際上在做?App 端自動化?的時候,Appium / Airtest?元素定位的時候,某些元素沒有任何屬性和可用的層級關(guān)系定位方式,這時候借助絕對定位是唯一的選擇。
屬性定位:對應(yīng)網(wǎng)頁元素標(biāo)簽的任意屬性,只要能唯一標(biāo)識目標(biāo)元素即可。
屬性定位很簡單,可以顯式的指定目標(biāo)元素的標(biāo)簽名或用?*?號匹配任意標(biāo)簽名,使用格式是:'//元素標(biāo)簽[@屬性名="屬性值"]'
#?1、通過標(biāo)簽名來定位
driver.find_element_by_xpath('//div[@id="element_id"]')
#?2、也可以用*號代替
driver.find_element_by_xpath('//*[@name="element_name"]')
元素關(guān)系定位:當(dāng)一個元素標(biāo)簽沒有任何屬性值,但是父元素標(biāo)簽存在唯一的屬性值,這時候可以先找到父元素標(biāo)簽,然后再找到自己。
#?通過父元素標(biāo)簽找到自己
#?父元素標(biāo)簽含有屬性值?class?=?parent_class
#?子元素標(biāo)簽為a
driver.find_element_by_xpath('//div[@class="parent_class"]/a")
運算符定位:頁面可能多個元素包含同一個屬性,這時候可以使用邏輯元素符?and?連接多個屬性來定位元素標(biāo)簽。
#?通過多個屬性值來唯一定位元素標(biāo)簽
driver.find_element_by_xpath('//div[@屬性1="屬性1的值"?and?@屬性2="屬性2的值"]')
匹配定位:匹配定位平常使用不多,主要是利用屬性中包含某個字符串來定位元素標(biāo)簽,包含:contains、starts_with
#?匹配定位
# class屬性值中包含:class
driver.find_element_by_xpath('//div[contains(@class,"part_str")]')
#?class屬性值以part_start開頭
//input[starts-with(@class,'part_start')]?????
實際上,網(wǎng)頁元素標(biāo)簽的 Xpath 表達(dá)式可以使用 Chrome 右鍵屬性或者 Xpath Chrome 插件去快速獲取。

4. CSS Selector
CSS Selector 是利用 CSS 選擇器來定位元素,相比 Xpath,語法更簡潔,元素定位速度更快一點。
常見的選擇器包含:class、id 兩種,使用方式如下:
#?利用元素class來定位
driver.find_element_by_css_selector(".element_class")
#?利用元素id來定位
driver.find_element_by_css_selector("#element_id")
和 Xpath 一樣,CSS Selector 元素沒有任何可用的屬性值時,可以使用?層級關(guān)系先定位?到父元素標(biāo)簽,然后再找到自己。
#?利用元素層級關(guān)系進(jìn)行定位
driver.find_element_by_css_selector("parent_div?>?target_element_div")
屬性定位:在 CSS Selector 中也很常見,使用方式如下:
#?屬性定位
driver.find_element_by_css_selector('[屬性名=屬性值]')
需要注意的是,屬性定位必須確保在當(dāng)前頁面內(nèi),這個屬性具有唯一性。
組合定位:將上面的定位方式結(jié)合在一起,即可以加強元素的唯一性,精準(zhǔn)快速地定位到元素標(biāo)簽。
#?組合定位
#?父元素:parent_div,class = parent_class
#?目標(biāo)元素:targent_div,id = targent_id
driver.find_element_by_css_selector("parent_div.parent_class?>?targent_div#targent_id")
5. 不常用方式
上面的元素定位方式都很常用,下面這些定位方式幾乎用不到,包含:
Tag 定位:利用 Tag 標(biāo)簽名去定位,一般網(wǎng)頁中都會包含多個 Tag,所以利用 Tag 去元素定位不實用。
# Tag定位,比如:tag為input
element_by_input_tag?=?driver.find_element_by_tag_name("input")
link 定位:link 定位是針對 a 標(biāo)簽中的文本匹配。
由于很多網(wǎng)頁元素都是動態(tài)變化的,文本匹配經(jīng)常需要修改,所以靈活性不高,很少使用。
#?比如:
#?百度一下
#?使用link來定位
driver.find_element_by_link_text("百度一下")
partial link 定位:相比 link 定位,相當(dāng)于 a 標(biāo)簽內(nèi)容局部匹配,只要包含待匹配的內(nèi)容,即使要查找的元素。
#?比如:
#?百度一下
#?使用?partial?link?來定位來定位
driver.find_element_by_link_text("百度")6. By + elements
Selenium 提供的查找方法還提供了另外一種形式,即通過:By( 定位方式,定位內(nèi)容值 )
實際上,對自動化做 Page Object 設(shè)計?的時候,一般都會用 By 的方式來封裝代碼,更易于我們維護(hù)代碼。
使用方式如下:
#?1、導(dǎo)入依賴類
from?selenium.webdriver.common.by?import?By
#?2、使用
driver.find_element(By.ID,?"element_id")
driver.find_element(By.NAME,?"element_name")
driver.find_element(By.CLASS_NAME,?"element_class_name")
driver.find_element(By.TAG_NAME,?"element_tag_name")
driver.find_element(By.LINK_TEXT,?"element_link_text")
driver.find_element(By.PARTIAL_LINK_TEXT,?"element_partial_link_text")
driver.find_element(By.XPATH,?"http://*[@class='element_xpath']")
driver.find_element(By.CSS_SELECTOR,?"element_css_selector")
上面查找元素的方法都是針對單個元素標(biāo)簽,如果要查找匹配多個元素,只需要將 element 改成 elements 即可。
#?單個元素
driver.find_element(By.ID,?"element_id")
#?多個元素
driver.find_elements(By.ID,?"element_id")
Selenium 元素定位的內(nèi)容差不多就這些了,下一篇將聊聊 Selenium 具體應(yīng)用場景的使用方式。

???
