0%

Xpath定位方法总结

浏览器控制台下,用Xpath命令调试

  1. 查看元素是否找到,如果有返回一个列表:$x('xpath路径")][text()="项目总数"]')
    示例:

    1
    2
    $x("//*[text()='确认']")
    (4) [span.confirm, span.confirm, span.confirm, span.confirm]
  2. 实现元素点击:$x('xpath路径")][text()="项目总数"]')[0].click()
    示例:

    1
    $x("//*[text()='确认']")[0].click()
  3. 调试模式下的其它元素定位方法

定位路径表达式

表达式实例描述
/xpath('//div')路径以/开始,表示找到满足绝对路径的元素
//xpath('//div')路径以//开始,表示找到文档中所有满足//后规则的元素,如//div表示找到所有div元素
*xpath('/div/*')表示选择所有元素
[表达式]xpath('/body/div[1]')
xpath('/body/div[@class]')
xpath('/body/div[@class="main"]')
①[数字]:表示选择第几个,其中[last()]表示最后一个
②[@属性]限定满足该属性,如//TEXT[@name]表示含有name属性的TEXT元素;//TEXT[not(@*)]表示所有没有属性的TEXT元素;
/TEXT[@name="text"]表示所有含有name属性且其值为textTEXT元素
|xpath(‘//div|//table’)逻辑或,将多个路径合并到一起,如//BBB | /AAA 选择所有BBB元素和根元素AAA;可合并的路径数目没有限制

Xpath定位方法

  1. 绝对路径定位
    就是从根部开始找,一级一级往下走,如果有同级别的需要用[]标明序号,从1开始

    1
    2
    3
    4
    5
    6
    7
    8
    // CSDN博客的博主头像
    //*[@id="csdn_container_tool"]/div/ul/li[6]/div[1]/a/img
    // CSDN博客的CSDNlogo
    //*[@id="nav-left-menu"]/li[1]/a/img

    // CSDN博客的搜索框的两种xpath定位方法
    //*[@id="toolber-keyword"]
    /html/body/div[4]/div/ul/div/input
  2. 相对路径定位

    1
    /html/body/div[1]/div[2]/div[1]/div[1]/form/span[1]/input

    以下都以定位到input做说明。

2.1 元素本身查找(@表示属性)

1
2
3
//input[@id="kw"]
//*[@id="kw"]
//*[@type="text"]

//input表示匹配input标签的所有元素
//*表示匹配所有元素的标签

2.2 布尔值写法
如果input标签中,id不是唯一的,type也不是唯一的,但在该页面中包含该idtype的只有这个元素时,就可以用组合的方式定位

1
2
//*[@id="kw" and @type="text"]
//*[@id="kw" or @type="text"]

2.3 找父级
如果自己没有唯一的标志,那么就找自己的上级(父级),或者上级的上级,以此类推。

1
2
3
4
//找父级
//span[@class="s_ipt_w"]/input
//找父级的父级
//form[@id="form"]/span[1]/input

2.4 跳级
如果需要定位的元素在该页面不是唯一,但在某个容器内是唯一的,当然那个容器必须要有唯一的标志;
该方法要保证在某容器内该元素是唯一的。

1
//div[@id="wrapper"]//input[@id="kw"]
  1. Xpath函数过滤
  2. 1 contains()
    1
    //div[contains(@id,'in')]
    表示选择id中包含有indiv节点

3.2 text()

1
//a[text()='baidu']

由于一个节点的文本值不属于属性,比如<a class="baidu" herf="http://www.baidu.com">baidu</a>,所以用text()函数来匹配节点

3.3 last()
表示取列表的最后一个

3.4 start-with()

1
//div[starts-with(@id,'in')]

表示选择以in开头的id属性的div节点

3.5 not()函数

1
//input[@name='identity' and not(contains(@class, 'a'))]

表示匹配出nameidentity,并且class的值中不包含a的input节点;
not()函数通常与返回值为true or false的函数组合使用,比如contains()starts-with()等;
有一种特殊情况需要注意:要匹配出input节点下所有的id属性//input[@id],要匹配出input节点下不含有id属性//input[not(@id)]

  1. 轴&步
    轴可定义相对于当前节点的节点集。
轴名称描述
ancestor选取当前节点的所有先辈(父、祖父等)。
ancestor-or-self选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
attribute选取当前节点的所有属性。
child选取当前节点的所有子元素。
descendant选取当前节点的所有后代元素(子、孙等)。
descendant-or-self选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following选取文档中当前节点的结束标签之后的所有节点。
following-sibling选取当前节点之后的所有同级节点
namespace选取当前节点的所有命名空间节点。
parent选取当前节点的父节点。
preceding选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling选取当前节点之前的所有同级节点。
self选取当前节点。

语法:轴名称::节点测试[谓语]

实例1

例子结果
child::book选取所有属于当前节点的子元素的 book 节点。
attribute::lang选取当前节点的 lang 属性。
child::*选取当前节点的所有子元素。
attribute::*选取当前节点的所有属性。
child::text()选取当前节点的所有文本子节点。
child::node()选取当前节点的所有子节点。
descendant::book选取当前节点的所有 book 后代。
ancestor::book选择当前节点的所有 book 先辈。
ancestor-or-self::book选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点)
child::*/child::price选取当前节点的所有 price 孙节点。

实例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<div data-v-f7a7d94e="" id="carInfo" class="mt48">
<div data-v-f7a7d94e="" class="title">车辆信息</div>
<div data-v-f7a7d94e="" class="content">
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">车型</div>
<div data-v-f7a7d94e="" class="value">2016款 锐行 1.5L 手动风尚版</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">外观颜色</div>
<div data-v-f7a7d94e="" class="value">泰晤士青</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">内饰颜色</div>
<div data-v-f7a7d94e="" class="value">黑色</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">车型编码</div>
<div data-v-f7a7d94e="" class="value">15004-n</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">车架号</div>
<div data-v-f7a7d94e="" class="value">-</div>
</div>
</div>
</div>

<div data-v-f7a7d94e="" id="princeInfo" class="mt48">
<div data-v-f7a7d94e="" class="title">金额信息</div>
<div data-v-f7a7d94e="" class="content">
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">裸车价</div>
<div data-v-f7a7d94e="" class="value">¥ 0.06</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">装潢合计</div>
<div data-v-f7a7d94e="" class="value">-</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">金融合计</div>
<div data-v-f7a7d94e="" class="value">-</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">保险合计</div>
<div data-v-f7a7d94e="" class="value">-</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">延保金额</div>
<div data-v-f7a7d94e="" class="value">-</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">代办合计</div>
<div data-v-f7a7d94e="" class="value">-</div>
</div>
<div data-v-f7a7d94e="" class="item">
<div data-v-f7a7d94e="" class="label mr12">实际成交价</div>
<div data-v-f7a7d94e="" class="value">¥ 0.06</div>
</div>
</div>
</div>

UI组件化获取label对应的value:

1
//div[@class='title' and contains(text(),'"+分组名+"')]/parent::div/div[@class='content']/descendant::div[contains(@class,'label') and text()='"+标签+"']/parent::div/div[@class='value']
  • 分组名:选择的title的名称
  • 标签:选择的label的名称
  • //div[@class='title' and contains(text(),'"+分组名+"')]:选取div中,class等于title,并且div中文案包含对应的分组名的节点
  • parent::div/div[@class='content']:选取父级div节点的子div节点中,class等于content的节点
  • descendant::div[contains(@class,'label') and text()='"+标签+"']:选取当前节点所有的div子节点中,class包含label,并且文本等于标签值的节点
  • parent::div/div[@class='value']:选取父级div节点的子div节点中,class等于value的节点