通常,我們這頁面中定位一個元素,如果HTML中明明有卻定位不到,我們一定會從這兩個方面考慮。
第一:是不是頁面中有多個iframe/frame結構,很多情況下我們需要通過切換iframe/frame結構來定位,如果頁面中存在iframe/frame的情況,我們先要排查是否是因為我們的driver所在位置與我們要定位的element不在同一iframe/frame中,排查方法:查看HTML結構,頁面中找到我們要定位的元素,一級一級向上,如果被直至確定其最上級是一個iframe/frame,並且確認driver當前所在位置不被包含於iframe/frame結構中;我們要做的就是將我們的driver切換至這個iframe/frame結構中再定位。
例子:
假如,我們的driver所在在’‘且不被包含於iframe結構中,我們要定位iframe 表單結構中的‘My97DatePicker’這個元素,我們要先將driver切換至iframe結構中–driver.switch_to.frame() 然后再定位我們的要定位的元素。 這里的的難點應該是關於iframe的定位:driver.switch_to.frame() 這個方法“()”中可以是iframe的id/name(如果是固定的),也可是一個Webelement(這個可以通過定位iframe來獲取)
我這里,由於iframe沒有id和name(當你遇到的id/name是隨機的時候也可以這樣),思路:我的driver在iframe的上一級,在整個HTML中搜索iframe有且只有一個iframe結構,所有我利用標簽(driver.find_elemen_by_tag("iframe"))來定位,然后切換結構層,定位我們要定位的元素
,腳本實現:
Webelement = driver.find_elemen_by_tag(“iframe”)
driver.switch_to.frame(Webelement )
driver.find_element_by_link_text(“My97DatePicker”)
iframe/frame的切換方法還有很多,大家自己普及(有時間我會考慮出一篇相關思路整理發表)
第二:是否不顯示在頁面中。隨着JavaScript的普及,很多元素的定位我們都得考慮是否這個元素被觸發為可見狀態了。
下面列舉兩種需要出發的情況:
1、元素被包含在下拉列表中,不點擊下列表時無法選中。
這種情況很好結局,無非就是先定位並點擊列表,在定位我們要定位的元素
2、元素被包含在提示框中,鼠標得懸浮在其上才能觸發JavaScript,元素才可見被選中。
這種情況,我們就需要引用鼠標懸浮的方法,腳本實現:
引用selenium公共方法 ActionChains
from selenium.webdriver.common.action_chains import ActionChains
鼠標懸浮至element上:
Webelement = driver.find_elemen_by_xxx (element)
ActionChains(driver).move_to_element(Webelement).perform()
然后再定位我們的元素。
黑科技:
排除上面兩種我們還定位不到元素的思路:
組合定位方法
定位頁面中所有相同的元素(class_name相同、xpath相同、css相同、tag_name相同…等等),再通過元素的屬性值來篩選達到定位至該元素(當你死活定位不到這個元素的時候開業嘗試)
例子,舉例通過不同的定位方式定位頁面中相同元素:
<div class="J_adv" data-view="true" data-mod="ad_popu_259" data-mtp="66" data-order="806" data-con="ad_content_3933"></div>
方法一: find_element_by_xpath(‘//*[@id=”feedlist_id”]/div‘)
方法二:find_element_by_class_name(‘J_adv’)
方法三:
for element in find_element_by_xpaths('//*[@id=”feedlist_id”]/div'): \ ''' 這些if都是限定條件,根據就是 element.get_attribute() 這個方法,這個方法可以獲取WebElement的任何屬性。 這時,我們就可以根據 WebElment 的任何屬性來限定我們要定位的元素 ''' if element.get_attribute('class') == 'J_adv': if element.get_attribute('data-view')=='true': if element.get_attribute('data-mod')=='ad_popu_259': element.click()
同樣的,我們還能使用這么些方法去限定: element.is_displayed():返回元素結果是否可見(True 或 False) #常用 element.is_selected():返回元素結果是否被選中(True 或 False) #一般不用 還是寫文章不會寫啊,我感覺自己想表達的東西還是沒有完全表達出來,我是真心想讓每個對webelement定位覺得困難的朋友有所收獲,唉~文筆不夠啊。 另外總結一下經驗之談的兩種定位不到元素的情況: 1、頁面未完全加載:這種情況可以嘗試使用顯性等待、強制等待等方式: 顯性等待:
from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.common.by import By locator = (By.XPATH, element) #顯性等待頁面中所有元素 WebDriverWait(driver, 15, 0.5).until(EC.visibility_of_all_elements_located(locator)) #等待頁面中是至少一個元素存在 WebDriverWait(driver, 20, 0.5).until(EC.presence_of_element_located(locator)) #處理這些還有很多大家自己去拓展
強制等待: import time time.sleep(2) 2、頁面加載完成元素需要JavaScript的渲染,未渲染完全 這里和大家說一下,如果頁面加載完成一般這個元素都是可以在頁面中獲取了,但是在未渲染完全的情況下是不可見的,所以我們可以通過上面的顯性等待、強制等待、或者 一些 循環語句結合 element.is_displayed() 來達到效果。
總結:定位元素失敗只有三種原因:遮罩層、表單結構、渲染時間。