测试网址:白月黑羽测试网页2 (byhy.net)
按理说下面这行代码应该能选中这三个植物,但是实际测试发现不行,这说明我们elements根本就没有获取到.
elements=wd.find_elements(By.CSS_SELECTOR,'.plant')
原因是因为我们获取到的元素是在一个iframe中。我们发现html在iframe中。
在html语法中,frame元素或者iframe元素内部会包含一个被嵌入的另一份html文档。在我们使用selenium打开一个网页时,我们操作的缺省是当前的html,并不包含被嵌入的html文档里面的内容。
我们在进行元素选择时,不会进入iframe内层的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')
修改后的代码如下:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
#创建一个Chrome浏览器的WebDriver实例对象,指明使用chrome浏览器驱动
wd=webdriver.Chrome()
wd.implicitly_wait(1)
wd.get('https://cdn2.byhy.net/files/selenium/sample2.html')
wd.switch_to.frame('innerFrame')
elements=wd.find_elements(By.CSS_SELECTOR,'.plant')
for element in elements:
print(element.get_attribute('outerHTML'))
print('结束了')
input()
wd.switch_to.frame(),括号里面的参数可以按照之前学的元素选择获取
比如:
wd.switch_to.frame(wd.find_elements_by_css_selector('iframe[src="sample1.html"]'))
(注意了,iframe[src="sample1.html"]'的含义在前面说过,代表tag=iframe且src=“sample1.html”的元素)
如果在前面切换到了frame之后,我们需要选择frame外部的元素进行操作,我们需要切换回去。
使用代码:wd.switch_to.default_content()切换回外部。
比如我们需要点击这个外部按钮,但是现在已经切换到内层html中了。
代码如下:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
#创建一个Chrome浏览器的WebDriver实例对象,指明使用chrome浏览器驱动
wd=webdriver.Chrome()
wd.implicitly_wait(1)
wd.get('https://cdn2.byhy.net/files/selenium/sample2.html')
wd.switch_to.frame(wd.find_element(By.CSS_SELECTOR,'iframe[src="sample1.html"]'))
elements=wd.find_elements(By.CSS_SELECTOR,'.plant')
for element in elements:
print(element.get_attribute('outerHTML'))
wd.switch_to.default_content()
wd.find_element(By.CSS_SELECTOR,'#outerbutton').click()
input()
测试网站:白月黑羽测试网页3 (byhy.net)
有的时候在一些网站中,可以通过点击一些按钮来跳出新的界面。
如果我们用Selenium写自动化程序 在新窗口里面 打开一个新网址, 并且去自动化操作新窗口里面的元素,会有什么问题呢?
问题就在于,即使新窗口打开了, 这时候,我们的 WebDriver对象对应的 还是老窗口,自动化操作也还是在老窗口进行。
如果我们要到新的窗口里面操作,该怎么做呢?
可以使用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)