先看一個例子:
這是 163 郵箱登錄頁面类茂,我們想模擬一下郵箱登錄忿等。
driver.find_element_by_name('email').send_keys('nemo')
額躁锁,報錯了裁蚁!Selenium 告訴我們:Message: no such element: Unable to locate element。
檢查定位方式對的啊案站,name 屬性嘛躬审。可為什么就是要報錯呢蟆盐?
仔細觀察頁面結(jié)構(gòu)承边,我們發(fā)現(xiàn)要操作的登錄元素都是放在一個叫 iframe 的元素中,而且還是一個完整的 HTML(有 HTML 聲明和 html 根節(jié)點):
<iframe>
標(biāo)簽創(chuàng)建包含另一個文檔的行內(nèi)框架石挂。
iframe 用來包含一個獨立的 HTML 文檔博助。相當(dāng)于在一個 HTML 頁面中包含了另一個 HTML 頁面。所以也稱為內(nèi)嵌頁面痹愚,由于其定義是 HTML 中的一個框架富岳,所以也稱為內(nèi)聯(lián)框架蛔糯。
現(xiàn)代網(wǎng)頁中主要使用 iframe 來解決跨域的問題。比如這個登錄是 163 的單點登錄窖式,郵箱只是 163 賬號可登錄站點中的一個蚁飒,所以登錄站點和郵箱不在同一個域下面,需要用 iframe 來解決跨域問題脖镀。
當(dāng)你想操作 iframe 中內(nèi)嵌的頁面中的元素時飒箭,已經(jīng)脫離了當(dāng)前頁面。
如何判斷是否是當(dāng)前頁面蜒灰?
你可以嘗試在頁面上右鍵單擊弦蹂,然后選擇“查看網(wǎng)頁源碼”,看到的 HTML 代碼就是當(dāng)前頁面强窖。
對于脫離于當(dāng)前頁面的元素凸椿,WebDriver 提供了 switch_to.frame() 方法,用來跳轉(zhuǎn)到需要操作的頁面翅溺。(注意脑漫,只有frame()
方法沒有iframe())
要跳轉(zhuǎn)到對應(yīng)的 iframe 元素,可以通過以下四種方式來指定:
方式 | 說明 | 舉例 |
---|---|---|
index | 通過 iframe 在頁面中出現(xiàn)的順序 | driver.switch_to.frame(0) 選擇第一個 |
id | 通過 iframe 的 id 屬性 | driver.switch_to.frame('frame-id') |
name | 通過 iframe 的 name 屬性 | driver.switch_to.frame('frame-name') |
WebElement | 沒有合適的 id咙崎,name 屬性 通過 find_element() 找到 iframe 元素再跳轉(zhuǎn) |
iframe = driver.find_element_by_xpath('//*[id="login"]/iframe') driver.switch_to.frame(iframe) |
這里 163 郵箱登錄的案例优幸,沒有 id 也沒有 name ,我們選擇第四種方式:
# 定位到 iframe 元素
iframe = driver.find_element_by_css_selector('#loginDiv>iframe')
# 跳轉(zhuǎn)到 iframe
driver.switch_to.frame(iframe)
# 操作
driver.find_element_by_name('email').send_keys('nemo')
# 跳出 iframe
driver.switch_to.default_content()
在 iframe 中操作之后褪猛,操作外面的元素需要跳出來网杆。跳出方式有兩種:
driver.switch_to.parent_frame() # 跳到父級 frame 元素
driver.switch_to.default_content() # 跳到最外層頁面
如果有多級 iframe 的情況下,通過driver.switch_to.parent_frame()
可以只跳一級伊滋。而driver.switch_to.default_content()
是在任何情況下都跳轉(zhuǎn)到最外層頁面碳却。
注意,在 iframe 操作后一定要跳出 iframe笑旺,如果沒有跳出 Firefox 瀏覽器可能會出現(xiàn)異常昼浦。