递归遍历frame
经常用selenium定位元素时,定位方式试过,就是报找不到元素,然后发现元素在另一个frame里面,需要切换,多个frame的话,需要切来切去,十分不方便。这里封装一个方法findElement,可以递归遍历所有frame,一个个去找这个元素,直到找到为止,分享之。
这里的实例用的IEDriverServer.exe,没有的童鞋,需要网上下载,并拷贝到C:\Program Files\Internet Explorer\目录下,目录可以修改,熟悉selenium的可以根据喜好更改。
# -*- coding:utf-8 -*-
from selenium import webdriver
import os
from selenium.webdriver.common.by import By
#IE
IEDriverServer = "C:\Program Files\Internet Explorer\IEDriverServer.exe"
os.environ["webdriver.ie.driver"] = IEDriverServer
driver = webdriver.Ie(IEDriverServer)
def isGetElement(by=By.ID,location='input_text'):
try:
driver.find_element(by,location)
return True
except Exception ,err :
return False
def findElement(by=By.ID,location='input_text'):
res=None
if isGetElement(by,location):
res=driver.find_element(by,location)
return res
driver.switch_to_default_content() #初始化切换回default frame
if isGetElement(by,location): # 此处操作,应对元素在根frame下的情况
res=driver.find_element(by,location)
return res
if isGetElement(By.XPATH,"//iframe"):
elems=driver.find_elements(By.XPATH,"//iframe")
for index in range(len(elems)):
driver.switch_to_frame(index)
if(isGetElement(by,location)):
res=driver.find_element(by,location)
break
else:
res = findElement_child(by,location)
if res is not None:
break
else:
driver.switch_to.parent_frame()
if res is None:
raise WebDriverException("Can't find element ["+location+"]")
else:
return res
def findElement_child(by=By.ID,location='input_text'):
res = None
if isGetElement(By.XPATH,"//iframe"):
elems=driver.find_elements(By.XPATH,"//iframe")
for index in range(len(elems)):
driver.switch_to_frame(index)
if(isGetElement(by,location)):
res=driver.find_element(by,location)
return res
else:
res = findElement_child(by,location)
if res is not None:
return res
else:
driver.switch_to.parent_frame()
else:
return None
#最后调用,根据需要做调整,下面是实例
driver.get('http://*.*.*.*/url')
driver.maximize_window()
findElement(By.ID, 'username').send_keys('admin')
findElement(By.ID, 'password').send_keys('123456')
这样封装,优缺点
优点:不用手动切换frame,避免不必要的错误,十分方便。
确定:测试的系统frame过多时,效率会慢一点;不同frame下有相同的id,则直接返回第一个找到的那个,不一定是想要的。