一、文档说明
本文档整合了 XPath 元素定位的核心方法,涵盖属性筛选、可见性判断、相对路径定位三大核心场景,包含语法规则、场景示例、代码实操及验证方式,适用于爬虫、自动化测试等各类元素精准定位需求,兼顾基础用法与进阶技巧,满足不同场景下的定位需求。
二、核心定位场景与语法汇总
第一部分:属性筛选定位
场景1:属性值不等于指定值
-
语法规则 :使用
!=运算符,精准匹配完整属性值并排除目标值。 -
语法 :
//标签名[@属性名!='目标值'] -
适用场景:元素存在该属性,需排除属性值完全等于目标值的元素。
-
示例:
-
HTML 结构:
<div class="item">正常项</div><div class="item disabled">禁用项</div><div class="item hidden">隐藏项</div> -
定位需求:选择
class不等于disabled的div。 -
XPath 表达式:
//div[@class!='disabled'] -
结果:匹配"正常项""隐藏项"对应的
div。
-
场景2:属性中不包含指定字符串
-
语法规则 :使用
not(contains(@属性名, '目标字符串')),适配多值属性(如复合类名)。 -
语法 :
//标签名[not(contains(@属性名, '目标字符串'))] -
适用场景:属性值为复合关键词,需排除包含某关键词的元素。
-
示例:
-
HTML 结构:同上
-
定位需求:选择
class中不含disabled的div。 -
XPath 表达式:
//div[not(contains(@class, 'disabled'))] -
结果:匹配"正常项""隐藏项"对应的
div。
-
场景3:元素无指定属性
-
语法规则 :使用
not(@属性名),筛选完全不存在该属性的元素。 -
语法 :
//标签名[not(@属性名)] -
适用场景:元素未定义目标属性(区别于"属性值为空")。
-
示例:
-
HTML 结构:
<input type="text" name="username" required><input type="text" name="email"><input type="button" value="提交"> -
定位需求:选择无
required属性的input。 -
XPath 表达式:
//input[not(@required)] -
结果:匹配
name="email"的文本框和"提交"按钮。
-
场景4:属性精准匹配(单属性/多属性)
-
语法规则 :直接通过
@属性名=属性值匹配,支持and连接多属性。 -
语法 :
//标签名[@属性名=属性值]或//标签名[@属性1=值1 and @属性2=值2] -
适用场景:已知元素明确属性及属性值,需精准定位单个/多个符合条件的元素。
-
示例:
-
单属性匹配:
//input[@id='kw'](定位 id 为 kw 的输入框) -
多属性组合:
//input[@name='password' and @pwd='123456'](name 为 password 且 pwd 为 123456 的输入框) -
存在属性即匹配:
//input[@value](所有含 value 属性的输入框) -
任意属性匹配:
//input[@*='SYS123456'](任意属性值为 SYS123456 的输入框)
-
场景5:部分属性值匹配(模糊匹配)
-
语法规则 :通过
starts-with(前缀)、ends-with(后缀)、contains(包含)函数实现。 -
语法:
-
前缀匹配:
//标签名[starts-with(@属性名, '前缀字符串')] -
后缀匹配:
//标签名[ends-with(@属性名, '后缀字符串')] -
包含匹配:
//标签名[contains(@属性名, '包含字符串')]
-
-
适用场景:属性值过长、动态变化(仅前缀/后缀固定)或仅知部分属性值。
-
示例:
-
前缀匹配:
//input[starts-with(@id,'ctrl')](id 以 ctrl 开头的 input) -
后缀匹配:
//input[ends-with(@id,'_userName')](id 以 _userName 结尾的 input) -
包含匹配:
//input[contains(@id,'userName')](id 含 userName 的 input)
-
第二部分:可见性筛选定位
场景1:元素可见(内联 style 隐藏)
-
语法规则 :排除内联
style中含display: none的元素(兼容有无空格)。 -
语法 :
//标签名[not(contains(@style, 'display: none')) and not(contains(@style, 'display:none'))] -
适用场景 :元素隐藏样式写在
style内联属性中(如style="display: none")。 -
示例:
-
HTML 结构:
<div class="content">可见1</div><div class="content" style="display: none;">隐藏1</div><div class="content" style="display:none;">隐藏2</div> -
定位需求:选择显示的
div。 -
XPath 表达式:
//div[contains(@class, 'content') and not(contains(@style, 'display: none')) and not(contains(@style, 'display:none'))] -
结果:仅匹配"可见1"对应的
div。
-
场景2:元素可见(CSS 类/外部样式隐藏)
-
语法规则:纯 XPath 无法解析 CSS 样式,需结合隐藏类名排除或自动化工具判断。
-
语法/方法:
-
已知隐藏类名:
//标签名[not(contains(@class, '隐藏类名'))] -
未知隐藏类名:使用 Selenium 的
is_displayed()方法(推荐) -
精准判断计算样式:通过 JavaScript 获取
getComputedStyle结果
-
-
适用场景 :元素隐藏样式来自 CSS 类(如
.hidden {display: none;})或外部样式表。 -
示例:
-
示例1(已知隐藏类名):
-
CSS 规则:
.hidden { display: none; } -
HTML 结构:
<div class="item">可见2</div><div class="item hidden">隐藏3</div> -
XPath 表达式:
//div[contains(@class, 'item') and not(contains(@class, 'hidden'))] -
结果:匹配"可见2"对应的
div。
-
-
示例2(Selenium 内置方法):
pythonfrom selenium import webdriver from selenium.webdriver.common.by import By driver = webdriver.Chrome() driver.get("目标页面URL") all_items = driver.find_elements(By.XPATH, "//div[contains(@class, 'item')]") visible_item = None for item in all_items: if item.is_displayed(): # 综合判断所有样式规则,确认元素可见 visible_item = item break if visible_item: print("可见元素文本:", visible_item.text) driver.quit() -
示例3(JS 计算样式):
python# 接示例2代码,替换筛选逻辑 visible_items = [] for item in all_items: display_style = driver.execute_script( "return window.getComputedStyle(arguments[0]).display;", item ) if display_style != 'none': visible_items.append(item)
-
第三部分:相对路径定位(按位置/关系筛选)
场景1:索引(下标)定位
-
语法规则:通过索引值指定元素位置,支持绝对位置、范围、特殊位置。
-
语法:
-
第 N 个元素:
//标签名[索引值] -
前 N 个元素:
//标签名[position()<N] -
最后一个元素:
//标签名[last()] -
父元素下第 N 个子元素:
//父标签/*[索引值]
-
-
适用场景:页面存在多个同类型元素,需按位置筛选。
-
示例:
-
第 2 个 input:
//input[2] -
前 2 个 input:
//input[position()<3] -
最后一个 input:
//input[last()] -
ul 下第 5 个子元素:
//ul/*[5] -
嵌套路径索引:
//*[@id='J_login_form']/*/*/input[2](表单下嵌套路径的第 2 个 input)
-
场景2:文本内容匹配
-
语法规则 :通过
text()函数匹配元素文本,支持完全匹配和部分包含。 -
语法:
-
完全匹配:
//标签名[text()='完整文本'] -
部分包含:
//标签名[contains(text(), '部分文本')]
-
-
适用场景:元素有明确文本内容,需按文本定位。
-
示例:
-
完全匹配:
//a[text()="退出"](文本为"退出"的链接) -
部分包含:
//a[contains(text(),"出")](文本含"出"字的链接) -
任意标签文本匹配:
//*[text()='Heading'](所有文本为 Heading 的元素)
-
场景3:轴定位(节点关系定位)
-
语法规则 :通过轴名称描述节点间关系(父子、兄弟、祖先等),语法为
//路径/轴名称::节点名称[条件]。 -
常用轴类型:
-
祖先节点:
ancestor(含父节点) -
父节点:
parent(直接父节点) -
子节点:
child(直接子节点) -
后代节点:
descendant(所有层级后代) -
之前兄弟节点:
preceding-sibling(同级前序节点) -
之后兄弟节点:
following-sibling(同级后序节点) -
之前所有节点:
preceding(当前节点前的所有节点) -
之后所有节点:
following(当前节点后的所有节点)
-
-
适用场景:复杂 DOM 结构,元素无明确属性/文本,需通过相邻节点关系定位。
-
示例:
-
定位父节点:
//input[@id='kw']/parent::span(id 为 kw 的 input 的直接父节点 span) -
定位之后的兄弟节点:
//li[text()='首页']/following-sibling::li[1]("首页"后的第一个同级 li) -
复杂路径轴定位:
//div//table/td/preceding::td/following-sibling::a[contains(text(),"课程")](div 下 table 的 td 之前的 td 同级中,含"课程"文本的链接)
-
三、XPath 定位验证方法(Chrome 浏览器)
1. Elements 面板验证
-
页面按 F12 打开开发者工具,切换至 Elements 面板;
-
按下 Ctrl+F 调出搜索框,输入 XPath 表达式;
-
搜索结果显示匹配数量,高亮对应元素,匹配唯一则定位正确。
2. Console 面板验证
-
切换到 Console 面板,输入语法:
$x("你的XPath表达式"); -
正确表达式返回匹配元素列表(如
[input#su.bg.s_btn]); -
无匹配元素返回空数组
[]; -
语法错误提示报错(如引号混用导致
Uncaught SyntaxError)。
四、关键注意事项
-
精准匹配 vs 模糊匹配:
-
!=和@属性名=属性值是精准匹配(属性值完全一致); -
contains/starts-with/ends-with是模糊匹配(匹配部分内容)。
-
-
无属性 vs 属性值为空:
-
not(@属性名)匹配"无该属性"的元素; -
@属性名=''匹配"有该属性但值为空"的元素。
-
-
可见性判断优先级:
-
自动化场景优先使用 Selenium 的
is_displayed()方法,可综合所有样式规则(包括父元素隐藏、CSS 类样式等),最可靠; -
纯解析场景(如 lxml)仅能通过 XPath 排除已知隐藏类/内联样式。
-
-
语法细节:
-
表达式中属性值建议用双引号,若值含双引号需替换为单引号;
-
XPath 索引从 1 开始(非 0 索引);
-
轴定位需用
::连接轴名称和节点名称,路径层级用/分隔。
-
-
动态元素适配:
-
动态变化的属性(如动态 id)优先使用部分属性匹配(
contains/starts-with)或文本匹配、轴定位; -
避免依赖易变的索引(如页面元素顺序调整会导致定位失效)。
-
五、速查表
| 定位需求 | 核心语法/方法 | 适用场景 |
|---|---|---|
| 属性值不等于XXX | //标签[@属性!='XXX'] |
精准排除特定属性值 |
| 属性不含XXX字符串 | //标签[not(contains(@属性, 'XXX'))] |
多值属性排除关键词 |
| 元素无XXX属性 | //标签[not(@XXX)] |
排除有该属性的元素 |
| 属性精准匹配(单/多属性) | //标签[@属性=值]///标签[@属性1=值1 and @属性2=值2] |
已知明确属性及值 |
| 部分属性值匹配(前缀/后缀/包含) | starts-with/ends-with/contains 函数 |
属性值过长或动态变化 |
| 可见元素(内联 style 隐藏) | //标签[not(contains(@style, 'display: none'))] |
内联样式隐藏的元素 |
| 可见元素(CSS 类/外部样式) | Selenium is_displayed()/排除隐藏类 |
样式来自 CSS 类/外部文件 |
| 按位置筛选元素 | //标签[索引值]/position()/last() |
同类型元素按位置选择 |
| 按文本筛选元素 | //标签[text()=文本]/contains(text(), 文本) |
元素有明确文本内容 |
| 按节点关系筛选元素 | 轴定位(parent/sibling等) |
复杂 DOM 结构,无明确属性文本 |
六、总结
XPath 定位的核心优势在于灵活性和通用性,可通过属性、位置、文本、节点关系等多维度组合实现精准定位。实际应用中,需根据元素特征(是否有明确属性、是否动态变化、样式来源等)选择合适的方法:
-
简单场景(元素有明确属性/文本):优先使用属性精准匹配、文本匹配;
-
复杂场景(多值属性、动态属性):使用部分属性匹配;
-
元素隐藏场景:自动化场景用
is_displayed(),纯解析场景排除已知隐藏类/内联样式; -
无明确属性文本场景:使用轴定位或索引定位(谨慎使用易变索引)。
定位后建议通过 Chrome 开发者工具验证表达式正确性,确保定位稳定可靠。