Python3 Selenium定位不到元素常見原因及解決辦法


轉自https://www.cnblogs.com/lizm166/p/9995612.html

一、問題描述

  在做web應用的自動化測試時,定位元素是必不可少的,這個過程經常會碰到定位不到元素的情況:

  報錯信息: no such element: Unable to locate element: {"method":"xpath","selector":"xpath"}

二、分析以及解決方案

1,原因一以及解決方案

(1)原因:

  Frame/Iframe原因定位不到元素:這個是最常見的原因,首先要理解下frame的實質,frame中實際上是嵌入了另一個頁面,而webdriver每次只能在一個頁面識別,因此需要先定位到相應的frame,對那個頁面里的元素進行定位。

(2)解決方案:

如果iframe有name或id的話,直接使用switch_to_frame("name值")或switch_to_frame("id值")。如下:

driver=webdriver.Firefox()
driver.get(r'http://www.126.com/')
driver.switch_to_frame('x-URS-iframe')  #需先跳轉到iframe框架
username=driver.find_element_by_name('email')
username.clear()
如果iframe沒有name或id的話,則可以通過下面的方式定位:
#先定位到iframe
elementi= driver.find_element_by_class_name('APP-editor-iframe')
#再將定位對象傳給switch_to_frame()方法
driver.switch_to_frame(elementi) 
如果完成操作后,可以通過switch_to.parent_content()方法跳出當前iframe,或者還可以通過switch_to.default_content()方法跳回最外層的頁面。

2,原因二以及解決方案

(1)原因:

  Xpath描述錯誤原因:由於Xpath層級太復雜,容易犯錯。但是該定位方式能夠有效定位絕大部分的元素,建議掌握。

(2)解決方案:

  <1>.可以使用Firefox的firePath,復制xpath路徑。該方式容易因為層級改變而需要重新編寫過xpath路徑,不建議使用,初學者可以先復制路徑,然后嘗試去修改它。

  <2>.提高下寫xpath的水平.

  如何檢驗編寫的Xpath是否正確?

  編寫好Xpath路徑,可以直接復制到搜狐瀏覽器的firebug查看html源碼,通過Xpath搜索:如下紅色框,若無報錯,則說明編寫的Xpath路徑沒錯。
  例如:find_element_by_xpath("//input[@id='kw']")
  

 

3,原因三以及解決方案

(1)原因

  頁面還沒有加載出來,就對頁面上的元素進行的操作:這種情況一般說來,可以設置等待,等待頁面顯示之后再操作,這與人手工操作的原理一樣:

(2)解決方案

  <1>.設置等待時間;缺點是需要設置較長的等待時間,案例多了測試就很慢;
  <2>.設置等待頁面的某個元素出現,比如一個文本、一個輸入框都可以,一旦指定的元素出現,就可以做操作。
  <3>.在調試的過程中可以把頁面的html代碼打印出來,以便分析。

  導入時間模塊。

  import time

  time.sleep(3)

4,原因四以及解決方案

(1)原因

  動態id定位不到元素:每次調用頁面出現的元素的ID會動態隨機分配。

(2)解決方案

  如果發現是動態id,推薦使用xpath的相對路徑方法查找到該元素。

  

5,原因五以及解決方案

(1)原因

  二次定位,如彈出框登錄:如百度登錄彈出框登錄百度賬號,需先定位到百度彈出框,然后再定位到用戶名密碼登錄。

(2)解決方案

復制代碼
'''
Project:登錄百度賬號
'''
from selenium import webdriver
import time

driver = webdriver.Firefox()
driver.get("http://www.baidu.com/")
time.sleep(3)
#點擊登錄:有些name為tj_login的元素為不可見的,點擊可見的那個登錄按鈕即可。
#否則會報:ElementNotVisibleException
element0=driver.find_elements_by_name("tj_login")
for ele0 in element0:
    if ele0.is_displayed():
        ele0.click()
#在登錄彈出框,需先定位到登錄彈出框
#否則會報:NoSuchElementException
element1=driver.find_element_by_class_name("tang-content")
element11=element1.find_element_by_id("TANGRAM__PSP_8__userName")
element11.clear()
element11.send_keys("登錄名")

element2=element1.find_element_by_id("TANGRAM__PSP_8__password")
element2.clear()
element2.send_keys("密碼")

element3=element1.find_element_by_id("TANGRAM__PSP_8__submit")
element3.click()
element3.submit()

try:
    assert "登錄名" in driver.page_source
except AssertionError as e:
    print "登錄失敗"
else:
    print "登錄成功"
    time.sleep(3)
finally:
    print "測試記錄:已測試"
driver.close()
復制代碼

6,原因六以及解決方案

(1)原因

  不可見元素定位:如上百度登錄代碼,通過名稱為tj_login查找的登錄元素,有些是不可見的。

(2)解決方案

  加一個循環判斷,找到可見元素(is_displayed())點擊登錄即可。

7,原因七以及解決方案

(1)原因

  firefox安全性強,不允許跨域調用出現報錯:因為firefox安全性強,不允許跨域調用。

(2)解決方案

   Firefox 要取消XMLHttpRequest的跨域限制的話,

  第一是從 about:config 里設置:signed.applets.codebase_principal_support = true; (地址欄輸入about:config 即可進行firefox設置)

  第二就是在open的代碼函數前加入類似如下的代碼:
try{
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
} catch (e) {
    alert("Permission UniversalBrowserRead denied.");
}

8,原因八以及解決方案

(1)原因

  窗口切換:窗口句柄還處在上一個窗口,導致無法定位新窗口的元素。

(2)解決方案

復制代碼
String currentWindow = driver.getWindowHandle();//獲取當前窗口句柄
Set<String> handles = driver.getWindowHandles();//獲取所有窗口句柄
for(String windowId : handles){
    if(!windowId.equals(currentWindow)){
        driver.switchTo().window(windowId);
        System.out.println(driver.getCurrentUrl());
        break;
     }
}    


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM