如果我們要 選擇 下圖方框中 所有的 蔬菜,使用css選擇,怎麼寫表達式?
當然,要先查看到它們的html元素特徵
大家可能會照舊寫出如下代碼:
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的 元素中的。
這個 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)