selenium中的三种切换:Windows窗口,iframe,alert弹窗

前言

在selenium的web自动化当中会遇到一些窗口跳转或者对话框的弹出。在selenium中,提供了三种切换:Windows窗口切换,iframe切换,alert弹窗切换。

Windows窗口切换

直接举例子,比如我们在百度搜索“腾讯课堂”,在搜索结果中点击,会弹出一个新的窗口,那么如果我要在新的窗口操作,那么我们就需要进行切换,切换后在新的界面点击登录按钮:
selenium中的三种切换:Windows窗口,iframe,alert弹窗_第1张图片
具体实现代码:

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time

chrome_driver = webdriver.Chrome()
chrome_driver.maximize_window()
chrome_driver.get("http://www.baidu.com")

chrome_driver.find_element_by_xpath('//*[@id="kw"]').send_keys("腾讯课堂")
chrome_driver.find_element_by_id('su').click()

loc = (By.XPATH, '//*[@id="3001"]/div/div[1]/div/div/h3/div/a[1]')
# 设置等待元素可见,因为搜索之后要加载
WebDriverWait(chrome_driver, 30, 0.2).until(EC.visibility_of_element_located(loc))
# 点击,出现新的窗口,如果我们要在新的窗口操作,那么就需要切换窗口
chrome_driver.find_element(*loc).click()
time.sleep(1)

# 切换到新窗口
# 1.获取打开的所有窗口,得到一个列表,列表中存放的是窗口的句柄,所谓句柄,就是窗口的唯一标识(handles)。注意列表中的出现顺序是窗口的打开顺序
wins = chrome_driver.window_handles

print(wins)
# 打印当前窗口的句柄
print(chrome_driver.current_window_handle)
# 切换窗口
chrome_driver.switch_to.window(wins[-1])

# 设置等待,确认有登录按钮
loc1 = (By.XPATH, '//*[@id="mgr_nav_login"]')
WebDriverWait(chrome_driver, 30).until(EC.visibility_of_element_located(loc1))
# 在新的界面点击登录按钮
chrome_driver.find_element(*loc1).click()

实现效果:
selenium中的三种切换:Windows窗口,iframe,alert弹窗_第2张图片
切换window窗口,除了上面的switch_to.window,还有expected_conditions类提供的一种方法new_window_is_opened。
比如上面的代码,可以写为:

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time

chrome_driver = webdriver.Chrome()
chrome_driver.maximize_window()
chrome_driver.get("http://www.baidu.com")

chrome_driver.find_element_by_xpath('//*[@id="kw"]').send_keys("腾讯课堂")
chrome_driver.find_element_by_id('su').click()

loc = (By.XPATH, '//*[@id="3001"]/div/div[1]/div/div/h3/div/a[1]')
# 设置等待元素可见,因为搜索之后要加载
WebDriverWait(chrome_driver, 30, 0.2).until(EC.visibility_of_element_located(loc))
# 获取当前的窗口数,在点击之前的窗口数量
cu_windows = chrome_driver.window_handles
# 点击,出现新的窗口,如果我们要在新的窗口操作,那么就需要切换窗口
chrome_driver.find_element(*loc).click()
# time.sleep(1)

# 在expected_conditions中有一个方法,专门为等待新的窗口出现
EC.new_window_is_opened(cu_windows)  # 使用这个,20s之内,会确保,新的窗口出现才会继续往下进行,如果直接使用sleep,可能会报错

# 设置等待,确认有登录按钮
loc1 = (By.XPATH, '//*[@id="mgr_nav_login"]')
WebDriverWait(chrome_driver, 30).until(EC.visibility_of_element_located(loc1))
# 在新的界面点击登录按钮
chrome_driver.find_element(*loc1).click()

iframe切换

iframe窗口是嵌套在我们整个HTML里面的一个HTML的页面,我们如果要对这个iframe中的元素进行操作,那么就必须要先切换这个iframe窗口才可以进行操作。
 比如我们下面网页,点击登录界面的注册新账号,我们在开发管理工具中,可以看到,这个按钮在iframe上,要点击这个按钮,首先要切换到它所在的frame上才行,否则会报错:
selenium中的三种切换:Windows窗口,iframe,alert弹窗_第3张图片
实现代码:

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time


driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://connect.qq.com/")

# 等待元素可见
login_btn_loc = (By.XPATH, '//div[@class="no-login"]/a')
WebDriverWait(driver, 30).until(EC.presence_of_element_located(login_btn_loc))
# 点击登录按钮
driver.find_element(*login_btn_loc).click()

# 等待frame加载到dom树中
frame_loc = (By.XPATH, '//*[@id="login_frame"]')
WebDriverWait(driver, 30).until(EC.presence_of_element_located(frame_loc))

# 切换到frame上,切换到frame上时,可以以三种形式传入参数:name属性,下标,webelement对象
# 切换到frame,传入 webelement对象
driver.switch_to.frame(driver.find_element_by_xpath('//*[@id="login_frame"]'))

# 点击
driver.find_element_by_xpath('//div[@id="bottom_qlogin"]/a[text()="注册新帐号"]').click()

效果:
selenium中的三种切换:Windows窗口,iframe,alert弹窗_第4张图片
下面这一句代码,切换frame时,传入的时webElement对象,其实还可以传入下标或者name属性的值:

driver.switch_to.frame(driver.find_element_by_xpath('//*[@id="login_frame"]'))

比如:

driver.switch_to.frame(0)  # 切换到第1个frame,注意下标是从0开始的
driver.switch_to.frame("login_frame")  # 切换到第一个frame,注意使用name属性时,要确认name属性的唯一性

当在frame上操作完毕后,如果要返回到原来的界面或者主界面,要进行切换。
切换到主界面:

chrome_driver.switch_to.default_content()

切换到父级的frame:

chrome_driver.switch_to.parent_frame()

其实,frame切换,除了上面说的driver.switch_to.frame的方式,还有一种是由expected_conditions提供的frame_to_be_available_and_switch_to_it方法。
比如上面的代码中,这两句代码:

WebDriverWait(driver, 30).until(EC.presence_of_element_located(frame_loc))

# 切换到frame上
driver.switch_to.frame(driver.find_element_by_xpath('//*[@id="login_frame"]'))

可以用下面这句代码进行替换,效果是一样的:

WebDriverWait(driver, 30).until(EC.frame_to_be_available_and_switch_to_it(frame_loc))

替换后代码:

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time


driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://connect.qq.com/")

# 等待元素可见
login_btn_loc = (By.XPATH, '//div[@class="no-login"]/a')
WebDriverWait(driver, 30).until(EC.presence_of_element_located(login_btn_loc))
# 点击登录按钮
driver.find_element(*login_btn_loc).click()

frame_loc = (By.XPATH, '//*[@id="login_frame"]')
WebDriverWait(driver, 30).until(EC.frame_to_be_available_and_switch_to_it(frame_loc))

# 点击
driver.find_element_by_xpath('//div[@id="bottom_qlogin"]/a[text()="注册新帐号"]').click()

alert弹窗切换

alert窗口就是js提示框,它不属于web界面,所以,在有这个提示框的作用下,我们是无法继续web操作的,必须先处理掉js弹窗,才可以继续。
Alert类提供了四个方法来处理弹窗:

driver.switch_to.alert.accept()  # 确定操作
driver.switch_to.alert.dismiss()    # 取消操作
driver.switch_to.alert.send_keys("")    # alert弹框输入文本
driver.switch_to.alert.text()      # 获取alert的文本内容

同上面两种切换一样,alert切换时,expected_conditions类也提供了一个切换方法alert_is_present:

alert = WebDriverWait(driver, 10).until(EC.alert_is_present())
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait


driver = webdriver.Chrome()
driver.get("my.html")

# 弹窗是否已出现,出现则返回弹窗对象
alert = WebDriverWait(driver, 10).until(EC.alert_is_present())
# alert = driver.switch_to.alert  可以被上一句替换掉
alert.accept()  # 确定
alert.dismiss()  # 取消
alert.send_keys()  # 输入
alert.text()  # 获取文本

你可能感兴趣的:(自动化,selenium,frame,Windows,alert)