二、Frame切换 1.应用场景:无法定位到页面上的元素,调查页面源代码时,发现这个元素属于frame或iframe标记下面的html里的元素,此时就需要切换frame。 示例: selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: 退出 2.Frame是html语法中的框架技术,包括frame和iframe两种标记,都可以实现网页的嵌套显示,在一个主网页里加入多个子网页来显示在同一个浏览器里。 示例: <html> ----主网页 …… <frame id='header-frame' name='header-frame'> <html> ---1个子网页 …… <a>退出</a> …… 3.如何切换进入Frame内的子网页里? (1)切换方式一:通过主网页源代码中frame或iframe标记的元素id或name属性值来切换。--最常用! 语法:driver.switch_to.frame("frame或iframe标记的元素id或name属性值") 示例1: # 切换到header-frame # <frame id='header-frame'…… driver.switch_to.frame("header-frame") 示例2: # <frame id='f1' name='frame1'…… driver.switch_to.frame("frame1") 示例3: # <iframe id='frame1' name='f1'…… driver.switch_to.frame("frame1") (2)切换方式二:使用frame或iframe标记的元素在整个主网页里的索引号来切换。 语法:driver.switch_to.frame(索引号) 注意:索引号是代表当前frame或iframe标记的元素是主网页里的第几个的整数,从0开始编号。 (3)切换方式三:使用其他方式来定位到frame或iframe标记的元素,然后把定位到的元素对象作为切换frame时的参数。其他方式包括class name或xpath或css selector定位等任何定位方法。---语法最复杂,功能最强大! 语法: 变量=driver.find_element(By.XXX,"xxxx") driver.switch_to.frame(变量) 注意:如果使用FirePath校验自己书写的xpath或css表达式是否正确,需要在FirePath面板左上角下拉列表里选择Top Window,这样就是在主网页里进行校验。 示例: # <frame src='frame1.html'> f=driver.find_element(By.XPATH,"//frame[@src='frame1.html']")#//frame[contains(@src,'frame1')] driver.switch_to.frame(f) 4.切换进入Frame的子网页里以后,可以定位该子网页里的所有元素来操作,但是不能定位其他子网页或主网页里的元素。 (1)如果已经切换进入某个frame内,从该frame回到默认主网页,下面的语法可以切换: driver.switch_to.default_content() #---好比从包间1出来,回到进门处---就是指主网页 (2)如果已经回到默认主网页,就可以切换到其他frame里。如果在一个子网页里,不能切换到同级的其他子网页里,否则抛出NoSuchFrameException 示例: driver.switch_to.frame(xxx) …… driver.switch_to.default_content() driver.switch_to.frame(yyy) …… 三、Window切换(窗口切换) 1.应用场景:测试网页里的超级链接或按钮或图片点击动作后,如果看到出现了一个新的浏览器窗口(也可能显示为一个浏览器里的一个新的标签页),我们需要切换Window才能操作新窗口里的网页。 示例:ECShop前台首页,点击“EC论坛”,就会出现一个新的浏览器窗口(以新的标签页形式显示)。 2.切换Window语法:driver.switch_to.window(窗口句柄) 3.窗口句柄(Window Handle):是Windows操作系统在启动每个窗口时,为每个窗口分配的一个唯一标识信息,就是窗口句柄,每个窗口的句柄都不会与其他窗口句柄重复。 4.说明:因为窗口句柄(Window Handle)是Windows操作系统在启动浏览器时动态分配的信息,所以我们无法提前调查网页来获得这个信息,我们需要在程序代码中浏览器启动的步骤后面,通过书写代码来动态获得当前的窗口句柄。 类比: Windows操作系统 ---派出所 窗口 ---人 窗口启动起来 ---人出生后上户口 窗口句柄---身份证号 写代码时不知道窗口句柄具体的值----人还没有出生不知道他的身份证号 运行代码过程中窗口启动起来了就有窗口句柄了----人出生去上完户口,此时有身份证号了 总结:写代码时,可以在出现新窗口的步骤后面,写获得当前窗口句柄的代码。 5.获得窗口句柄的语法: (1)driver.current_window_handle:获得此属性值可以获得当前窗口的句柄。 (2)driver.window_handles:获得此属性值可以获得所有由WebDriver本次运行所启动的窗口的句柄,是以list类型存储的。 6.采用排除法切换到新窗口的算法---适用于一共只有2个窗口的情况: (1)获得当前窗口句柄 (2)获得所有窗口句柄 (3)循环遍历所有窗口句柄 (4)判断如果不等于第(1)步骤的当前窗口句柄 (5)就用这个遍历到的句柄来切换 (6)退出循环 一、Window切换 7.现在一共有2个浏览器窗口,切换窗口的程序代码: # 切换到新窗口 a=driver.current_window_handle b=driver.window_handles for c in b: if c!=a: driver.switch_to.window(c) break 8.现在一共有3个或3个以上浏览器窗口,切换到目标窗口的程序代码:---了解!使用较少! (1)说明:3个或3个以上的情况,在break退出循环之前判断是否是目标浏览器窗口,是的话,就退出,不是的话,继续循环。 (2)判断是否是目标浏览器窗口,需要根据业务数据来判断,比如当前窗口里当前网页的标题、url、网页源代码、网页里是否可以定位到目标元素都可以作为判断的条件。 a.获得当前窗口里当前网页的标题:driver.title b.获得当前窗口里当前网页url:driver.current_url c.获得当前窗口里当前网页源代码(是一个很长的字符串,从<html>开始,到</html>结束):driver.page_source 示例: # 现在一共有3个窗口,希望能切换到网页标题是“复选框案例”的窗口 a=driver.current_window_handle b=driver.window_handles for c in b: if c!=a: driver.switch_to.window(c) if driver.title=="复选框案例": break (3)判断业务数据的代码: a.判断业务数据等于某值 示例1: if driver.title=="复选框案例": 示例2: if driver.current_url=="http://localhost/demo03.html": b.判断业务数据包含某值: 示例1: if "复选框" in driver.title: 示例2: if "demo03" in driver.current_url: 示例3: if "爬山" in driver.page_source c.判断业务数据开头部分: 示例: if driver.title.startswith("复选框"): d.判断业务数据结尾部分: 示例: if driver.current_url.endswith("demo03.html"): 9.补充:关闭浏览器窗口的函数 (1)driver.quit() 一次性关闭所有由WebDriver代码运行而启动的浏览器窗口,一般放在代码末尾,用于清理测试环境。 (2)driver.close() 只关闭当前浏览器窗口,也就是你刚刚还在操作的那个浏览器窗口或刚切换过来的那个窗口,只关闭一个窗口,不关闭其他窗口,一般放在业务步骤之间。 说明:关闭了当前浏览器窗口以后,如果想操作其他浏览器窗口,还是需要切换过去才能操作。 10.目前WebDriver问题:如果在一个浏览器窗口做了一个操作后,如果出现了新的浏览器窗口,就算不切换到新窗口,还想继续操作旧窗口,也必须先获得当前窗口句柄,然后再用这个句柄切换,才能操作旧窗口。 示例: driver=webdriver.Firefox()#打开一个浏览器窗口 driver.get("http://localhost/demo05.html") a2=driver.find_element(By.XPATH,"//a[2]") a2.click()#出现一个新的浏览器窗口 #获得当前窗口句柄,然后再用这个句柄切换 a=driver.current_window_handle driver.switch_to.window(a) a3=driver.find_element(By.XPATH,"//a[3]") a3.click()#又出现一个新的浏览器窗口