XPath & CSS元素定位----一篇搞定

本文详细对比了XPath和CSS在元素定位上的差异,并深入探讨XPath的定位技术,包括基本符号、轴定位、常用表达式及如何处理元素属性。同时,文章也提及了CSS定位的要点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



1.XPath 与 CSS selector 的对比

描述XPathCSS selector
父元素//div/.
使用ID定位//div[@id=‘id_value’]div#id_value
使用class定位//div[@class=‘class_value’]div.class_value
使用name定位//div[@name=‘name_value’]div[name=‘name_value’]
多属性定位//div[@name=‘name_value’ and class=‘class_value’]div[@name=‘name_value’] [class=‘class_value’]
第N个子元素//ul[@id=‘id_value’]/li[4]u#id_val li:nth-child(4)
最后一个元素//ul[@id=‘id_value’]/li[last()]u#id_val li:last-child
属性包含某字段//div[contains(@title, “text”)]div[title*=“text”]
属性以xxx开头//div[starts-with(@title, “text”)]div[title^=“text”]
属性以xxx结尾//div[ends-with(@title, “text”)]div[title$=“text”]
text中包含某字段//div[contains(text(), “text”)] 。
凡是用text()的地方均可以直接用.来进行表示。
例如a[text()=’SELENIUM’] 和 a[.=’SELENIUM’]是等价的。
同级弟弟元素//div[@id=‘D’]/following-sibling::div[1]
同级哥哥元素//li/preceding-sibling::div[1]


2.XPath定位详情



(1)基本符号的介绍

XPath运算符说明
/此路径运算符出现在模式开头时,表示应从根节点选择。
//是指从全文上下文中搜索//后面的节点
.//从当前节点开始递归下降。此路径运算符出现在模式开头时,表示应从根节点递归下降。
.当前上下文。
当前上下文节点父级。
*通配符;选择所有元素节点与元素名无关。(不包括文本,注释,指令等节点,如果也要包含这些节点请用node()函数)
@属性名的前缀。
@*选择所有属性,与名称无关。
:命名空间分隔符;将命名空间前缀与元素名或属性名分隔。
( )括号运算符(优先级最高),强制运算优先级。
[ ]应用筛选模式(即谓词,包括"过滤表达式"和"轴(向前/向后)")。
[ ]下标运算符;用于在集合中编制索引。
-减法。
div浮点除法。
and, or逻辑运算。
mod求余。
not()逻辑非
=等于
!=不等于
特殊比较运算符< 或者 <= 或者 > 或者 >=
normalize-space去掉文字前后的空格、回车,.//a[normalize-space(text())=‘XXXXX’]


(2)轴(Axis)定位

XPath轴名称说明
ancestor选取当前节点的所有先辈(父、祖父等)
ancestor-or-self选取当前节点的所有先辈(父、祖父等)以及当前节点本身
attribute选取当前节点的所有属性
child选取当前节点的所有子元素。
descendant选取当前节点的所有后代元素(子、孙等)。
descendant-or-self选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following选取文档中当前节点的结束标签之后的所有节点。
namespace选取当前节点的所有命名空间节点
parent选取当前节点的父节点。
preceding直到所有这个节点的父辈节点,顺序选择每个父辈节点前的所有同级节点
preceding-sibling选取当前节点之前的所有同级节点。
self选取当前节点。


(3)xpath 常用的表达式

常用表达式举例说明
/Document Root文档根.
/*选择文档根下面的所有元素节点,即根节点(XML文档只有一个根节点)
/node()根元素下所有的节点(包括文本节点,注释节点等)
/text()查找文档根节点下的所有文本节点
/messages/messagemessages节点下的所有message节点
/messages/message[1]messages节点下的第一个message节点
/messages/message[1]/self::node()第一个message节点(self轴表示自身,node()表示选择所有节点)
/messages/message[1]/node()第一个message节点下的所有子节点
/messages/message[1]/*[last()]第一个message节点的最后一个子节点
/messages/message[1]/[last()]Error,谓词前必须是节点或节点集
/messages/message[1]/node()[last()]第一个message节点的最后一个子节点
/messages/message[1]/text()第一个message节点的所有子节点
/messages/message[1]//text()第一个message节点下递归下降查找所有的文本节点(无限深度)
/messages/message[1] /child::node()第一个message节点下的所有子节点
/messages/message[1] /node()第一个message节点下的所有子节点
/messages/message[position()=1]/node()第一个message节点下的所有子节点
//message[@id=1] /node()第一个message节点下的所有子节点
//message[@id=1] //child::node()递归所有子节点(无限深度)
//message[position()=1]/node()选择id=1的message节点以及id=0的message节点
/messages/message[1] /parent:: *Messages节点
/messages/message[1]/body/attachments/parent::node()attachments节点的父节点。父节点只有一个,所以node()和* 返回结果一样。
/messages/message[1]/body/attachments/parent:: *attachments节点的父节点。父节点只有一个,所以node()和* 返回结果一样。
/messages/message[1]/body/attachments/. .attachments节点的父节点。
//message[@id=0]/ancestor:: *Ancestor轴表示所有的祖辈,父,祖父等。 向上递归
//message[@id=0]/ancestor-or-self:: *向上递归,包含自身
//message[@id=0]/ancestor::node()对比使用*,多一个文档根元素(Document root)
/messages/message[1]/descendant::node()递归下降查找message节点的所有节点
//messages/message[1]//node()递归下降查找message节点的所有节点
/messages/message[1]/sender/following:: *查找第一个message节点的sender节点后的所有同级节点,并对每一个同级节点递归向下查找。
//message[@id=1]/sender/following-sibling:: *查找id=1的message节点的sender节点的所有后续的同级节点。
//message[@id=1]/datetime/@date查找id=1的message节点的datetime节点的date属性
//message[@id=1]/datetime[@date]查找id=1的message节点的所有含有date属性的datetime节点
//message/datetime[attribute::date]查找message节点的所有含有date属性的datetime节点
//message[datetime]查找所有含有datetime节点的message节点
//message/datetime/attribute:: *返回message节点下datetime节点的所有属性节点
//message/datetime/attribute::node()返回message节点下datetime节点的所有属性节点
//message/datetime/@*返回message节点下datetime节点的所有属性节点
//message/datetime[attribute:: *]选择所有含有属性的datetime节点
//message/datetime[attribute::node()]选择所有含有属性的datetime节点
//message/datetime[@*]选择所有含有属性的datetime节点
//message/datetime[@node()]选择所有含有属性的datetime节点
//attribute:: *选择根节点下的所有属性节点
//message[@id=0]/body/preceding::node()顺序选择body节点所在节点前的所有同级节点。(查找顺序为:先找到body节点的顶级节点(根节点),得到根节点标签前的所有同级节点,执行完成后继续向下一级,顺序得到该节点标签前的所有同级节点,依次类推。) 注意:查找同级节点是顺序查找,而不是递归查找。
//message[@id=0]/body/preceding-sibling::node()顺序查找body标签前的所有同级节点。(和上例一个最大的区别是:不从最顶层开始到body节点逐层查找。我们可以理解成少了一个循环,而只查找当前节点前的同级节点)
//message[@id=1]//*[namespace::amazon]查找id=1的所有message节点下的所有命名空间为amazon的节点。
//namespace:: *文档中的所有的命名空间节点。(包括默认命名空间xmlns:xml)
//message[@id=0]//books/*[local-name()=‘book’]选择books下的所有的book节点, 注意:由于book节点定义了命名空间amazone:book.若写成//message[@id=0]//books/book则查找不出任何节点。
//message[@id=0]//books/*[local-name()=‘book’ and namespace-uri()=‘http://www.amazon.com/books/schema’]选择books下的所有的book节点,(节点名和命名空间都匹配)
//message[@id=0]//books/*[local-name()=‘book’][year>2006]选择year节点值>2006的book节点
//message[@id=0]//books/*[local-name()=‘book’][1]/year>2006指示第一个book节点的year节点值是否大于2006. 返回xs:boolean: true


(4)xpath 元素中某属性不包含XXX

  • 选择不包含class属性的节点

var result = node.SelectNodes(“.//span[not(@class)]”);

  • 选择不包含class和id属性的节点

var result = node.SelectNodes(“.//span[not(@class) and not(@id)]”);

  • 选择不包含class="expire"的span

var result = node.SelectNodes(“.//span[not(contains(@class,‘expire’))]”);

  • 选择包含class="expire"的span

var result = node.SelectNodes(“.//span[contains(@class,‘expire’)]”);

  • class包含属性displayDiv,但class又不包含groupTitle

//div[contains(@class,‘displayDiv’)][not(contains(@class,‘groupTitle’))]



3.CSS定位详情

CSS选择器示例说明CSS
.class.intro选择 class=“intro” 的所有元素。1
#id#firstname选择 id=“firstname” 的所有元素。1
**选择所有元素。2
elementp选择所有 <p> 元素。1
element,elementdiv,p选择所有 <div> 元素和所有 <p> 元素。1
element elementdiv p选择 <div> 元素内部的所有 <p> 元素。1
element>elementdiv>p选择父元素为 <div> 元素的所有 <p> 元素。2
element+elementdiv+p选择紧接在 <div> 元素之后的所有 <p> 元素。2
[attribute][target]选择带有 target 属性所有元素。2
[attribute=value][target=_blank]选择 target=“_blank” 的所有元素。2
[attribute~=value][title~=flower]选择 title 属性包含单词 “flower” 的所有元素。2
[attribute=value][lang=en]
:linka:link选择所有未被访问的链接。1
:visiteda:visited选择所有已被访问的链接。1
:activea:active选择活动链接。1
:hovera:hover选择鼠标指针位于其上的链接。1
:focusinput:focus选择获得焦点的 input 元素。2
:first-letterp:first-letter选择每个 <p> 元素的首字母。1
:first-linep:first-line选择每个 <p> 元素的首行。1
:first-childp:first-child选择属于父元素的第一个子元素的每个 <p> 元素。2
:beforep:before在每个 <p> 元素的内容之前插入内容。2
:afterp:after在每个 <p> 元素的内容之后插入内容。2
:lang(language)p:lang(it)选择带有以 “it” 开头的 lang 属性值的每个 <p> 元素。2
element1~element2p~ul选择前面有 <p> 元素的每个 <ul> 元素。3
[attribute^=value]a[src^=“https”]选择其 src 属性值以 “https” 开头的每个 <a> 元素。3
[attribute$=value]a[src$=“.pdf”]选择其 src 属性以 “.pdf” 结尾的所有 <a> 元素。3
[attribute*=value]a[src*=“abc”]选择其 src 属性中包含 “abc” 子串的每个 <a> 元素。3
:first-of-typep:first-of-type选择属于其父元素的首个 <p> 元素的每个 <p> 元素。3
:last-of-typep:last-of-type选择属于其父元素的最后 <p> 元素的每个 <p> 元素。3
:only-of-typep:only-of-type选择属于其父元素唯一的 <p> 元素的每个 <p> 元素。3
:only-childp:only-child选择属于其父元素的唯一子元素的每个 <p> 元素。3
:nth-child(n)p:nth-child(2)选择属于其父元素的第二个子元素的每个 <p> 元素。3
:nth-last-child(n)p:nth-last-child(2)同上,从最后一个子元素开始计数。3
:nth-of-type(n)p:nth-of-type(2)选择属于其父元素第二个 <p> 元素的每个 <p> 元素。3
:nth-last-of-type(n)p:nth-last-of-type(2)同上,但是从最后一个子元素开始计数。3
:last-childp:last-child选择属于其父元素最后一个子元素每个 <p> 元素。3
:root:root选择文档的根元素。3
:emptyp:empty选择没有子元素的每个 <p> 元素(包括文本节点)。3
:target#news:target选择当前活动的 #news 元素。3
:enabledinput:enabled选择每个启用的 <input> 元素。3
:disabledinput:disabled选择每个禁用的 <input> 元素。3
:checkedinput:checked选择每个被选中的 <input> 元素。3
:not(selector):not§选择非 <p> 元素的每个元素。3
::selection::selection选择被用户选取的元素部分。3


部分内容来源:
1.https://blog.csdn.net/weixin_40326608/article/details/101202935

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值