所以另外更好的解决方法则是Xpath的复合条件定位,比如下面的代码,先选择class为ant-modal-root的div,然后找到它下面class为ant-modal-wrap并且style属性不含有none关键字的div,再找到该div下面按钮文本为确定的按钮
//div[@class="ant-modal-root"]/div[(@class="ant-modal-wrap") and not(contains(@style,"none"))]//button/span[text()="确 定"]这样就不会因为弹窗层级变化导致定位失败的原因了,还达到了元素地址复用性的目的(两个弹窗共用一个Xpath元素地址)。
但如果有子弹窗的情况下,上面的写法又会失效:

分析上述DOM元素会发现,图片中的两个弹窗无法再通过style中是否存在none来区分了,因为他们都可见,并且分析发现只有aria-labelledby的值不一样:

我们当然可以根据不同的属性,例如上述弹窗的标题不同来区分他们,但这样每个弹窗中的按钮就都需要写一次不同的元素地址。如果为了复用性考虑,我写了如下的代码来实现:
elements=driver.find_elements(
By.XPATH,'//div[@class="ant-modal-root"]/div[(@class="ant-modal-wrap") and not(contains(@style,'
'"none"))]//button/span[text()="确 定"]')
for ele in elements:
if ele.is_displayed():
if ele.is_enabled():
try:
ele.click()
except ElementClickInterceptedException:
pass先获取可见的【确定】按钮对象,然后遍历点击,如果点击报错的话就跳过 (报错是因为有遮罩挡住就会报错,只有页面最前的元素会可点击,刚好达到我们的目的),达到了一个元素地址三个【弹窗】的复用。
但即便这样,同样存在着下面这些不足:
- DOM结构如果很大,执行会变慢,性能损耗;
- 为了复用性会有更多的代码逻辑判断,性能损耗;
- 页面代码发生修改可能需要重新定位元素,修改脚本或用例;
- 编写脚本或用例时,需要去分析DOM结构,调试代码,增加时间成本;
- 有iframe和多页面时需要单独切换;
- 有一定的学习成本;
这样分析下来,维护成本依然不低!那有没有解决方案呢?
肯定是有的,不然我也不会写这篇文章了!
二、解决方案
1. 讲解与演示
我们可以使用图像匹配来定位它,比如网易团队开源的airtest,类似于上述弹窗嵌套有多个【确定】按钮的情况,我们只需要截取一张【确定】按钮的图片,就能解决无数重复的确定按钮的定位了!哪怕页面代码进行了调整,只要你的按钮样式不变,还是原来的按钮的样子,也无须重新调整脚本和代码了!
这是我通过图像匹配的执行效果:

两个【确定】按钮完全共用的是一张图片
2. 实践教学
现在跟着我一起从0开始利用airtest写一个简单的图像识别测试脚本吧
需求
编写一个程序,它会通过图像识别执行点击百度的【新闻】,然后点击【互联网】这两步操作
具体步骤
1.先安装airtest
pip install airtest -i https://pypi.tuna.tsinghua.edu.cn/simple
2.创建一个项目,并输入如下代码:
from airtest.core.api import \*
news_path = 'news.png'
internet_path = 'internet.png'
connect_device('Windows:///')
ST.CVSTRATEGY = ["surf", "tpl"]
ST.FIND_TIMEOUT = 2
touch(Template(news_path))
touch(Template(internet_path))3.先打开百度截取【新闻】图片,再点击新闻,截取【互联网】图片:

截取的图片如下,命令为news.png并保存到代码所在目录


截取的图片如下,命令为internet.png并保存到代码所在目录

4.检查目录文件命名是否与代码中一致

5.让浏览器保持百度访问

6.执行代码然后马上切换回浏览器,执行效果如下:

















