我们在浏览器操作页面时,经常遇到打开新标签页的情况,但是在selenium的WebDriver对象中,只对当前get()打开的标签页生效,页面操作中打开的新标签页是不会更新到WebDriver对象中的,所以需要自己将WebDriver对象指定到新的标签页。
切换页面
对于页面操作的常用方法有如下:
方法 | 说明 |
---|---|
current_window_handle |
获取当前WebDriver对象的页面窗口句柄 |
window_handles |
获取当前浏览器所有页面的窗口句柄。返回的是个List对象 |
switch_to.window(window_name) |
切换到相关页面,window_name传入的是句柄 |
以百度首页登录和注册的页面切换为例,示例如下:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
if __name__ == "__main__":
driver = webdriver.Chrome()
driver.get("https://www.baidu.com/")
driver.implicitly_wait(20)
driver.find_element(By.LINK_TEXT, "登录").click()
print("----------只打开了百度首页----------")
print(f"当前窗口句柄:{driver.current_window_handle}")
print(f"当前所有窗口句柄:{driver.window_handles}")
driver.find_element(By.LINK_TEXT, "立即注册").click()
time.sleep(1)
print("----------打开了注册页面----------")
print(f"当前窗口句柄:{driver.current_window_handle}")
now_pages = driver.window_handles
print(f"当前所有窗口句柄:{now_pages}")
driver.switch_to.window(now_pages[-1])
print("----------切换到注册页面----------")
print(f"当前窗口句柄:{driver.current_window_handle}")
driver.find_element(By.ID, "TANGRAM__PSP_4__userName").send_keys("wen_xiaoba")
time.sleep(2)
driver.switch_to.window(now_pages[0])
driver.find_element(By.ID, "TANGRAM__PSP_11__userName").send_keys("wen_xiaojiu")
time.sleep(2)
driver.quit()
结果如下:
frame切换
html中存在一种frame结构,可以理解为页面中嵌套了另一个页面(不是弹窗的那种),在当前页面下是定位不到frame的,也就是说,如果我们没有切换到frame中的话,我们是无法定位到frame中的元素的。
frame标签包含frameset、frame、iframe三种,我们可以根据index、id、name、webelement等方式定位frame,然后切换到frame后,再去定位frame上的元素。
方法 | 说明 |
---|---|
switch_to.frame(frame_reference) |
切换到对应的子frame下(只能子frame,不能孙frame) |
switch_to.parent_frame() |
切换到父frame下 |
switch_to.default_content() |
切换到主页(即退出了frame,回到最初的页面) |
接下来我们以菜鸟驿站中的frame例子来进行演示。
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
if __name__ == "__main__":
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("https://www.runoob.com/try/try.php?filename=tryhtml_frame_name")
# frame_a和frame_d都在id为iframeResult的iframe标签下,所以先要切换到iframe标签
driver.switch_to.frame("iframeResult") # 根据id值进行切换
driver.switch_to.frame("frame_a") # 切换到属性name="frame_a"的frame标签下
# 读取 frame_a 标签的文本内容
print(f"frame_a内的文本内容是:{driver.find_element(By.TAG_NAME, 'h3').text}")
# 切换到当前的父frame下,即id为iframeResult的iframe标签
driver.switch_to.parent_frame()
# 定位frame_d所在的元素,用于切换到frame_d下
frame_d = driver.find_element(By.XPATH, "//frameset//frame[@src='frame_d.htm']")
# 根据frame_d这个WebElement对象,切换到frame_d这个frame下
driver.switch_to.frame(frame_d)
# 点击 首页
driver.find_element(By.XPATH, "//ul[@class='mobile-nav']//a[text()='首页']").click()
time.sleep(2)
# 返回页面主页
driver.switch_to.default_content()
# 点击菜鸟教程的图标,跳转菜鸟教程首页
driver.find_element(By.XPATH, "//div[@class='logo']//img").click()
time.sleep(2)
driver.quit()
执行结果如下:
弹框处理
弹框的表现形式有多种,比如div、frame,这2种看selenium系列的前面文章可以了解到,这里主要了解的有2种:alert弹窗、文件上传弹窗。
selenium有支持alert弹窗的方法,但是文件上传的弹窗涉及到了系统弹窗,selenium是没有支持的,网上很多方法基本上是需要第三方工具的/(ㄒoㄒ)/~~后面有好的解决办法再补充这一块
alert弹窗
alert弹窗的常用的内容如下:
方法 | 说明 |
---|---|
alert = switch_to.alert |
切换到alert弹窗,并将Alert对象返回给alert变量 |
accept() |
Alert对象的方法,表示确定(相当于点击了确定) |
dismiss() |
Alert对象的方法,表示取消(相当于关闭、取消弹窗【如果有取消或关闭按钮的话】) |
示例如下:
import time
from selenium import webdriver
if __name__ == "__main__":
driver = webdriver.Chrome()
driver.implicitly_wait(20)
# 打开百度首页
driver.get("https://image.baidu.com/")
# 通过执行js语句打开alert弹框
driver.execute_script('alert("我有一头小毛驴")')
time.sleep(2)
# 切换到alert弹框中
alert = driver.switch_to.alert
# 通过text属性获取alert弹框中的文本内容
print(f"alert弹框的文本内容为:{alert.text}")
# 取消弹框(相当于点击了取消按钮)
alert.dismiss()
time.sleep(2)
# 通过执行js语句打开alert弹框
driver.execute_script('alert("我是一只小小小小鸟~")')
alert_2 = driver.switch_to.alert
time.sleep(2)
# 点击弹框的“确定”
alert_2.accept()
time.sleep(2)
driver.quit()
执行结果如下:
文件上传
一般我们在文件上传的时候,都会打开系统弹窗,然后我们需要在系统弹窗中选择需要上传的文件(包括文档、图片、视频、音频等),但是selenium没有支持识别系统弹窗的方法。但是如果上传文件的元素是input标签,则可以直接对input标签send_keys(文件路径)进行文件上传,如果是非Input标签,则需要考虑第三方工具或寻找关联的input标签去调试了。
input标签
示例
如果上传按钮是个input标签,我们就直接使用send_keys(),以草料图片二维码生成器的上传为例:
想上传第二份时,会发现没有input标签了
一般而言,一个页面中,上传的元素是基本相同的,我们可以根据第一个上传前的id定位(或者扩大范围,一层层向上查input标签),从前一个截图可以看到,上传元素的input标签的id值是filedatacode,上传一个文件后,查找这个input标签是否还存在,若存在我们就继续用
具体代码如下:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
if __name__ == "__main__":
driver = webdriver.Chrome()
driver.implicitly_wait(20)
# 打开百度图片首页
driver.get("https://cli.im/files")
# 定位上传的input标签
up_load_input = driver.find_element(By.ID, "filedatacode")
# 上传第一个文件
up_load_input.send_keys("E:\\图片\\demo.txt")
time.sleep(2)
up_load_input2 = driver.find_element(By.ID, "filedatacode")
# 上传第二个文件
up_load_input2.send_keys("E:\\图片\\百度翻译.png")
time.sleep(2)
driver.quit()
涉及到的文件如下:
执行结果如下:
小tips
有时候我们使用浏览器的定位功能,发现上传按钮不是input标签,这个时候我们可以在上传按钮的上层去找input标签,直到找到类似上传的input标签。一般而言,上传的input标签会放在被定为的按钮的子级、同级或同级的子级。
以芝麻二维码解码器为例,我们使用浏览器的定位功能定位 选择二维码图片 的时候,发现是个button标签
我们以这个button标签为中心,向上扩展查找范围,比如扩展到 class=“decode_upload_right” 的div标签,在该div标签下查找input子标签,从xpath表达式匹配结果可以看出, 选择二维码图片 的button标签的同级标签下有一个匹配的input子标签,我们试试这个input标签的send_keys()方法是否能上传图片
实现如下:
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
if __name__ == "__main__":
driver = webdriver.Chrome()
driver.implicitly_wait(20)
# 打开芝麻二维码解码器页面
driver.get("https://www.hotapp.cn/jiema")
# 定位到input标签,上传百度翻译的二维码图片
driver.find_element(By.XPATH, "//div[@class='decode_upload_right']//input").send_keys("E:\\图片\\百度翻译.png")
# 阻塞3秒钟,用来人眼查看效果
time.sleep(3)
driver.quit()
执行结果如下:
文章来源:https://www.toymoban.com/news/detail-744115.html
上传按钮非input标签
占个位置,以后有实践再安排,嘻嘻~文章来源地址https://www.toymoban.com/news/detail-744115.html
到了这里,关于python之selenium的switch_to的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!