Selenium無法定位元素的九種解決方案

一阅酪、frame/iframe表單嵌套

WebDriver只能在一個頁面上對元素識別與定位框全,對于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() 跳回最外層的頁面

二留量、頁面跳轉(zhuǎn)到新的標(biāo)簽頁,或者彈出的警告框等

在頁面操作過程中有時候點(diǎn)擊某個鏈接會彈出新窗口哟冬,這時就需要切換焦點(diǎn)到新窗口上進(jìn)行操作楼熄。
解決方法1driver.switch_to.window(window_handle)切換到新窗口。
首先獲取當(dāng)前窗口的句柄driver.current_window_handle浩峡,接著打開彈出新窗口可岂,獲得當(dāng)前打開的所有窗口的句柄driver.window_handles。通過for循環(huán)遍歷handle翰灾,如果不等于第一次打開窗口的句柄缕粹,那么一定是新窗口的句柄,因?yàn)閳?zhí)行過程只打開了兩個窗口纸淮;改變條件平斩,如果等于第一次打開窗口的句柄,那么可以切換回第一次打開的窗口萎馅。
解決方法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'
三、頁面元素失去焦點(diǎn)導(dǎo)致腳本運(yùn)行不穩(wěn)定

解決方法driver.switch_to.active_element 遇到腳本不穩(wěn)定皆撩,有時會失去焦點(diǎn)導(dǎo)致測試失敗的情況下扣墩,可以先切到焦點(diǎn)元素再進(jìn)行操作。注意.active_element后面不帶括號()扛吞。
下面是一個參考案例呻惕。

'最初的 “右擊鼠標(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é)果這種操作總會導(dǎo)致輸入框失去焦點(diǎn),直接消失滥比,更不能send_keys進(jìn)去了亚脆,直接報(bào)錯。

'修改后的代碼如下'
driver.find_element_by_class_name('fnew').click()
time.sleep(2)
driver.switch_to.active_element.send_keys('filename')
time.sleep(2)
四盲泛、使用Xpath或CSS定位

find_element_by_xpath("http://標(biāo)簽[屬性='值']")
使用Xpath/CSS方法濒持,非常適合定位屬性值動態(tài)生成键耕、不容易定位的元素。如果不想指定標(biāo)簽柑营,則可以使用“*”代替屈雄,使用xpath不局限于id、name和class這三個屬性官套,元素的任意屬性值都可以使用酒奶,只要它能唯一的標(biāo)識一個元素。
解決方法1:如果一個元素沒有唯一屬性虏杰,那么我們可以一級一級向上查找讥蟆,直到找到可以唯一定位元素的屬性,再向下查找其子元素纺阔。
find_element_by_xpath("http://form[@id='form']/span[2]/input") 首先通過唯一標(biāo)識屬性id=form定位最外層元素瘸彤,接著找到最外層元素下的第2個span標(biāo)簽的元素為父元素,最后向下查找定位到父元素下標(biāo)簽為input的子元素笛钝。
解決方法2:如果一個屬性不能唯一地區(qū)分一個元素质况,那么使用多個屬性來唯一地定位一個元素。
find_element_by_xpath("http://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)致無法定位到元素。

五蝎土、頁面還沒有加載出來视哑,就對頁面上的元素進(jìn)行的操作

因?yàn)榧虞d元素延時造成的腳本失敗,我們可以通過設(shè)置等待時間來提升自動化腳本的穩(wěn)定性誊涯。
解決方法1WebDriverWait() 顯示等待挡毅。等待單個的元素加載,通常配合until()暴构、until_not()方法使用跪呈。

WebDriverWait(driver,timeout,poll_frequency=0.5,ignored_exceptions=None)
- driver - 傳入WebDriver實(shí)例,必填
- timeout - 最長等待時間取逾,必填
- poll_frequency - 調(diào)用`until`/`until_not`方法的時間間隔耗绿,默認(rèn)為0.5秒,可省砾隅。
- ignored_exceptions - 忽略異常缭乘,默認(rèn)僅包含NoSuchElementException,可省。
WebDriverWait(driver,10).until(method,message='')     '等待目標(biāo)出現(xiàn)'
WebDriverWait(driver,5,1).until_not(method,message='')    '等待目標(biāo)消失'
- method - 必填堕绩。
- message - 默認(rèn)為空,可省邑时。如果超時奴紧,拋出TimeoutException,返回message信息晶丘。

即黍氮,WebDriverWait(driver, 超時時長, 調(diào)用頻率, 忽略異常).until(可執(zhí)行方法, 超時時返回的信息)

WebDriverWait(driver,5,1).until(expected_conditions.presence_of_element_located(By.ID,'kw'))

最長等待時間為5s,每隔1秒檢查一次id='kw'的元素是否被加載在DOM樹里(并不代表該元素一定可見)浅浮。最常用的methodexpected_conditions類提供的預(yù)期條件判斷沫浆。

is_disappeared = WebDriverWait(driver, 30, 1, (ElementNotVisibleException)).until_not(lambda x: x.find_element_by_id('someId').is_displayed())

最長等待時間為30s,每隔1秒檢查一次id='someId'的元素是否從DOM樹里消失滚秩,忽略默認(rèn)異常信息NoSuchElementException 和指定的異常信息ElementNotVisibleException专执。此處匿名函數(shù)lambda的用法具體參考Python語法。
解決方法2driver.implicitly_wait(秒) 隱式等待郁油。全局等待本股,對所有元素設(shè)置超時時間,等待頁面的加載桐腌,因此只需要設(shè)置一次即可拄显。這里的時間是最長等待時間(非固定等待時間)。
解決方法3sleep(秒) 線程等待案站。休眠固定的時間躬审,使用時需要先引入time模塊的sleep方法from time import sleep

六蟆盐、元素被遮擋承边,不可用,不可見

解決方法1driver.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)蜒灰。

七弦蹂、使用WebDriver調(diào)用JavaScript代碼代替無法實(shí)現(xiàn)的功能

對于有些WebDriver沒有提供的方法或者無法實(shí)現(xiàn)的功能,WebDriver提供了driver.execute_script()方法來執(zhí)行JavaScript代碼强窖。
解決方法:如果頁面內(nèi)容過長凸椿,窗口最大化也無法查看到所有元素,可以通過執(zhí)行JavaScript腳本實(shí)現(xiàn)滾動條的拖動等動作翅溺。

driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

以上語句實(shí)現(xiàn)了拉動頁面到底部的功能脑漫,其中window.scrollTo(左邊距,上邊距)是JavaScript中用于設(shè)置瀏覽器窗口滾動條的水平和垂直位置的代碼咙崎。

text = "input text"
driver.execute_script("var obj=document.getElementById('text'); obj.value=' " + text + " ';")

假設(shè)一個輸入框可以通過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[0]跛璧,所以arguments[0]相當(dāng)于JavaScript腳本的document.getElementsByTagName("video")。JavaScript不支持重載新啼,使用arguments對象可以模擬函數(shù)重載效果追城。

八、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”文件火诸,再由自動化腳本os.system("D:\\upfile.exe")實(shí)現(xiàn)上傳/下載。
* 雖然這種方法可以解決文件上傳荠察、下載的操作問題置蜀,但是并不推薦。因?yàn)橥ㄟ^python調(diào)用exe程序并不在python的可控范圍內(nèi)悉盆,執(zhí)行多長時間盯荤,執(zhí)行過程是否出錯,都無從自動化過程得知焕盟。

九秋秤、資源是通過JavaScript加載的情況
http://www.reibang.com/p/de5e779048de
/
/
/
/

十、firefox安全性強(qiáng),不允許跨域調(diào)用出現(xiàn)報(bào)錯

錯誤描述: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."); 
      } 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芥玉,一起剝皮案震驚了整個濱河市蛇摸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌灿巧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件揽涮,死亡現(xiàn)場離奇詭異抠藕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)蒋困,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門盾似,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人雪标,你說我怎么就攤上這事零院。” “怎么了村刨?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵告抄,是天一觀的道長。 經(jīng)常有香客問我嵌牺,道長打洼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任逆粹,我火速辦了婚禮募疮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘僻弹。我一直安慰自己阿浓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布蹋绽。 她就那樣靜靜地躺著芭毙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蟋字。 梳的紋絲不亂的頭發(fā)上稿蹲,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機(jī)與錄音鹊奖,去河邊找鬼苛聘。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的设哗。 我是一名探鬼主播唱捣,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼网梢!你這毒婦竟也來了震缭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤战虏,失蹤者是張志新(化名)和其女友劉穎拣宰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體烦感,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡巡社,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了手趣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晌该。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖绿渣,靈堂內(nèi)的尸體忽然破棺而出朝群,到底是詐尸還是另有隱情,我是刑警寧澤中符,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布姜胖,位于F島的核電站,受9級特大地震影響舟茶,放射性物質(zhì)發(fā)生泄漏谭期。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一吧凉、第九天 我趴在偏房一處隱蔽的房頂上張望隧出。 院中可真熱鬧,春花似錦阀捅、人聲如沸胀瞪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽凄诞。三九已至,卻和暖如春忍级,著一層夾襖步出監(jiān)牢的瞬間帆谍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工轴咱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留汛蝙,地道東北人烈涮。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像窖剑,于是被迫代替她去往敵國和親坚洽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355