一、选取节点
常用的路径表达式:
表达式 | 描述 | 实例 | |
nodename | 选取nodename节点的所有子节点 | xpath(‘//div’) | 选取了div节点的所有子节点 |
/ | 从根节点选取 | xpath(‘/div’) | 从根节点上选取div节点 |
// | 选取所有的当前节点,不考虑他们的位置 | xpath(‘//div’) | 选取所有的div节点 |
. | 选取当前节点 | xpath(‘./div’) | 选取当前节点下的div节点 |
.. | 选取当前节点的父节点 | xpath(‘..’) | 回到上一个节点 |
@ | 选取属性 | xpath(’//@calss’) | 选取所有的class属性 |
二、谓语
谓语被嵌在方括号内,用来查找某个特定的节点或包含某个制定的值的节点
实例:
表达式 | 结果 |
xpath(‘/body/div[1]’) | 选取body下的第一个div节点 |
xpath(‘/body/div[last()]’) | 选取body下最后一个div节点 |
xpath(‘/body/div[last()-1]’) | 选取body下倒数第二个div节点 |
xpath(‘/body/div[positon()<3]’) | 选取body下前两个div节点 |
xpath(‘/body/div[@class]’) | 选取body下带有class属性的div节点 |
xpath(‘/body/div[@class=”main”]’) | 选取body下class属性为main的div节点 |
xpath(‘/body/div[price>35.00]’) | 选取body下price元素值大于35的div节点 |
三、通配符
Xpath通过通配符来选取未知的XML元素
表达式 | 结果 |
xpath(’/div/*’) | 选取div下的所有子节点 |
xpath(‘/div[@*]’) | 选取所有带属性的div节点 |
四、取多个路径
使用“|”运算符可以选取多个路径
表达式 | 结果 |
xpath(‘//div|//table’) | 选取所有的div和table节点 |
五、Xpath轴
轴可以定义相对于当前节点的节点集
轴名称 | 表达式 | 描述 |
ancestor | xpath(‘./ancestor::*’) | 选取当前节点的所有先辈节点(父、祖父) |
ancestor-or-self | xpath(‘./ancestor-or-self::*’) | 选取当前节点的所有先辈节点以及节点本身 |
attribute | xpath(‘./attribute::*’) | 选取当前节点的所有属性 |
child | xpath(‘./child::*’) | 返回当前节点的所有子节点 |
descendant | xpath(‘./descendant::*’) | 返回当前节点的所有后代节点(子节点、孙节点) |
following | xpath(‘./following::*’) | 选取文档中当前节点结束标签后的所有节点 |
following-sibing | xpath(‘./following-sibing::*’) | 选取当前节点之后的兄弟节点 |
parent | xpath(‘./parent::*’) | 选取当前节点的父节点 |
preceding | xpath(‘./preceding::*’) | 选取文档中当前节点开始标签前的所有节点 |
preceding-sibling | xpath(‘./preceding-sibling::*’) | 选取当前节点之前的兄弟节点 |
self | xpath(‘./self::*’) | 选取当前节点 |
六、功能函数
使用功能函数能够更好的进行模糊搜索
函数 | 用法 | 解释 |
starts-with | xpath(‘//div[starts-with(@id,”ma”)]‘) | 选取id值以ma开头的div节点 |
contains | xpath(‘//div[contains(@id,”ma”)]‘) | 选取id值包含ma的div节点 |
and | xpath(‘//div[contains(@id,”ma”) and contains(@id,”in”)]‘) | 选取id值包含ma和in的div节点 |
text() | xpath(‘//div[contains(text(),”ma”)]‘) | 选取节点文本包含ma的div节点 |
补充:
//input[not(@id='123')] 找id不为123的input
//span[substring(@name,3,5)='xxxxx'] name属性第3个字符开始的5个字符是xxxxx的
//span[sbustring-before(@class,"-")="spanclass1"] class属性中-字符前面的字符是spanclass1
//span[sbustring-after(@class,"-")="spanclass1"] class属性中-字符后面的字符是spanclass1
//div[div[@id='xxx']] 依靠子节点定位
xpath中/与//的区别
/表示指定路径下的所有符合条件的节点,//表示指定路径下匹配模式的所有节点。这样说很难区分,举例:
(1) ./parameter:表示本节点下(不包括子节点)下所有的parameter节点集
(2) .//parameter: 表示本节点及其所有子节点下的parameter节点集(包括子节点、孙节点、子子孙孙都包括)
<interactionClass name="Viechle_Move" sharing="PublishSubscribe" transportation="HLAreliable" order="TimeStamp" semantics="GX01">
<parameter name="federate_type" dataType="string"/>
<interactionClass name="Engage_Event" sharing="PublishSubscribe" transportation="HLAreliable" order="TimeStamp">
<parameter name="action_instance_handle" dataType="long"/>
<parameter name="target_instance_handle" dataType="long"/>
<parameter name="position_x" dataType="double"/>
<parameter name="position_y" dataType="double"/>
<parameter name="position_z" dataType="double"/>
</interactionClass>
</interactionClass>
假定当前节点为"Viechle_Move",对于(1),则只包括"federate_type"一个parameter结点,
而对于(2)则包括了本节点的一个parameter和子节点Engage_Event下的5个parameter节点
实例
Xpath 中的绝对路径从 HTML 根节点开始算,相对路径从任意节点开始。
通过开发者工具,我们可以拷贝到 Xpath 的绝对路径和相对路径代码:
但是由于拷贝出来的代码缺乏灵活性,也不全然准确。大部分情况下,都需要自己定义 Xpath 语句,因此 Xpath 语法还是有必要学习。
绝对路径:
Xpath 中最直观的定位策略就是绝对路径。
以百度中的输入框和按钮为例,通过拷贝出来的 full Xpath:
/html/body/div[2]/div/div/div/div/form/span/input
这就是一个绝对路径我们可以看出,绝对路径是从根节点
/html
开始往下,一层层的表示出来直到需要的节点为止。
这明显不是理智的选项,因此了解以下即可,不用往心里去。
相对路径
除了绝对路径,Xpath 中更常用的方式是相对路径定位方法,以“//”开头。
相对路径可以从任意节点开始,一般我们会选取一个可以唯一定位到的元素开始写,可以增加查找的准确性。
相对路径可以通过以下的方式来定位元素:
基本定位语法
定位语法主要依赖于以下特殊符号:
元素属性定位
属性定位是通过 @ 符号指定需要使用的属性。
- 根据元素是否具备某个属性查找元素
//*[@data-recordid]
选取包含data-recordid属性的所有节点。可以定位到以下元素:
<tr role="row" data-boundview="gridview-1029" data-recordid="B36BCA33" ></tr>
- 根据属性是否等于某值查找元素
//span[@role='img']
选取属性 role 的属性值为 img 的所有节点。可以定位到以下元素:
<span role="img" class="x-btn-icon-el" unselectable="on" style=""></span>
<form action="search" id="form" method="post">
<span class="bg">
<span class="soutu">搜索</span>
</span>
<span class="soutu">
<input type="text" name="key" id="su">
</span>
</form>
- 根据层级向下找,从 form 找到绿色的 span:
//form[@id="form"]/span/span
- 查找某元素内部的所有元素,选取 form 元素内部的所有 span:
//form[@id="form"]//span
第二个双斜杠,表示选取内部所有的 span,不管层级关系
- 使用星号找不特定的元素
//*[@id="form"]//*[@type="text"]
选取 id 属性为 form 的任意属性内部,并且 type 属性为 text 的任意元素。这里会找到 input。
- 使用
从下往上找,根据 input 查找其父节点 span:..
//input[@name="key"]/..
注意最后的两个点,找到 input 节点的上级节点,如果还要再往上再加 /..
- 找同级节点:比如我们想通过第一个 span 标签去 找 div 标签。树形结构中,兄弟节点之间的关系是通过父节点建立起来的。所以可以先找到父节点,再通过父节点找同级节点。
//span[@class="bg"]/../div
先通过/..找到 span 的父节点,再通过父节点找到 div。
使用谓语定位
谓语是 Xpath 中用于描述元素位置。主要有数字下标、最后一个子元素
last()
、元素下标函数
position()
。
- 使用下标的方式,从 form 找到 input :
//form[@id="form"]/span[2]/input
Xpath 中的下标从 1 开始。
- 查找最后一个子元素,选取 form 下的最后一个 span:
//form[@id="form"]/span[last()]
- 查找倒数第几个子元素,选取 form 下的倒数第一个 span:
//form[@id="form"]/span[last()-1]
- 使用 position() 函数,选取 from 下第二个 span:
//form[@id="form"]/span[position()=2]
- 使用 position() 函数,选取下标大于 2 的 span:
//form[@id="form"]/span[position()>2]
使用逻辑运算符
如果元素的某个属性无法精确定位到这个元素,我们还可以用逻辑运算符 and 连接多个属性进行定位,以百度输入框为例。
使用
and
:
//*[@name='wd' and @class='s_ipt']
查找 name 属性为 wd 并且 class 属性为 s_ipt 的任意元素
使用
or
:
//*[@name='wd' or @class='s_ipt']
使用
|
,同时查找多个路径,取或:
//form[@id="form"]//span | //form[@id="form"]//input
使用文本定位
使用文本定位,是 Xpath 中的一大特色。在自动化测试中,为了让代码的可读性更高,可以使用文本的方式。
以下一个案例:
<tr>
<td valign="top">
<input type="radio" name="payment" value="1" checked="" iscod="0">
</td>
<td valign="top">
<strong>支付宝</strong>
</td>
</tr>
红色箭头表示查找路径,先定位到“支付宝”所在的 strong,再定位
td -> tr -> td - >input
。那么要定位“支付宝”文本,就需要用到 Xpath 中的函数
text()
或
string()
,注意是函数,所以括号不能少。
text()
:当前元素节点包含的文本内容;
表达式
//div[text()="文本"]
,能找到:
<div>文本</div>
不能找到:
<div><span>文本</span></div>
string()
:当前元素节点内部所有节点元素的文本内容。表达式
//div[string()="文本"]
上述两种情况都能找到。
好,接着写上面的内容。先通过
//strong[text()="支付宝"]
定位到“支付宝”所在的元素 strong,再找上级 td -> tr,再向下找:
//strong[text()="支付宝"]/../../td[1]/input
//td[string()="支付宝"]/../td[1]/input
使用部分匹配函数
Xpath 中有提供了几个函数,用来进行部分匹配。
【错误原因】//a/@href获取的是全部html下的a标签。并不是我们筛选出来的div中的a标签。
【解决方法】应该使用.//a/@href (注:前面加了点)
xpath 爬去百度