Selenium 自动化 —— 一篇文章彻底搞懂XPath

 更多关于Selenium的知识请访问“兰亭序咖啡”的专栏:专栏《Selenium 从入门到精通》


文章目录

前言

一、什么是xpath?

二、XPath 节点

三. 节点的关系

1. 父(Parent)

2. 子(Children)

3. 同胞(Sibling)

4. 先辈(Ancestor)

5. 后代(Descendant)

四. 路径表达式

五. 谓语(Predicates)

六. 轴(Axes)

七. XPath 示例

1. 绝对路径

2. 所有位置元素

3. 使用谓语

4. 通过@根据属性筛选

5. 通过属性值筛选

6. 元素计数器

7. 根据标签名筛选

8. 函数—包含 contains

9. 函数—字符串长度

10. 逻辑或

11. 轴

12. 根据符合条件的子节点选父节点

八. Selenium 中使用XPath

总结


前言

如何定位一个XML(尤其是HTML)中的一个节点?前文我们学习了Selenium的常用的几种选择器,相比其它几种比较简单的比如id选择器、name选择器等外,最强大也是我们使用最频繁的是xpath选择器

本文,我们就对xpath进行全面的学习。


一、什么是xpath?

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。(简单说就是在一个庞大复杂的XML中找到一个特定节点

而我们的 HTML 就是一种特殊的XML。所以 XPath 当然也可以用来对 HTML 元素和属性进行遍历。

XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。

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

这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

/usr/local/apache/log/

二、XPath 节点

在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及根节点。 

下面我们对每种节点介绍。

XPath 是对 XML 的操作,但是我们用得比较多的是 HTML,所以下面的代码都会以 HTML 来演示。

<html xmlns:example="http://www.example.com">
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
</head>
<body><!-- 测试 HTML -->
<h1 name="header">我的第一个标题</h1><p>我的第一个段落。</p></body>
</html>

对于上面的代码:

  1. <html> 就是根节点
  2. 每个标签都是一个元素,比如:<h1>我的第一个标题</h1>
  3.  <h1 name="header">中的name=“header”就是一个属性
  4. <p>我的第一个段落。</p> 中的“我的第一个段落。”就是文本
  5. <html xmlns:example="http://www.example.com">中的namespace就是命名空间
  6. <!-- 测试 HTML -->就是一个注释
  7. 处理指令一般不怎么常用,如果在Vue中<div v-if="show">会比较常见。

特别注意:节点和元素的区别:

  • 节点是很广泛的概念,包括了元素、属性、文本、命名空间、处理指令、注释以及根节点
  • 元素只是节点的一种,属性也是一种节点,元素通常是html标签对!
  • 后面会介绍 * 表示所有元素,而node()表示任意节点。

三. 节点的关系

人和人之间有关系,比如父子,兄弟等,节点同样有这些关系

这些关系可以帮我们定位一个节点。

1. 父(Parent)

每个元素都只有一个父节点。

  • coffe的父节点是list
  • list的父节点是drink

但是注意:coffe只有一个父节点,drink不是coffe的父节点。

<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

2. 子(Children)

每个节点都有零个、一个或多个子节点。

  • food的子节点是drink
  • list的子节点有3个,分别是coffe、tea和milk
  • coffe没有子节点

特别注意:coffe不是food和drink的子节点。

<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

3. 同胞(Sibling)

拥有相同父节点的节点。

  • coffe、tea、milk他们的父节点都是list,所以他们是同胞节点。
  • drink只有list一个子节点,所以list没有同胞节点。
<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

4. 先辈(Ancestor)

某节点的父、父的父……

  • coffe的先辈节点有list、drink和food
<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

5. 后代(Descendant)

某个节点的子,子的子,等等。

  • food的后代节点有drink、list,还有coffe、tea、milk
<div class="food"><div class="drink"><ol class="list"><li item="coffe">Coffee</li><li item="tea">Tea</li><li item="milk">Milk</li></ol></div>
</div>

四. 路径表达式

XPath 使用路径表达式在 XML 文档中选取节点

最常用的路径表达式
路径表达式作用示例
nodename选取此节点的所有子节点。

input:选择所有<input>节点的所有子节点。

/

从根节点选取。

也就是绝对路径。

/html:选择根节点,网页的根节点都是<html>节点。

//

从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。

也就是相对路径。

//input:选中所有<input>节点。
.选取当前节点。
..选取当前节点的父节点。
@选取属性。//@id:选中所有有id属性的节点。        
*匹配任何元素

//*:任意元素的节点

//@*:属性为任意值的节点,换句话说就是有属性的节点,比如<html>和<body>这种节点不会被选中。

node()

匹配任何类型的节点

(特别区别*,元素是特殊的节点,属性也是节点)

//node():选中任意节点
|使用“|”运算符,可以选取若干个路径。也就是或//input | //ul:选中所有的<input>或者<ul>节点

是不是和 Linux 的路径语法很类似!区别在于一个是选择目录,一个是选择节点

//div/span 和 //div//span 有什么区别?(非常重要)

  • //div/span:选择div元素的子节点中的span
  • //div//span:选择div元素的后代节点中的span

比如对于下面的html,使用“//div/span”只能选中一个span,但是使用"//div//span"可以选中两个span!

<div><span>Hello<span><ul><span>World</span></ul>
<div>

节点和元素的区别?(特别重要)

以 * 和 node()为例:

  • //*:选中了5个元素:(5) [html, head, title, body, div.box]
  • //node():选中了8个节点:(8) [<!DOCTYPE html>, html, head, title, text, body, div.box, text]
<!DOCTYPE html>
<html><head><title>预定</title></head><body><div class="box">Hello</div></body>
</html>

五. 谓语(Predicates)

谓语用来查找某个特定的节点或者包含某个指定的值的节点。谓语被嵌在方括号中。

是不是不太好理解。

其实,我们学习中文或者英文语法的时候,也接触过 主+谓+宾语 的结构,这和XPath的谓语很类似。

谓语(Predicate) 是对主语动作状态或特征的陈述或说明,指出"做什么(what to do)" , "是什么(what is this)"。

谓语动词的位置一般在主语之后, 经常用动词和形容词搭配来充当谓语动词。

比如:

  • 选择div的第二个子节点
  • 选择有id属性的div节点
  • 数值大于35的节点
  • ……

有了这些谓词,我们可以更精确的定位到特定的节点

六. 轴(Axes)

前面介绍了节点之间的关系,比如父子关系、兄弟关系等。

Xpath 使用轴 定义了节点与当前节点之间的关系,相当于节点的运动路径。每一个轴都有一个基本节点类型。

 在 XPath 中,我们使用轴(如 child、parent、attribute 等)来定位节点

用关系来定位节点!

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

语法规则:

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

下面列举一些实例来说明!!!

例子结果
//div//child::input

选取所有属于div节点的子元素的 input 节点。

不过直接用简单的写法就行了://div//input

//input//attribute::id

选取所有input节点的 id 属性。(属性也是一种节点!

比如<input id="username" name="uname"> 

//ul//child::*

选取当前节点的所有子元素。(因为使用了//相对路径, 所以是所有后代节点

如果 //ul/child::*  因为是 / 绝度路径, 所以选中所有子节点

//input//attribute::*

选取input节点的所有属性。

<input id="username" name="uname" class="big">

//a//child::text()

选取a节点的所有文本子节点。

简单写法://a/text()

比如:<a>测试</a>  <a>Hello</a>

//a//child::node()

选取a节点的所有子节点。(注意是节点,所以也包括元素,而且使用的//相对,所以所有后代的节点)

//ul//descendant::input选取ul节点的所有 input 后代节点。
//input//ancestor::li选择input节点的所有 li 先辈节点。
ancestor-or-self::book选取当前节点的所有 book 先辈以及当前节点(如果此节点是 book 节点)
//ul/child::*/child::input

选取ul节点的所有 input 孙节点

相当于://ul/*/inut

所有的child::XXX 都可以直接写XXX

比如://a//child::text()   --> //a//text()

           //div//child::input --> //div//input

七. XPath 示例

1. 绝对路径

/html/body/div[2]/top-menu/header/div/div[1]/h1/a/img

2. 所有位置元素

//div //任意div节点
//div//img /*div的所有img后代*/

3. 使用谓语

//ul//li[1] /*选择第一个*/
//ul//li[position() = 1] /*多种写法*///ul//li[last()] /*选择最后一个*/

4. 通过@根据属性筛选

//@jscontent	/*所有带jscontent属性的节点*/
//span[@jscontent] /*所有带jscontent属性的span节点*///span[@*] /*所有带任意属性的span节点*///div[not(@*)] /*没有任何属性的div节点*/
//div[not(@id)] /*没有id属性的div节点*/

5. 通过属性值筛选

//span[@class='currency']
//span[normalize-space(@class)='currency']  /*去掉前后空格后再比较*/

6. 元素计数器

//ul[count(li)=5] /*有5个li的ul*///*[count(*)=3] /*有3个子元素的任意节点*/

7. 根据标签名筛选

//*[name()='span']	/*等同于//span*
//span//*[starts-with(name(), 'scri')]  /*标签名以scri开头的标签*/
//*[contains(name(), 'pt')] /*标签名包含pt的标签*/

8. 函数—包含 contains

//div[contains(@class, 'rowFlightItem')]

如果使用全匹配是获取不到的//div[@class, 'tripselector_inbound'] 除非//div[@class, 'tripselector_inbound ng-star-inserted']

但是要特别注意,模糊匹配可能会匹配到不期望的对象

//flight//div[contains(@class, 'row')]

9. 函数—字符串长度

//*[string-length(name()) = 3] /*标签名字为3个字符串的节点,比如div,img*/

10. 逻辑或

//ul | //button /*ul标签或button*/

11. 轴

//div//child::ul  /*选择子节点是ul的div*///div/ul /*简洁写法*/

注意child和descendant的区别,一个儿子,一个是后代。儿子也是后代

后代节点轴

//div//descendant::*  /*选择div下面的所有元素*///div//*

后面的兄弟节点

//ul//li/following-sibling::*  /*ul下第一个后面的子节点!*/

12. 根据符合条件的子节点选父节点

//table[.//th[@scope="colgroup" and normalize-space(.)="成人"]]
.//tr[contains(@class, 'taxesOrFees-tr') and (.//td)]  /*子节点有td的tr*/
<table class="table"><caption class="">Departure flight - adult prices resume table</caption><tbody><tr class="colgroup_title"><th colspan="2" scope="colgroup">成人</th></tr>

八. Selenium 中使用XPath

使用非常简单,就是By.xpath()方法即可:

WebElement element = driver.findElement(By.xpath("//input[@id='username']"));


总结

以上就是今天要讲的内容,本文系统全面的介绍了Xpath,从什么是Xpath讲起,到Xpath的基本概念,最后到语法和实战!相信这会让你在使用 Selenium 时如虎添翼!关注兰亭序咖啡的博客,我们一起对 Selenium 学习和探讨!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/11048.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣:48. 旋转图像(Java)

目录 题目描述&#xff1a;输入&#xff1a;输出&#xff1a;代码实现&#xff1a; 题目描述&#xff1a; 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使…

LangChain:模型 I/O 封装使用解析和感触

目录 模型 API&#xff1a;LLM vs. ChatModel OpenAI 模型封装 多轮对话 Session 封装 换个国产模型 模型的输入与输出 Prompt 模板封装 PromptTemplate ChatPromptTemplate MessagesPlaceholder 从文件加载 Prompt 模板 TXT模板 Yaml模板 Json模板 输出封装 Out…

目标检测标注工具Labelimg安装与使用

目录 一、安装Labelimg与打开 二、使用 1、基本功能介绍 2、快捷键 3、状态栏的工具 三、附录 1、YOLO模式创建标签的样式 2、create ML模式创建标签的样式 3、PascalVOC模式创建标签的样式 一、安装Labelimg与打开 labelimg是一款开源的数据标注工具&#xff0c;可以…

51基于单片机的温室大棚系统设计

设计摘要&#xff1a; 本设计旨在基于51单片机和蓝牙技术&#xff0c;实现一个功能完善的温室大棚系统。该系统具备以下主要功能&#xff1a;首先&#xff0c;通过连接的显示屏能够实时地显示当前的温度和湿度信息&#xff0c;方便用户了解温室内的环境变化。其次&#xff0c;…

ctfshow web271--web273

web271 laravel5.7反序列化漏洞 define(LARAVEL_START, microtime(true));/* |-------------------------------------------------------------------------- | Register The Auto Loader |-------------------------------------------------------------------------- | |…

凸优化理论学习二|凸函数及其相关概念

系列文章目录 凸优化理论学习一|最优化及凸集的基本概念 文章目录 系列文章目录一、凸函数&#xff08;一&#xff09;凸集&#xff08;二&#xff09;凸函数的定义及举例&#xff08;三&#xff09;凸函数的证明1、将凸函数限制在一条直线上2、判断函数是否为凸函数的一阶条件…

贝叶斯分类器详解

1 概率论知识 1.1 先验概率 先验概率是基于背景常识或者历史数据的统计得出的预判概率&#xff0c;一般只包含一个变量&#xff0c;例如P(A)&#xff0c;P(B)。 1.2 联合概率 联合概率指的是事件同时发生的概率&#xff0c;例如现在A,B两个事件同时发生的概率&#xff0c;记…

华为交换机配置导出备份python脚本

一、脚本编写思路 &#xff08;一&#xff09;针对设备型号 主要针对华为&#xff08;Huawei&#xff09;和华三&#xff08;H3C&#xff09;交换机设备的配置备份 &#xff08;二&#xff09;导出前预处理 1.在配置导出前&#xff0c;自动打开crt软件或者MobaXterm软件&am…

掌握MySQL执行计划分析【Explain】

前言 MySQL是一个强大的关系型数据库管理系统&#xff0c;其高效执行SQL查询的能力是其核心价值之一。然而&#xff0c;当查询变得复杂或者数据量急剧增长时&#xff0c;SQL查询的性能问题往往成为我们不得不面对的挑战。为了深入了解查询的执行过程并找到性能瓶颈&#xff0c…

Modbus通讯协议初学

目录 Modbus通讯协议初学什么是Modbus?Modbus用来做什么?4个种类的寄存器协议速记功能码Modbus 报文帧示例解读 Modbus通讯协议初学 什么是Modbus? 顾名思义,它是一个bus,即总线协议。比如串口协议、IIC协议、SPI都是通讯协议。你接触到这种协议,相信你所处的行业是工业方…

如何自定义Linux命令

说明&#xff1a;本文介绍如何将自己常用的命令设置为自定义的命令&#xff0c;以下操作在阿里云服务器CentOS上进行。 修改配置文件 修改配置文件前&#xff0c;先敲下面的命令查看当前系统配置的shell版本 echo $SHELL或者 echo $0区别在于&#xff0c;$SHELL查看的是系统…

落雪音乐 超好用的桌面端音乐播放器

之前一直都是充某Q音乐的会员&#xff0c;突然不想氪金了&#xff0c;终于找到一个开源的音乐播放器&#xff0c;在此先给落雪无痕大佬跪了 太爱了 简直白嫖怪的福音 话不多说&#xff0c;直接上操作&#xff1a;解压密码&#xff1a;www.1234f.com下载地址&#xff1a;极速云…

图片批量管理迈入智能新时代:一键输入关键词,自动生成并保存惊艳图片,轻松开启创意之旅!

在数字化时代&#xff0c;图片已成为我们表达创意、记录生活、传递信息的重要工具。然而&#xff0c;随着图片数量的不断增加&#xff0c;如何高效、便捷地管理这些图片&#xff0c;却成为了一个令人头疼的问题。 第一步&#xff0c;进入首助编辑高手主页面&#xff0c;在上方…

视频封面一键提取:从指定时长中轻松获取您想要的帧图片

在数字媒体时代&#xff0c;视频已成为人们获取信息、娱乐和沟通的主要形式之一。而一个好的视频封面&#xff0c;往往能够吸引观众的眼球&#xff0c;增加视频的点击率和观看量。然而&#xff0c;对于很多视频创作者和编辑者来说&#xff0c;如何从视频中快速、准确地提取出合…

Git知识点总结

目录 1、版本控制 1.1什么是版本控制 1.2常见的版本控制工具 1.3版本控制分类 2、集中版本控制 SVN 3、分布式版本控制 Git 2、Git与SVN的主要区别 3、软件下载 安装&#xff1a;无脑下一步即可&#xff01;安装完毕就可以使用了&#xff01; 4、启动Git 4.1常用的Li…

Shell编程之循环语句之for

一.for循环语句 读取不同的变量值&#xff0c;用来逐个执行同一组命令 for 变量名 in 取值列表 do命令序列 done 示例&#xff1a; 1.计算从1到100所有整数的和 2.提示用户输入一个小于100的整数&#xff0c;并计算从1到该数之间所有整数的和 3.求从1到100所有整数的偶数和…

【牛客】SQL206 获取每个部门中当前员工薪水最高的相关信息

1、描述 有一个员工表dept_emp简况如下&#xff1a; 有一个薪水表salaries简况如下&#xff1a; 获取每个部门中当前员工薪水最高的相关信息&#xff0c;给出dept_no, emp_no以及其对应的salary&#xff0c;按照部门编号dept_no升序排列&#xff0c;以上例子输出如下: 2、题目…

SBM模型、超效率SBM模型代码及案例数据(补充操作视频)

01、数据简介 SBM&#xff08;Slack-Based Measure&#xff09;模型是一种数据包络分析&#xff08;Data Envelopment Analysis, DEA&#xff09;的方法&#xff0c;用于评估决策单元&#xff08;Decision Making Units, DMUs&#xff09;的效率。而超效率SBM模型是对SBM模型的…

轮转数组 与 消失的数字

轮转数组 思路一 创建一个新内存空间&#xff0c;将需轮转的数依次放入&#xff0c;之后在把其它数放入 代码&#xff1a; void rotate(int* nums, int numsSize, int k) {k k % numsSize;// 确定有效的旋转次数if(k 0)return;int* newnums (int*)malloc(sizeof(int) * nu…

企业OA办公系统开发笔记:1、搭建后端环境

文章目录 企业办公系统&#xff1a;搭建环境一、项目介绍1、介绍2、技术栈3、项目模块4、数据库 二、搭建环境1、搭建后端1.1、搭建父工程clfwzx-oa-parent1.2、搭建工具类父模块common1.3、搭建工具类common的子模块1.4、搭建实体类模块model和项目模块service-oa 2、配置依赖…