selenium無法定位元素的幾種解決方案
1、frame/iframe表單嵌套
WebDriver只能在一個(gè)頁面上對元素識(shí)別與定位,對于frame/iframe表單內(nèi)嵌的頁面元素?zé)o法直接定位。
解決方法:
driver.switch_to.frame(id/name/obj)
switch_to.frame()默認(rèn)可以直接取表單的id或name屬性。如果沒有可用的id和name屬性,可以先定位到frame/iframe,再將定位對象傳給switch_to.frame(對象)方法。
xf = driver.find_element_by_xpath('//*[@class="if"]') driver.switch_to.frame(xf) ... driver.switch_to.parent_frame() 切到父frame。影響性能,可以提給開發(fā),讓其改進(jìn)。 driver.switch_to.default_content() 跳回最外層的頁面
2、頁面跳轉(zhuǎn)到新標(biāo)簽頁,或彈出警告框等
在頁面操作過程中有時(shí)候點(diǎn)擊某個(gè)鏈接會(huì)彈出新窗口,這時(shí)就需要切換焦點(diǎn)到新窗口上進(jìn)行操作。
解決方法1:
driver.switch_to.window(window_handle)切換到新窗口。
首先獲取當(dāng)前窗口的句柄driver.current_window_handle,接著打開彈出新窗口,獲得當(dāng)前打開的所有窗口的句柄driver.window_handles。通過for循環(huán)遍歷handle,如果不等于第一次打開窗口的句柄,那么一定是新窗口的句柄,因?yàn)閳?zhí)行過程只打開了兩個(gè)窗口;改變條件,如果等于第一次打開窗口的句柄,那么可以切換回第一次打開的窗口。
解決方法2:
對于JavaScript生成的alert、confirm以及prompt,無法使用前端工具對彈出窗口進(jìn)行定位的,使用driver.switch_to.alert方法定位彈出框。
alert的方法有:
- .accept() '等同于點(diǎn)擊“確認(rèn)”或“OK”'
- .dismiss() '等同于點(diǎn)擊“取消”或“Cancel”'
- .text '獲取alert文本內(nèi)容,對有信息顯示的alert框'
- .send_keys(text) '發(fā)送文本,對有提交需求的prompt框'
- .authenticate(username,password) '驗(yàn)證,針對需要身份驗(yàn)證的alert'
3、頁面元素失去焦點(diǎn)導(dǎo)致腳本運(yùn)行不穩(wěn)定
解決方法:
driver.switch_to.active_element 遇到腳本不穩(wěn)定,有時(shí)會(huì)失去焦點(diǎn)導(dǎo)致測試失敗的情況下,可以先切到焦點(diǎn)元素再進(jìn)行操作。注意.active_element后面不帶括號()。
下面是一個(gè)參考案例:
'最初的 “右擊鼠標(biāo) → 新建文件夾 → 輸入文件夾名稱” 的代碼'
l = driver.find_element_by_id('pm_treeRoom_1_span') ActionChains(driver).context_click(l).perform() driver.find_element_by_class_name('fnew').click() time.sleep(2) driver.find_element_by_xpath('//*[@id="pm_treeRoom_1_ul"]/li[...]').send_keys('filename') time.sleep(2)
結(jié)果這種操作總會(huì)導(dǎo)致輸入框失去焦點(diǎn),直接消失,更不能send_keys進(jìn)去了,直接報(bào)錯(cuò)。
'修改后的代碼如下'
driver.find_element_by_class_name('fnew').click() time.sleep(2) driver.switch_to.active_element.send_keys('filename') time.sleep(2)
4、使用Xpath或CSS定位
find_element_by_xpath("//標(biāo)簽[屬性='值']")
使用Xpath/CSS方法,非常適合定位屬性值動(dòng)態(tài)生成、不容易定位的元素。如果不想指定標(biāo)簽,則可以使用“*”代替,使用xpath不局限于id、name和class這三個(gè)屬性,元素的任意屬性值都可以使用,只要它能唯一的標(biāo)識(shí)一個(gè)元素。
解決方法1:
如果一個(gè)元素沒有唯一屬性,那么我們可以一級一級向上查找,直到找到可以唯一定位元素的屬性,再向下查找其子元素。
find_element_by_xpath("//form[@id='form']/span[2]/input") 首先通過唯一標(biāo)識(shí)屬性id=form定位最外層元素,接著找到最外層元素下的第2個(gè)span標(biāo)簽的元素為父元素,最后向下查找定位到父元素下標(biāo)簽為input的子元素。
解決方法2:
如果一個(gè)屬性不能唯一地區(qū)分一個(gè)元素,那么使用多個(gè)屬性來唯一地定位一個(gè)元素。
find_element_by_xpath("//input[@id='kw'and@class='su']/span/input") 首先找到標(biāo)簽為input,id=kw且class=su的元素,接著找到其下標(biāo)簽為span的子元素,繼續(xù)向下查找找到標(biāo)簽為input的子元素。
解決方法3:
檢查Xpath描述是否有誤,導(dǎo)致無法定位到元素。
5、頁面還沒加載出來就對頁面上的元素進(jìn)行操作
因?yàn)榧虞d元素延時(shí)造成的腳本失敗,我們可以通過設(shè)置等待時(shí)間來提升自動(dòng)化腳本的穩(wěn)定性。
解決方法1:
WebDriverWait()顯示等待。等待單個(gè)的元素加載,通常配合until()、until_not()方法使用。
即,WebDriverWait(driver, 超時(shí)時(shí)長, 調(diào)用頻率, 忽略異常).until(可執(zhí)行方法, 超時(shí)時(shí)返回的信息)
WebDriverWait(driver,5,1).until(expected_conditions.presence_of_element_located(By.ID,'kw'))
最長等待時(shí)間為5s,每隔1秒檢查一次id='kw'的元素是否被加載在DOM樹里(并不代表該元素一定可見)。最常用的method是expected_conditions類提供的預(yù)期條件判斷。
is_disappeared= WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).until_not(lambda x: x.find_element_by_id('someId').is_displayed())
最長等待時(shí)間為30s,每隔1秒檢查一次id='someId'的元素是否從DOM樹里消失,忽略默認(rèn)異常信息NoSuchElementException 和指定的異常信息ElementNotVisibleException。此處匿名函數(shù)lambda的用法具體參考Python語法。
解決方法2:
driver.implicitly_wait(秒) 隱式等待。全局等待,對所有元素設(shè)置超時(shí)時(shí)間,等待頁面的加載,因此只需要設(shè)置一次即可。這里的時(shí)間是最長等待時(shí)間(非固定等待時(shí)間)。
解決方法3:
sleep(秒)線程等待。休眠固定的時(shí)間,使用時(shí)需要先引入time模塊的sleep方法from time import sleep。
6、元素被遮擋,不可用,不可見
解決方法1:
driver.maximize_window()由于窗口大小改變引起的頁面元素布局發(fā)生變化,被測元素被遮擋,可以先將窗口最大化,再進(jìn)行元素定位。
解決方法2:
.is_enabled()由于業(yè)務(wù)原因元素在某些情況下不可用(元素屬性disabled,灰顯),首先檢查測試步驟是否符合業(yè)務(wù)邏輯,其次確認(rèn)是否為業(yè)務(wù)流程上的Bug。
解決方法3:
.is_displayed()對于屬性不一定可見的元素,在定位前首先判斷其屬性是否可見,是否被隱藏。
解決方法4:
由于布局不合理導(dǎo)致的元素被遮蓋、或是元素本身缺失引起的無法定位問題屬于Bug,可以提給開發(fā)讓其改進(jìn)。
7、用WebDriver調(diào)用JavaScript代碼代替無法實(shí)現(xiàn)的功能
對于有些WebDriver沒有提供的方法或者無法實(shí)現(xiàn)的功能,WebDriver提供了driver.execute_script()方法來執(zhí)行JavaScript代碼。
解決方法:
如果頁面內(nèi)容過長,窗口最大化也無法查看到所有元素,可以通過執(zhí)行JavaScript腳本實(shí)現(xiàn)滾動(dòng)條的拖動(dòng)等動(dòng)作。
driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
以上語句實(shí)現(xiàn)了拉動(dòng)頁面到底部的功能,其中window.scrollTo(左邊距,上邊距)是JavaScript中用于設(shè)置瀏覽器窗口滾動(dòng)條的水平和垂直位置的代碼。
text = "input text" driver.execute_script("var obj=document.getElementById('text'); obj.value=' " + text + " ';")
假設(shè)一個(gè)輸入框可以通過id='text'將其定位,卻不能通過send_keys()輸入文本內(nèi)容,可以借助JavaScript代碼來實(shí)現(xiàn)。
video = driver.find_element_by_xpath("body/Section[1]/div/video") url = driver.execute_script("return arguments[0].currentSrc;", video) print(url) '返回文件播放地址' print("start") '播放視屏' driver.execute_script("return arguments[0].play()", video) sleep(15) '播放15秒鐘' print(stop) '暫停視屏' driver.execute_script("arguments[0].pause()", video) ...
以上實(shí)現(xiàn)了HTML5視屏<video>標(biāo)簽的部分測試,更多內(nèi)容參考HTML DOM Video對象。
其中arguments是JavaScript的內(nèi)置對象。因?yàn)閷ideo對象傳給了arguments,所以arguments[0]相當(dāng)于JavaScript腳本的document.getElementsByTagName("video")。JavaScript不支持重載,使用arguments對象可以模擬函數(shù)重載效果。
8、WebDriver無法操作Windows控件
文件的普通上傳和下載(參考How to auto save files using custom Firefox profile ?),可以通過..send_keys('本地路徑')和find_element_by_partial_link_text('下載鏈接名').click()實(shí)現(xiàn)。
解決方法:
對于插件上傳,需要操作Windows控件的,可以通過安裝AutoIt工具、編寫腳本、保存為“.au3”文件、轉(zhuǎn)換成“.exe”文件,再由自動(dòng)化腳本os.system("D:\\upfile.exe")實(shí)現(xiàn)上傳/下載。
* 雖然這種方法可以解決文件上傳、下載的操作問題,但是并不推薦。因?yàn)橥ㄟ^python調(diào)用exe程序并不在python的可控范圍內(nèi),執(zhí)行多長時(shí)間,執(zhí)行過程是否出錯(cuò),都無從自動(dòng)化過程得知。
9、firefox安全性強(qiáng),不允許跨域調(diào)用出現(xiàn)報(bào)錯(cuò)
錯(cuò)誤描述:
uncaught exception: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIDOMNSHTMLDocument.execCommand]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location:
解決辦法:
Firefox 要取消XMLHttpRequest的跨域限制的話,
第一是從 about:config 里設(shè)置 signed.applets.codebase_principal_support = true;(地址欄輸入about:config 即可進(jìn)行firefox設(shè)置);
第二就是在open的代碼函數(shù)前加入類似如下的代碼:
try { netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead"); } catch (e) { alert("Permission UniversalBrowserRead denied."); }
以上就是selenium無法定位元素的幾種解決方案的詳細(xì)內(nèi)容,更多關(guān)于selenium無法定位元素的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
13個(gè)最常用的Python深度學(xué)習(xí)庫介紹
這篇文章主要介紹了13個(gè)最常用的Python深度學(xué)習(xí)庫介紹,具有一定參考價(jià)值,需要的朋友可以參考下。2017-10-10Tensorflow 自定義loss的情況下初始化部分變量方式
今天小編就為大家分享一篇Tensorflow 自定義loss的情況下初始化部分變量方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01Python光學(xué)仿真學(xué)習(xí)處理高斯光束分布圖像
這篇文章主要為大家介紹了Python光學(xué)仿真學(xué)習(xí)之如何處理高斯光束的分布圖像,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-10-10詳解使用PyInstaller將Pygame庫編寫的小游戲程序打包為exe文件
這篇文章主要介紹了詳解使用PyInstaller將Pygame庫編寫的小游戲程序打包為exe文件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-08-08python人工智能tensorflow優(yōu)化器Optimizer算法匯總
這篇文章主要為大家介紹了python人工智能tensorflowtf優(yōu)化器Optimizer算法匯總,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05Python正則表達(dá)式匹配數(shù)字和小數(shù)的方法
這篇文章主要介紹了Python正則匹配數(shù)字和小數(shù)的方法,本文通過示例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-07-07python 實(shí)現(xiàn)format進(jìn)制轉(zhuǎn)換與刪除進(jìn)制前綴
這篇文章主要介紹了python 實(shí)現(xiàn)format進(jìn)制轉(zhuǎn)換與刪除進(jìn)制前綴的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03