瀏覽過程中,圖片中的內容可能太小,無法看清,可以>右鍵>在新標簽中打開
Outline
項目原因,需要用selenium實現模擬登陸、模擬上傳文件,自然就需要模擬點擊【上傳】按鈕;
模擬點擊之前需要通過selenium提供的“方法”去定位到要點擊的元素;
模擬登陸過程中,全程都可以定位到需要點擊的元素,但登陸后需要定位點擊【上傳】按鈕時問題來了;
元素明明在那放着,就是定位不到,這個問題困擾了一下午還沒解決,最終走到了iframe這個一步,才得以解決。
什么是iframe
解決問題之前很有必要先了解下什么是iframe:
HTML內聯框架元素 <iframe> 表示嵌套的瀏覽上下文,有效地將另一個HTML頁面嵌入到當前頁面中。在HTML 4.01中,文檔可能包含頭部和正文,或頭部和框架集,但不能包含正文和框架集。
但是,<iframe>可以在正常的文檔主體中使用。每個瀏覽上下文都有自己的會話歷史記錄和活動文檔。包含嵌入內容的瀏覽上下文稱為父瀏覽上下文。頂級瀏覽上下文(沒有父級)通常是瀏覽器窗口。
iframe是HTML三種結構中的框結構,框結構中還有另外兩個元素:
frameset
和frame
,但它們都已廢棄,不再推薦使用。
HTML中iframe展示
如下圖所示,右側代碼中圈出來的iframe標簽,渲染之后在前端顯示的就是左側圈出來的區域;
也就是此iframe嵌套在該HTML框架中。
如何說明iframe是一個獨立部分、是被嵌套到HTML框架內部的?見下圖:
將iframe標簽中的 src=/default/research/redirect 復制出來在地址欄進行鏈接替換,會發現此時的頁面只有iframe獨立部分,之前頁面中的banner不見了。
參考:
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