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
通過測試的結果,我們可以看到窗口切換了兩次。