1、多表单(或者说框架)切换
什么是表单:就是网页标签名为frame或iframe 的元素,表单引用了其他页面的链接,真正的页面数据没有出现在源码中,但是 在浏览器中可以看见,与浏览器的多个窗口类似
为什么需要切换:在web应用会遇到frame/iframe表单嵌套的应用,selenium的WebDriver只能在一个页面对元素操作及定位,对表单里的元素无法直接定位,此时需要切换到表单页面再进行定位
表单切换方法1:switch_to.frame('id的值'),此方法是默认取表单的id的值或name属性的值进行定位(现在163邮箱没有name属性,id的是动态id,无法使用此方法进行切换表单)
表单切换方法2:先定位到表单,再切换到表单,然后才能正常定位到表单内的元素
# 导包 from selenium import webdriver import time # 创建一个浏览器对象 driver = webdriver.Chrome() # 默认浏览器全屏 driver.maximize_window() # 访问163邮箱 url = 'https://email.163.com/' driver.get(url) # 不切换表单,直接定位到输入框 try: driver.find_element_by_css_selector('#auto-id-1596976820406') print('不需要切换表单可以直接定位') except: print('定位失败,请切换表单') # 第一种方式切换表单 # 格式:driver.switch_to.frame('id的值或name属性的值') # driver.switch_to.frame('auto-id-1596976820406')# 此网址id为动态id,无法用此方法定位 # 第二种方式(先定位到表单,再切换到表单,然后才能正常定位到表单里的输入框) # 定位到表单frame fr = driver.find_element_by_tag_name('iframe') # 切换到表单 driver.switch_to.frame(fr) # 定位账号输入框并输入 usr_email = driver.find_element_by_name('email') usr_email.send_keys('8888888888') time.sleep(1) # 定位到密码输入框并输入 password = driver.find_element_by_name('password') password.send_keys('00000000') time.sleep(3) # 定位登录按钮 log = driver.find_element_by_id('dologin') log.click() # 获取图片 time.sleep(2) driver.get_screenshot_as_file('获取表单登录图片.png') # 关闭浏览器 driver.quit()
2、多层表单切换(本地文件网页)
跳到最外层页面:driver.switch_to.default_content()
跳到上一级页面:driver.switch_to.parent_frame()
# 导入WebDriver和os模块(用于获取本地连接) from selenium import webdriver import os # 创建一个浏览器默认最大化 driver = webdriver.Firefox() driver.maximize_window() # os.path.abspath()方法是获取本地路径(此处是本地网页路径) bendi_path = 'file:///' + os.path.abspath('./day4/example_frame.html') print(bendi_path) # 访问本地路径网页 driver.get(bendi_path) # 此网页有三层,默认电脑光标在第一层,此时需要定位到最内层的百度,需要经过两次frame表单 # 因为默认的是在第一层,所有此时先切换到第二层 driver.switch_to.frame('kw_frame1') # 再切换到最内层 driver.switch_to.frame('kw_frame2') # 此时已经进入最内层,可以正常开始定位 # 定位百度搜索框并输入 sr = driver.find_element_by_id('kw') sr.send_keys('兵法') # 跳出到最外层 driver.switch_to.default_content() # 验证跳出最外层 try: # 按理此时不在最内层,无法定位最内层的搜索框 driver.find_element_by_id('kw') print('还在最内层,可以定位到') except: print('已经跳出最内层') # 跳回上一层,执行两次,跳到最内层 driver.switch_to.parent_frame() driver.switch_to.parent_frame() # 验证是否跳回上一层 try: driver.find_element_by_id('kw') print('已经跳回上一层') except: print('跳转两次后回到了最内层') # 关闭浏览器 driver.quit()
代码中两个简单的网页源码,把下面源码保存成HTML格式,放于与脚本同一级目录即可使用
<html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <title>inner</title> </head> <body> <div class="row-fluid"> <div class="span6 well"> <h3>inner</h3> <iframe id="kw_frame2" src="https://www.baidu.com/" width="700" height="500"></iframe> <a href="javascript:alert('watir-webdriver better than selenium webdriver;')">click</a> </div> </div> </body> </html>
<html> <head> <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <title>frame</title> <script type="text/javascript" async="" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js "></script> <link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet" /> <script type="text/javascript"> $(document).ready(function(){ }); </script> </head> <body> <div class="row-fluid"> <div class="span10 well"> <h3>frame</h3> <iframe id="kw_frame1" src="inner.html" width="800", height="600"></iframe> </div> </div> </body> <script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> </html>