pythonUI自动化之Xpath元素定位003

前言:

  元素定位有很多种方式,id、class、css等等,但为了系统的稳定性,后续少维护代码,使用Xpath是明智的方法。

  我们在找属性时,注意尽量找不会发生产变动,具有唯一的标签。

  Xpath分为(绝对路径)和(相对路径),两个方法各有千秋:

    (绝对路径)定位:根据元素的位置来定位元素,缺点是元素位置发生变动,维护工作量巨大。不建议的大量使用

    (相对路径)定位:根据元素的唯一特征来定位,支持逻辑运算。相对于(绝对路径)后期维护工作量小。可广泛应用至自动化中。

  

 

以下是Xpath 表达式的作用符号。需要注意的是/如果是放在最前面,表示根节点,如果不是,则表示下一节点。

 

 

这里已“百度一下”按钮为例演示,首先是xpath语法的标准格式://标签名[@属性名=属性值]

首先按F12调出开发者模式,然后按Ctrl+F进入查询模式。在下图中,input是标签名,value是属性名,“百度一下”是属性值。

所以最简单的语法便是://input[@value="百度一下"]

 

 

 

接下来我们来升级一下语法:逻辑运算格式,可以使用and之外还可以使用or

//*[@属性名=属性值 and @属性名=属性值]  #*是代表匹配所有标签,不建议使用。

//input[@属性名=属性值 or @属性名=属性值]

 

 XPath提供了多种比较运算符,如 =(等于)、!=(在XPath 2.0及更高版本中)、//book[not(@price=35)](旧版1.0版本中)、<(小于)、<=(小于或等于)、>(大于)和>=(大于或等于)。但是,请注意,并非所有XPath处理器都支持XPath 2.0或更高版本,其中!=是在XPath 2.0中引入的。

 

在以上基础上加上文本定位:

  格式://标签名[@属性名="属性值" and text()="文本"]    #此为完全匹配

  格式2://标签名[contains(text(),"部分文本内容")]  #此为部分匹配。如果是app, 则需要加@,并且把括号去掉, 如//标签名[contains(@text,"部分文本内容")]

       //标签名[contains(@属性名,"部分属性值")]  #属性值部分匹配。

加上层级条件:

  格式://父标签[@父属性名="父属性值"]//子标签[@子属性名="子属性值"]    #中间的//意思是匹配以下所有标签,如果是/,则表示的是下一个节点标签。

加上同级条件:在上面的标签属于哥哥,在下面的标签属于弟弟。

  定位的元素如果属于哥哥:preceding-sibling

  //标签1[@属性名1="属性值1"]/preceding-sibling::标签2[@属性名2="属性值2"]

  定位的元素如果属于弟弟:following-sibling

  //标签1[@属性名1="属性值1"]/following-sibling::标签2[@属性名2="属性值2"]

 

由子节点定位父节点,示例://span[text()="子节点元素"]/.. 

 

轴定位

     XPath轴(XPath Axes)可定义某个相对于当前节点的节点集:

     1、child  选取当前节点的所有子元素

     2、parent  选取当前节点的父节点

     3、descendant 选取当前节点的所有后代元素(子、孙等)

    示例://div[@id="aabbc"]/descendant::span[text()="订单"]

     4、ancestor  选取当前节点的所有先辈(父、祖父等)

     5、descendant-or-self  选取当前节点的所有后代元素(子、孙等)以及当前节点本身

     6、ancestor-or-self  选取当前节点的所有先辈(父、祖父等)以及当前节点本身

     7、preceding-sibling 选取当前节点之前的所有同级节点

     8、following-sibling 选取当前节点之后的所有同级节点

     9、preceding   选取文档中当前节点的开始标签之前的所有节点

     10、following   选取文档中当前节点的结束标签之后的所有节点

     11、self  选取当前节点

     12、attribute  选取当前节点的所有属性

     13、namespace 选取当前节点的所有命名空间节点

     descendant-or-self跟descendant类似,多了节点本身。

 

经验分享:

1. 下拉框:

  可以先点击“下拉框”让它弹出选项,再对选项进行“点击”选取。这类操作在某些场景下依旧会出现定位不到,最保险的方法是 “点击”下拉框 > “输入”想要的值 > “点击”搜索出来的值。如果下拉框没有搜索功能,则只能模拟鼠标滑动事件来解决。

 

2. 关于窗口切换:

  某些场景下,窗口切换是需要加上“等待时间”的,否则窗口会切换失败。原因是因为窗口句柄没有加载出来就切换了,但是加上固定等待时间会显示非常lou,你可以写一个循环语句来判断窗口是否切换成功,或者写一个try解释器。

  如何切换窗口?

    wid1 = wd.window_handles #获取所有窗口句柄

    wd.switch_to.window(wid1[2]) #切换到最新的窗口句柄

    #切换会旧窗口

    driver.switch_to.window(self.driver.window_handles[1]) # 切换到新页签  

    driver.close() # 关闭当前新页签

    driver.switch_to.window(self.driver.window_handles[0])  # 然后切换回原始页签

 

3. 关于iframe:

  某些人分不清iframe和窗口的区别。 窗口相当于另一个浏览器页签,iframe是嵌套在html中的另一个页签。两者的定位方式都大同小异,都是得先切换到新页签,才能对页签里面的元素操作。

  元素在不同“窗口”这很好判断,视觉上就可以判断出来。但是元素是否处于不同iframe却不好判断,虽然你看着两个按钮都在同一个界面,但他们可能并不同属一个iframe,你可以通过往下查看定位元素的父父...级元素,如果出现iframe,则说明当前定位元素出现别的iframe中。

  如何切换iframe?

    iframe=driver.find_elements_by_xpath(“//iframe[@id="123"]”) #定位iframe框架
    driver.switch_to.frame(iframe)                  #切换到iframe框架
    driver.find_elements_by_xpath(“//input[@id="123"]”).click()   #对iframe里的元素操作
    driver.switch_to.default_content()                #退出iframe

 

posted @ 2021-10-17 10:55  博无止境  阅读(331)  评论(0编辑  收藏  举报