frame切換/窗口切換

如果我們要 選擇 下圖方框中 所有的 蔬菜,使用css選擇,怎麼寫表達式?

當然,要先查看到它們的html元素特徵

白月黑羽Python3教程

大家可能會照舊寫出如下代碼:

from selenium import webdriver

wd = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe')

wd.get('http://f.python3.vip/webauto/sample2.html')

# 根據 class name 選擇元素,返回的是 一個列表
elements = wd.find_elements_by_class_name('plant')

for element in elements:
    print(element.text)

運行一下,你就會發現,運行結果打印內容爲空白,說明沒有選擇到 class 屬性值爲 plant 的元素。

爲什麼呢?

因爲仔細看,你可以發現, 這些元素是在一個叫 iframe的 元素中的。

白月黑羽Python3教程

這個 iframe 元素非常的特殊, 在html語法中,frame 元素 或者iframe元素的內部 會包含一個 被嵌入的 另一份html文檔。

在我們使用selenium打開一個網頁是, 我們的操作範圍 缺省是當前的 html , 並不包含被嵌入的html文檔裏面的內容。

如果我們要 操作 被嵌入的 html 文檔 中的元素, 就必須 切換操作範圍 到 被嵌入的文檔中。

怎麼切換呢?

使用 WebDriver 對象的 switch_to 屬性,像這樣

wd.switch_to.frame(frame_reference)

其中, frame_reference 可以是 frame 元素的屬性 name 或者 ID 。

比如這裏,就可以填寫 iframe元素的id ‘frame1’ 或者 name屬性值 ‘innerFrame’。

像這樣

wd.switch_to.frame('frame1')

或者

wd.switch_to.frame('innerFrame')

 

也可以填寫frame 所對應的 WebElement 對象。

我們可以根據frame的元素位置或者屬性特性,使用find系列的方法,選擇到該元素,得到對應的WebElement對象

比如,這裏就可以寫

wd.switch_to.frame(wd.find_element_by_tag_name("iframe"))

然後,就可以進行後續操作frame裏面的元素了。

上面的例子的正確代碼如下

from selenium import webdriver

wd = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe')

wd.get('http://f.python3.vip/webauto/sample2.html')


# 先根據name屬性值 'innerFrame',切換到iframe中
wd.switch_to.frame('innerFrame')

# 根據 class name 選擇元素,返回的是 一個列表
elements = wd.find_elements_by_class_name('plant')

for element in elements:
    print(element.text)

 

如果我們已經切換到某個iframe裏面進行操作了,那麼後續選擇和操作界面元素 就都是在這個frame裏面進行的。

這時候,如果我們又需要操作 主html(我們把最外部的html稱之爲主html) 裏面的元素了呢?

怎麼切換回原來的主html呢?

很簡單,寫如下代碼即可

wd.switch_to.default_content()

例如,在上面 代碼 操作完 frame裏面的元素後, 需要 點擊 主html 裏面的按鈕,就可以這樣寫

from selenium import webdriver

wd = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe')

wd.get('http://f.python3.vip/webauto/sample2.html')


# 先根據name屬性值 'innerFrame',切換到iframe中
wd.switch_to.frame('innerFrame')

# 根據 class name 選擇元素,返回的是 一個列表
elements = wd.find_elements_by_class_name('plant')

for element in elements:
    print(element.text)

# 切換回 最外部的 HTML 中
wd.switch_to.default_content()

# 然後再 選擇操作 外部的 HTML 中 的元素
wd.find_element_by_id('outerbutton').click()

wd.quit()

切換到新的窗口

在網頁上操作的時候,我們經常遇到,點擊一個鏈接 或者 按鈕,就會打開一個 新窗口 。

請大家點擊這裏,打開這個鏈接

在打開的網頁中,點擊 鏈接 “訪問bing網站” , 就會彈出一個新窗口,訪問bing網址。

如果我們用Selenium寫自動化程序 在新窗口裏面 打開一個新網址, 並且去自動化操作新窗口裏面的元素,會有什麼問題呢?

問題就在於,即使新窗口打開了, 這時候,我們的 WebDriver對象對應的 還是老窗口,自動化操作也還是在老窗口進行,

我們可以運行如下代碼驗證一下

from selenium import webdriver


wd = webdriver.Chrome(r'd:\webdrivers\chromedriver.exe')
wd.implicitly_wait(10)

wd.get('http://f.python3.vip/webauto/sample3.html')

# 點擊打開新窗口的鏈接
link = wd.find_element_by_tag_name("a")
link.click()

# wd.title屬性是當前窗口的標題欄 文本
print(wd.title)

運行完程序後,最後一行 打印當前窗口的標題欄 文本, 輸出內容是

白月黑羽測試網頁3

說明, 我們的 WebDriver對象指向的還是老窗口,否則的話,運行結果就應該新窗口的標題欄 “微軟Bing搜索”


如果我們要到新的窗口裏面操作,該怎麼做呢?

可以使用Webdriver對象的switch_to屬性的 window方法,如下所示:

wd.switch_to.window(handle)

其中,參數handle需要傳入什麼呢?

WebDriver對象有window_handles 屬性,這是一個列表對象, 裏面包括了當前瀏覽器裏面所有的窗口句柄

所謂句柄,大家可以想象成對應網頁窗口的一個ID,

那麼我們就可以通過 類似下面的代碼,

for handle in wd.window_handles:
    # 先切換到該窗口
    wd.switch_to.window(handle)
    # 得到該窗口的標題欄字符串,判斷是不是我們要操作的那個窗口
    if 'Bing' in wd.title:
        # 如果是,那麼這時候WebDriver對象就是對應的該該窗口,正好,跳出循環,
        break

上面代碼的用意就是:

我們依次獲取 wd.window_handles 裏面的所有 句柄 對象, 並且調用 wd.switch_to.window(handle) 方法,切入到每個窗口,

然後檢查裏面該窗口對象的屬性(可以是標題欄,地址欄),判斷是不是我們要操作的那個窗口,如果是,就跳出循環。


同樣的,如果我們在新窗口 操作結束後, 還要回到原來的窗口,該怎麼辦?

我們可以仍然使用上面的方法,依次切入窗口,然後根據 標題欄 之類的屬性值判斷。

還有更省事的方法。

因爲我們一開始就在 原來的窗口裏面,我們知道 進入新窗口操作完後,還要回來,可以事先 保存該老窗口的 句柄,使用如下方法

# mainWindow變量保存當前窗口的句柄
mainWindow = wd.current_window_handle

切換到新窗口操作完後,就可以直接像下面這樣,將driver對應的對象返回到原來的窗口

#通過前面保存的老窗口的句柄,自己切換到老窗口
wd.switch_to.window(mainWindow)

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章