Selenium定位不到指定元素原因之iframe(unable to locate element)


瀏覽過程中,圖片中的內容可能太小,無法看清,可以>右鍵>在新標簽中打開

Outline

項目原因,需要用selenium實現模擬登陸、模擬上傳文件,自然就需要模擬點擊【上傳】按鈕;

模擬點擊之前需要通過selenium提供的“方法”去定位到要點擊的元素;

模擬登陸過程中,全程都可以定位到需要點擊的元素,但登陸后需要定位點擊【上傳】按鈕時問題來了;

元素明明在那放着,就是定位不到,這個問題困擾了一下午還沒解決,最終走到了iframe這個一步,才得以解決。

什么是iframe

解決問題之前很有必要先了解下什么是iframe:

HTML內聯框架元素 <iframe> 表示嵌套的瀏覽上下文,有效地將另一個HTML頁面嵌入到當前頁面中。在HTML 4.01中,文檔可能包含頭部和正文,或頭部和框架集,但不能包含正文和框架集。

但是,<iframe>可以在正常的文檔主體中使用。每個瀏覽上下文都有自己的會話歷史記錄和活動文檔。包含嵌入內容的瀏覽上下文稱為父瀏覽上下文。頂級瀏覽上下文(沒有父級)通常是瀏覽器窗口。

 

iframe是HTML三種結構中的框結構,框結構中還有另外兩個元素:framesetframe,但它們都已廢棄,不再推薦使用。

HTML中iframe展示

如下圖所示,右側代碼中圈出來的iframe標簽,渲染之后在前端顯示的就是左側圈出來的區域;

也就是此iframe嵌套在該HTML框架中。

如何說明iframe是一個獨立部分、是被嵌套到HTML框架內部的?見下圖:

將iframe標簽中的 src=/default/research/redirect 復制出來在地址欄進行鏈接替換,會發現此時的頁面只有iframe獨立部分,之前頁面中的banner不見了。

參考:

深入理解iframe-簡書

iframe文檔

selenium定位元素

 selenium模擬登陸操作

部分代碼:

    def auto_login(self):
        # 獲取瀏覽器窗口對象
        driver = webdriver.Chrome()
        # 打開瀏覽器進入指定地址
        driver.get('https://ycjq.95358.com/research')

        # selenium進行元素定位、填寫內容
        driver.find_element_by_name("CyLoginForm[username]").send_keys("你的賬號")
        driver.find_element_by_name("CyLoginForm[pwd]").send_keys("你的密碼")

        # 這里圖像識別獲取驗證碼  def valideCode():
        # driver.find_element_by_name("valideCode").send_keys("")

        # selenium進行元素定位、模擬點擊(登陸)
        time.sleep(10)
        driver.find_element_by_id("btnSubmit").click()

頁面分析:

根據標簽的“name”、“id”等,進行元素定位,然后模擬操作。

執行上述代碼,你會發現會自動打開瀏覽器,進入指定地址,然后會自動進行賬號密碼的輸入,並且自動點擊“登陸”;

然后會進行登陸后的頁面跳轉。

整個流程很正確也很合理,但頁面跳轉之后再進行元素定位、模擬點擊時就有坑了。

切換iframe

 上一步“模擬登陸”時,HTML頁面並不涉及 iframe 標簽,但登陸過后就含有 iframe標簽了。

所以再通過selenium進行模擬點擊時就要切換iframe了。

在用selenium定位頁面元素的時候會遇到定位不到的問題,明明元素就在那兒,用firebug也可以看到,就是定位不到,問題很有可能就出在iframe上。

 問題復現

錯誤代碼復現:

    def auto_login(self):
        # 獲取瀏覽器窗口對象
        driver = webdriver.Chrome()
        # 打開瀏覽器進入指定地址
        driver.get('https://ycjq.95358.com/research')

        # selenium進行元素定位、填寫內容
        driver.find_element_by_name("CyLoginForm[username]").send_keys("你的賬號")
        driver.find_element_by_name("CyLoginForm[pwd]").send_keys("你的密碼")

        # selenium進行元素定位、模擬點擊(登陸)
        time.sleep(10)
        driver.find_element_by_id("btnSubmit").click()
        time.sleep(10)
     # 定位到“上傳”按鈕
        driver.find_element_by_id('notebook_list_info').click()

可以確定下圖的元素定位位置無誤,理應可以通過selenium模擬點擊的,但模擬點擊之后一直提示找不到標簽:

問題解決

問題出現之后,進行相關問題搜索,五花八門,各種解決方案,用了一下午,各種嘗試,最終確定問題出在iframe。

只有切換到iframe里面,selenium才能定位到 iframe里面的元素。

切換iframe

selenium提供了switch_to.frame()方法來切換frame

switch_to.frame(reference)

注意:

可能你會這樣寫:switch_to_frame(),但會發現,這段代碼被加上“刪除線”了;

原因是這個方法已經out了,之后可能被廢棄,建議switch_to.frame()

 

switch_to.frame(reference)中的reference是傳入的參數,用來定位frame,可以傳入id、name、index以及selenium的WebElement對象。

如下圖中的 id、name。

如果沒有id、name屬性的化,可以通過xpath匹配WebElement對象進行定位。

正確定位代碼:

    def auto_login(self):
        # 獲取瀏覽器窗口對象
        driver = webdriver.Chrome()
        # 打開瀏覽器進入指定地址
        driver.get('https://ycjq.95358.com/research')

        # selenium進行元素定位、填寫內容
        driver.find_element_by_name("CyLoginForm[username]").send_keys("你的賬號")
        driver.find_element_by_name("CyLoginForm[pwd]").send_keys("你的密碼")

        # 這里圖像識別獲取驗證碼  def valideCode():
        # driver.find_element_by_name("valideCode").send_keys("")

        # selenium進行元素定位、模擬點擊(登陸)
        time.sleep(10)
        driver.find_element_by_id("btnSubmit").click()
        time.sleep(10)
        # 切換iframe
        driver.switch_to.frame('research')
        driver.find_element_by_id('notebook_list_info').click()

執行代碼之后即可正確模擬點擊”上傳“按鈕。

 

參考:https://blog.csdn.net/huilan_same/article/details/52200586 

 


免責聲明!

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



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