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>主htmltitle>
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
通过测试的结果,我们可以看到窗口切换了两次。