场景还原
我们在通过selenium的find_element方法定位页面元素的时候会发现一个问题,我的定位条件没有问题,定位元素也是非隐藏元素,可代码执行时总提示Message: no such element: Unable to locate element,百思不得其解时,最后发现元素嵌套在了iframe当中,无法直接定位。
这个时候我们通常的解决办法就是,查看元素所在的iframe,然后调用selenium的switch_to.frame()跳转到所在的iframe。由于iframe的特性,当存在多层嵌套iframe时,我们还需要一层一层的去跳进跳出,比较繁琐。
解决思路
一、思路构图
把页面中的所有iframe看做一棵树,0代表default_content(),1、2、3节点为并列同层iframe,0、1、4节点为嵌套iframe。元素定位时,当前iframe可能是树的任意位置。采用N次先序遍历的方式,对所有iframe进行遍历检查。具体步骤如下:
1.优先从当前iframe节点第一次遍历,这样可以提升查找效率,此时顺序为1-4-5;
2.将遍历过的iframe存储在一个已遍历集合当中,在下一轮遍历时跳过这些节点;
3.当上一轮遍历未发现目标元素时,返回页面顶层,也就是根节点0;
4.从根节点查找其下子节点,并剔除其中已遍历节点,返回结果为2、3;
4.针对2、3节点进行递归循环查找,最终遍历顺序为1-4-5-0-2-6-3-7-8。
二、方法实现
过滤隐藏iframe
def elementisvisable(self,element:WebElement):
'''
判断元素是否可见,在selenium的判断的基础上增加了一些特殊的判断。判断了元素尺寸。
:param element: 元素对象
:return: boolean
'''
try:
if not element.is_displayed():
return False
size = element.size
if not int(size['height']) and not int(size['width']):
return False
loc = element.location
if int(loc['x&