XPath从入门到精通:基础和高级用法完整指南,附美团APP匹配示例

XPath 通常用来进行网站、XML (APP )和数据挖掘,通过元素和属性的方式来获取指定的节点,然后抓取需要的信息。

学习 XPath 语法之前,首先了解一些概念。

概念介绍

节点之间的关系

在这里插入图片描述

以上面的 HTML 节点树为例,节点之间包含了下列的关系:

  1. 父节点 (Parent): HTML 是 DIV 和 P 节点的父节点;
  2. 子节点 (Child):DIV 和 P 是 HTML 的子节点;
  3. 兄弟节点 (Sibling):拥有同样的一个父节点,DIV 和 P 就是兄弟节点。类似的 span、img 和 i 也是兄弟节点。
  4. 祖先节点 (Ancestor):html 是 span 的祖先节点,隔开一级;
  5. 后代节点 (Descendant):span 是 HTML 的后代节点,隔开一级。

除了了解这些概念,parent、sibling 等关键词也非常关键,在匹配复杂的结构时常常用到。

绝对和相对路径

xpath 中绝对路径使用 / 开始,比如:/html/body/div[1]/a/img,绝对路径较长,其中可能包含变化的部分,不建议单独使用绝对路径来选择元素,最好配合其它语法。
比如下面的情况单独使用绝对路径进行定位就会出错:

// 本意是匹配第三个div下的span,但因为第一个div因为是动态显隐的,导致匹配第而个div匹配到之前的第三个了/html/body/div[2]/span

相对路径以 // 开始,比如 //*[@class],表示只要包含 class 属性的元素均可匹配,无论从哪一个节点开始。

下面是一些常见选择节点示例:

表达式说明举例
/下一个节点,或者根节点开始/html/body/div
//从任意节点开始//img
.选取当前节点//a/.
当前节点的父节点//a/…
@选取包含某属性的元素//div[@class]或//@class
*表示任意元素或者任意属性//*[@class]

除此之外,通过谷歌浏览器-元素上审查元素-复制 xpath,可以直接获取绝对路径和相对路径。

在这里插入图片描述

但复制下来的代码,通常还需要进行一些修改,才能具备通用性。

基础语法

定位需要的信息通常通过元素、属性名、属性值以及三者结合等方式进行。

下面来分别看一下,也这段 html 代码为例:

<div id="app"><p class="title">喜欢的动物</p><ul><li class="cat"></li><li class="dog"></li><li id="panda">熊猫</li></ul><p class="title">喜欢的电影</p><ul><li>阿甘正传</li><li>霸王别姬</li><li>阿凡达</li></ul><p>其它不需要信息</p>
</div>

1. 通过元素名定位

示例:

1.1 //div/p
在这里插入图片描述

定位所有 div 下的 p 子元素,可以是任何 div,只要这个 div 的子节点包含 p 就可以匹配

1.2 //ul
在这里插入图片描述

会定位从任何节点开始的 ul 元素

1.3 /html/body/div/p
在这里插入图片描述

使用绝对路径定位元素,必须从 /html 开始,否则最好使用 // 相对路径开始

2. 通过属性名定位

通过元素是否包含某个属性来进行定位,属性名需要使用 @ 开始,同时放在 []

2.1 //*[@class]
在这里插入图片描述

定位包含 class 属性的元素

2.2 //@class
在这里插入图片描述

这种语法定位到的是属性里面的具体值 title,而不是元素,所有没有元素没选中

3. 通过属性值定位

示例:
//li[@class="cat"]
在这里插入图片描述

定位包含 class 属性,值为 cat 的 li 属性元素

4. 使用逻辑运算符定位

常用逻辑运算符包括:andornot 三种

示例:

4.1 //li[@class and @class="cat"]
在这里插入图片描述

选中包含 class 属性,并且属性值为 cat 的 li 元素对象。

4.2 //li[@class or @id]
![[CleanShot 2024-02-01 at 10.00.21@2x 1.png]]
选中包含 class 或者 id 属性的 li 元素对象。

4.3 //li[not(@class)]
![[CleanShot 2024-02-01 at 10.01.52@2x.png]]

选中不包含 class 属性的 li 元素对象。

5. 使用谓语定位

5.1 //li[1]
![[CleanShot 2024-02-01 at 10.04.02@2x.png]]

定位任意元素下的第一个 li。

注意
xpath 中索引从 1 开始。

5.2 (//li)[1]
![[CleanShot 2024-02-01 at 10.04.56@2x.png]]

两者区别如下:
//li[1] 任意元素下第一个li,也就是说这个 li 在任意的 ul 下是第一个就会被选中
(//li)[1] 将所有的 li 选出来的结果数组中取第一个,这两者是完全不同的含义

6. 使用文本定位

使用元素中文本的内容进行定位。

示例:

6.1 //li[text()="猫"]
![[CleanShot 2024-02-01 at 10.12.46@2x.png]]

选中文本内容为 的 li 元素对象。

6.2 //*[contains(text(),"喜欢")]
![[CleanShot 2024-02-01 at 10.14.01@2x.png]]

选中任意元素文本中包含 喜欢 两个字的元素,其中 * 表示所有元素是通配符,contains() 表示包含函数。
类似的有:starts-withends-with 函数,表示以什么字符开始和字符结尾的文本。

节点选择器

除了相对和绝对选择之外,下面这些选择器在处理较复杂的匹配场景可以发挥关键作用。

  • parent:::选中父级节点,/.. 也是选中父级,但是通常 parent:: 用于写在 [] 里面作为条件来判断
  • child:::选中子级节点,/ 也是选中子级,通常也是作为条件来使用
  • preceding-sibling:::选中同一层级的前面所有兄弟节点
  • following-sibling:::选中同一层级的后面所有兄弟节点
  • ancestor:::选中祖先节点,包括父级以及更上层的节点
  • descendant:::选中当前节点下面的所有节点,包括子级

举例:

//*[ancestor::div]

![[CleanShot 2024-02-01 at 10.37.40@2x.png]]

选中所有元素中,上级是 div 的元素,其实也就是选中了所有元素,来看看这个

//ancestor::div
![[CleanShot 2024-02-01 at 10.38.55@2x.png]]

只选中了一个元素。

两者的区别如下:
//*[ancestor::div] 选中的 * 表示所有元素,这些元素条件是 [ancestor::div] 父级及以上有 div。
//ancestor::div 选中的是作为别人父级及以上的 div,也就是选中的是 div,这个 div 的是别人的父级或者爷级等
两者是完全不同的概念

美团 APP 匹配示例

看了半天 HTML,我们来了解一下 APP 中的 XML,通常匹配 APP 比网页复杂太多,基本就那几个元素,而且属性名基本都一样,所以常用的手段还是使用各种条件来进行限制匹配,下面来看一个例子。

 <android.view.View index="5" class="android.view.View" text="" checked="false" clickable="true"><android.widget.TextView index="1" class="android.widget.TextView" text="象山酥院(湛江印象汇店)" checked="false"/><android.widget.TextView index="2" class="android.widget.TextView" text="" checked="false" clickable="true"/><android.view.View index="3" class="android.view.View" text="" checked="false"><android.widget.TextView index="0" class="android.widget.TextView" text="5.0" checked="false" /></android.view.View><android.widget.TextView index="4" class="android.widget.TextView" text="周销量 872" checked="false" /></android.view.View><android.view.View index="5" class="android.view.View" text="" checked="false" clickable="true"><android.widget.TextView index="1" class="android.widget.TextView" text="蜜雪冰城" checked="false"/><android.widget.TextView index="2" class="android.widget.TextView" text="" checked="false" clickable="true"/><android.view.View index="3" class="android.view.View" text="" checked="false"><android.widget.TextView index="0" class="android.widget.TextView" text="5.0" checked="false"/></android.view.View><android.widget.TextView index="4" class="android.widget.TextView" text="周销量 2322" checked="false"/></android.view.View>

上面代码为美团的城市列表页面的 UI XML 代码,其中每个元素都包含大量相同的属性和属性值,关键在于整个页面,任何地方基本就是 android.view.Viewandroid.widget.TextView ,像匹配 HTML 那样元素显然行不通。

示例:获取两个商品的评分
//*[@text and ancestor::*/following-sibling::*[contains(@text, '周销量')]]
规则解释:获取任何包含 text 属性的元素,它的父级的的兄弟元素必须是一个 text 值中包含 "周销量"的元素。
我这里没有使用 [1][2][3] 来定位,是因为不同商品的属性很多时候不一样。

通常还是根据想要的元素的位置,以及相邻元素的特征来定位,首先找到独特的文本,比如上面的周销量是固定会出现的,还有 ¥ 符号也可以,这些都是位置和文本值固定的,找到这个的位置,再去定位需要的元素的位置。

工具推荐

  1. 谷歌浏览器-审查元素- ctrl + f,可以直接输入 xpath 语句
  2. 谷歌浏览器-selectorshub 插件,文中使用的是这个插件在这里插入图片描述

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

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

相关文章

Linux——安装MySQL

1、安装mysql8.0.35 1.1、安装步骤 1.更新包列表&#xff0c;首先&#xff0c;确保您的系统已更新到最新状态。运行以下命令来更新包列表和安装最新的软件包&#xff1a; sudo apt update sudo apt upgrade2.安装MySQL服务器&#xff1a;运行以下命令来安装MySQL服务器&…

win11安装wsl作为linux子系统并当作服务器

wsl安装 打开控制面板&#xff0c;找到启用或关闭windows功能 开启windows虚拟机监控平台和适用于Linux的Windows子系统&#xff0c;重启电脑。 打开microsoft store搜索ubuntu&#xff0c;找到合适的版本下载安装 输入wsl -l如下所示&#xff0c;即为安装成功。 安装过程比较…

Golang语言异常机制解析:错误策略与优雅处理

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站https://www.captainbed.cn/kitie。 前言 作为开发者来说&#xff0c;我们没办法保证程序在运行过程中永远不会出现异常&#xff0c;对于异常…

Maven:Dmaven.multiModuleProjectDirectory system propery is not set.

eclipse中使用maven插件的时候&#xff0c;运行run as maven build的时候报错 -Dmaven.multiModuleProjectDirectory system propery is not set. Check $M2_HOME environment variable and mvn script match. 直接的解决方法&#xff1a;使用低版本的maven 可以设一个环境变量…

分布式搜索引擎_学习笔记_2

分布式搜索引擎_学习笔记_2 在昨天的学习中&#xff0c;我们已经导入了大量数据到elasticsearch中&#xff0c;实现了elasticsearch的数据存储功能。但elasticsearch最擅长的还是搜索和数据分析。 所以今天&#xff0c;我们研究下elasticsearch的数据搜索功能。我们会分别使用…

Vue.js 中子组件向父组件传值的方法

Vue.js 是一款流行的 JavaScript 前端框架&#xff0c;它提供了一套完整的工具和 API&#xff0c;使得开发者可以更加高效地构建交互式的 Web 应用程序。其中&#xff0c;组件化是 Vue.js 的一个核心概念&#xff0c;通过组件化可以将一个复杂的应用程序拆分成多个独立的部分&a…

系统架构设计师考试大纲2023

一、 考试方式&#xff08;机考&#xff09; 考试采取科目连考、 分批次考试的方式&#xff0c; 连考的第一个科目作答结束交卷完成后自动进 入第二个科目&#xff0c; 第一个科目节余的时长可为第二个科目使用。 高级资格&#xff1a; 综合知识科目考试时长 150 分钟&#xff…

基于ecal的foxglove studio可视化工具的使用

ecal通讯在自动驾驶和机器人中的应用越来越多,在调试测试过程中,可以使用ecal monitor,ecal recoder和ecal player等工具,对ecal 消息进行监测录制回播。但是,有时候需要对消息进行可视化查看,比如雷达点云信息,相机图像等,可以使用foxglove studio可视化工具。 Foxg…

CSRF靶场练习

简述&#xff1a;CSRF漏洞实际很少&#xff1b;条件限制很多&#xff1b;局限性很大&#xff1b;实验仅供参考&#xff0c;熟悉csrf概念和攻击原理即可 Pikachu靶场 CSRF GET 登录用户vince的账户可以看到用户的相关信息&#xff1b; 点击修改个人信息&#xff0c;发现数据包…

轻量式RPC调用日志链路设计方案

导语: 调用链跟踪系统,又称为tracing&#xff0c;是微服务设计架构中&#xff0c;从系统层面对整体的monitoring和profiling的一种技术手 背景说明 由于我们的项目是微服务方向&#xff0c;中后台服务调用链路过深&#xff0c;追踪路径过长&#xff0c;其中某个服务报错或者异…

【Redis】实现购物秒杀及分布式锁

Redis实现购物秒杀及分布式锁 全局唯一ID Redis自增ID策略 ID构造是:时间戳 + 计数器 每天一个key,方便统计订单量 业务实现 获取指定时间的秒数 LocalDateTime timeBegin = LocalDateTime.of(2024, 1, 1, 0, 0, 0); long second = timeBegin.toEpochSecond(ZoneOffset…

Java面试题宝典(万字长文)

Java 基础 1. JDK 和 JRE 有什么区别&#xff1f; JRE是Java运行环境&#xff0c;即&#xff08;Java Runtime Environment&#xff09;&#xff0c;也就是Java平台。所有的Java程序都要在JRE下才能运行。 JDK是开发工具包&#xff0c;即&#xff08;Java Development Kit&am…

【Docker与微服务】基础篇

1 Docker简介 1.1 docker是什么 1.1.1 问题&#xff1a;为什么会有docker出现&#xff1f; 假定您在开发一个项目&#xff0c;您使用的是一台笔记本电脑而且您的开发环境具有特定的配置。其他开发人员身处的环境配置也各有不同。您正在开发的应用依赖于您当前的配置且还要依…

android 自定义下拉框

一、 简介&#xff1a; 原生Android 提供的spinner下拉框不怎么方便&#xff0c;样式有点丑。修改起来麻烦&#xff0c;于是就自己动手写了一下拉列表。 实现原理使用的是&#xff0c;popwindow弹框&#xff0c;可实现宽高自定义&#xff0c;下拉列表使用listview. 二、pop弹框…

大模型基础架构的变革:剖析Transformer的挑战者(中)

上一篇文章中&#xff0c;我们介绍了RetNet、RWKV、Mamba等有可能会替代Transformer的模型架构&#xff0c;这一篇文章我们将要介绍另外三个有可能会替代Transformer的模型架构&#xff0c;它们分别是UniRepLKNet、StripedHyena、PanGu-π&#xff0c;想了解之前的内容&#xf…

vue项目改造服务端渲染

vue项目改造服务端渲染 概述 【定义】 服务器渲染的Vue应用程序被认为是"同构"或"通用"&#xff0c;因为应用程序的大部分代码都可以在服务器和客户端上运行 【优点】 与传统SPA相比&#xff0c;服务器端渲染(SSR)的优势主要在于&#xff1a; 1、更好的…

二叉树-堆应用(1)

目录 堆排序 整体思路 代码实现 Q1建大堆/小堆 Q2数据个数和下标 TopK问题 整体思路 代码实现 Q1造数据CreateData Q2建大堆/小堆 建堆的两种方法这里会用到前面的向上/向下调整/交换函数。向上调整&向下调整算法-CSDN博客 堆排序 整体思路 建堆&#xff08;直…

Qt 5.9.4 转 Qt 6.6.1 遇到的问题总结(三)

1.QSet: toList 中的toList 函数已不存在&#xff0c;遇到xx->toList改成直接用&#xff0c;如下&#xff1a; 2.开源QWT 图形库中QwtDial中的 setPenWidth 变成 setPenWidthF函数。 3.QDateTime 中无setTime_t 改为了setSecsSinceEpoch函数。 4.QRegExp 类已不存在 可以用Q…

【定位·HTML】

定位布局可以分为以下四种&#xff1a; 静态定位&#xff08;inherit&#xff09; 相对定位&#xff08;relative&#xff09; 绝对定位&#xff08;absolute&#xff09; 固定定位&#xff08;fixed&#xff09; 一般的标签元素不加任何定位属性时&#xff0c;默认都属于静态…

百川终入海 ,一站式海量数据迁移工具 X2Doris 正式发布

在大数据分析领域&#xff0c;Apache Doris 作为广受认可的开源实时数据仓库&#xff0c;已经在越来越多行业用户的真实业务场景中得到广泛应用&#xff0c;成为许多企业数据分析基础设施的重要基座。尤其在过去一年多的时间里&#xff0c;越来越多企业选择基于 Apache Doris 进…