Selenium(六):frame切換、窗口切換


1. 切換到frame

index.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>    
    </head>
    <script>

        
    function appendEle(info) {
        var node = document.createElement("LI");
        var textnode = document.createTextNode(info);
        node.appendChild(textnode);
        document.getElementById("add").appendChild(node);
    }

    function clickbutton() {       
        appendEle("你點擊了外部按鈕");
    }

    </script>
    <body>
        <div><button id='outerbutton' onclick='clickbutton()' >外部按鈕</button></div>

        <br>

        <div class="baiyueheiyu"><span>下面的內容是iframe中的</span></div>

        <iframe src="sample1.html" id='frame1' name='innerFrame' width="300" height="200"></iframe>
        <div id="add"></div>
    </body>
</html>

sample1.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            .wolf{
                color: red;
            }
        </style>
    </head>
    <body>
        <div class="raise"><span>喜羊羊</span></div>
        <div class="raise"><span>美羊羊</span></div>
        <div class="raise"><span>暖羊羊</span></div>
 
        <div class="wolf"><span>灰太狼</span></div>
        <div class="wolf"><span>紅太狼</span></div>
        <div class="wolf"><span>小灰灰</span></div>
    </body>
</html>

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

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

 

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

from selenium import webdriver

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

wd.get('http://127.0.0.1:8020/day01/index.html')

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

for element in elements:
    print(element.text)

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

為什么呢?

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

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

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

1.1 從主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'E:\webdrivers\chromedriver.exe')

wd.get('http://127.0.0.1:8020/day01/index.html')


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

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

for element in elements:
    print(element.text)

1.2 從被嵌入的文檔切換到主html

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

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

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

很簡單,寫如下代碼即可:

wd.switch_to.default_content()

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

from selenium import webdriver

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

wd.get('http://127.0.0.1:8020/day01/index.html')


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

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

for element in elements:
    print(element.text)

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

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

2. 切換窗口

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

html代碼:

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="UTF-8">
        <title>主html</title>
    </head>
    <script>
            function appendEle(info) {
                var node = document.createElement("LI");
                var textnode = document.createTextNode(info);
                node.appendChild(textnode);
                document.getElementById("add").appendChild(node);
            }
        
            function clickbutton() {       
                appendEle("你點擊了外部按鈕");
            }
        
    </script>
    <body>
        <a href="http://www.bing.com" target="_blank">訪問bing網站</a>
        
        <div><button id='outerbutton' onclick='clickbutton()' >功能按鈕</button></div>

        <br>

        <div id="add"></div>

    </body>
</html>

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

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

問題就在於,即使新窗口打開了,這時候,我們的 WebDriver對象對應的還是老窗口,自動化操作也還是在老窗口進行,我們可以運行如下代碼驗證一下:

from selenium import webdriver

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

wd.get('http://127.0.0.1:8020/day01/index.html')

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

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

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

主html

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

2.1 切換到新窗口

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

可以使用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)方法,切入到每個窗口,然后檢查里面該窗口對象的屬性(可以是標題欄,地址欄),判斷是不是我們要操作的那個窗口,如果是,就跳出循環。

完整代碼:

from selenium import webdriver

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

wd.get('http://127.0.0.1:8020/day01/index.html')

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

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

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

2.2 切換回原來的窗口

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

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

還有更省事的方法。

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

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

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

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

完整代碼:

from selenium import webdriver

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

wd.get('http://127.0.0.1:8020/day01/index.html')

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

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

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

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

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

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

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

結果:

主html
微軟 Bing 搜索 - 國內版
主html

通過測試的結果,我們可以看到窗口切換了兩次。


免責聲明!

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



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