XPATH 使用备忘

news2024/9/21 20:47:06

xpath的基础使用 

一.xpath简介

XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航。
  • XPath 使用路径表达式在 XML 文档中进行导航
  • XPath 包含一个标准函数库
  • XPath 是 XSLT 中的主要元素
  • XPath 是一个 W3C 标准

`节点

  在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。

xpath比美丽汤更通用,在各语言的xpath中都可以使用,scrapy框架也是内置了一个xpath,而美丽汤只能在python中使用.

二、xpath语法

  1.选取节点

表达式

描述

实例

nodename

选取nodename节点的所有子节点

xpath('//div')

选取了div节点的所有子节点

/

从根节点选取

xpath('/div')

从根节点上选取div节点

//

选取所有的当前节点,不考虑他们的位置

xpath('//div')

选取所有的div节点

.

选取当前节点

xpath('./div')

选取当前节点下的div节点

..

选取当前节点的父节点

xpath('..')

回到上一个节点

@

选取属性

xpath('//@calss')

选取所有的class属性

  2、谓语

     谓语被嵌在方括号内,用来查找某个特定的节点或包含某个特定的值的节点,因为所有xpath解析返回值为一个列表

    xpath的索引从1开始   

表达式

结果

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节点

  3、通配符  

    Xpath通过通配符来选取未知的XML元素

表达式

结果

xpath('/div/*')

选取div下的所有子节点

xpath('/div[@*]')

选取所有带属性的div节点

    4、逻辑运算

    使用“|”或者and运算符可以选取多个路径

    

表达式

结果

xpath('//div|//table')

选取所有的div和table节点

xpath(//a[@href="" and @class="du"])

选取同时具href="",class='du'的a标签

  5、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-sibling::*')

选取当前节点之后的兄弟节点

parent

xpath('./parent::*')

选取当前节点的父节点

preceding

xpath('./preceding::*')

选取文档中当前节点开始标签前的

  

preceding-sibling

xpath('./preceding-sibling::*')

选取当前节点之前的兄弟节点

self

xpath('./self::*')

选取当前节点

   6、功能函数(模糊匹配) 

      使用功能函数能够更好的进行模糊搜索

函数

用法

解释

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节点

    7.取属性和文本

@//div[@class="tang"]//li[2]/a/@href取标签的的href属性值
text()//div[@class="song"]/p[1]/text()取p[1]的所有属性值
text()//div[@class="tang"]//text()取div标签的所有文本值,包括子标签的

    

     8.通过text()确定标签

选取文本是'>'的a标签
xpath('//a[text()=">"]')

    9.string(.)提取所有文本  

html3 = '''
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <div id="test3">
        我左青龙,
        <span id="tiger">
            右白虎,
            <ul>上朱雀,
                <li>下玄武。</li>
            </ul>
            老牛在当中,
        </span>
        龙头在胸口。
    </div>
</body>
</html>
'''
#如果使用一般的办法,就会出现获取到的数据不完整的情况
selector = lxml.html.fromstring(html3)
# content_1 = selector.xpath('//div[@id="test3"]/text()')
# for each in content_1:
#     print(each)

# 使用string(.)就可以把数据获取完整
data = selector.xpath('//div[@id="test3"]')[0]
info = data.xpath('string(.)')
print(info)


#####或者使用这种情况
t=etree.HTML(html3)
res = t.xpath("//div[@id='test3']//text()")
print(res)

   10.text_content()

最开始对html文本使用 etree.HTML(html)解析,得到Element对象。

from lxml import etree

str="""

<div>
<a href="xxxx">123</a>
<a href="xxxx">45</a>
<div>

"""

root= etree.HTML(str)

root.xpath("//div//text()")

#发现并没有直接获取12345文本方法

#后来网上调查发现lxml操作html有一个专门的html模块html,然后找到了解决该问题的关键方法text_content(),这个方法在上面的写法中是不存在的于是解决方案如下。

from lxml import html

root = html.fromstring('''<div><a href="xxxx">123</a><a href="xxxx">45</a><div>''')

 

 root.xpath("//div").text_content()

三.使用流程

xpath数据解析流程:
  1.pip install lxml
  2.导包:from lxml import etree 
  3.实例化一个etree对象(将页面数据加载到该对象)

    •  本地文件:tree = etree.parse(文件名)          tree.xpath("xpath表达式")  ===>本地文件指的是包打开的网页另存为到本地的文件
    •   网络数据:tree = etree.HTML(网页内容字符串)       tree.xpath("xpath表达式")    

  4.调用etree中的xpath函数结合着xpath表达式进行数据解析操作

    补充:

      # 使用lxml.etree.parse()解析html文件,该方法默认使用的是“XML”解析器,所以如果碰到不规范的html文件时就会解析错误

      # lxml.etree.XMLSyntaxError: Opening and ending tag mismatch: meta line 3 and head, line 3, column 87

      # 创建html解析器,增加parser参数

      parser = etree.HTMLParser(encoding="utf-8")

      tree = etree.parse('exe_file/xpath.html', parser=parser)

   看一个例子(爬取58)

import requests
from lxml import etree

headers={
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER'
}
url='https://sz.58.com/ershoufang/?PGTID=0d200001-0000-4229-cd25-6936558931c6&ClickID=1'
#拿到页面源码数据的text
page_text=requests.get(url=url,headers=headers).text
#把页面源码数据作为参数实例一个etree对象
tree=etree.HTML(page_text)

#用xpath进行解析
#xpath表达式的作用:xpath表达式如果作用到页面源码中,可以将页面源码中指定的标签进行定位.
#所有xpath解析返回值为一个列表
#可以对局部对象在进行xpath,但是路径要记得要变成./
li_list=tree.xpath('//ul[@class="house-list-wrap"]/li')

f=open('./xpath-58.txt','w',encoding='utf-8')
for li in li_list:
    title=li.xpath('./div[2]/h2/a/text()')[0]#xpath返回的是一个列表,即使解析对象只有一个
    total_price=li.xpath('./div[3]/p[1]//text()')#返回两个值直接返回
    total_price=''.join(total_price)

    f.write(title+':'+total_price+'\n')
f.close()

#这边只爬取了第一页,如想要爬取其他页面,只要去改一下页码参数,进行一个循环即可

 主要几点:

1.获取文本
  •   a/text() 获取a下文本
  • a//text() 获取a下面的所有文本
  • a[text()='下一页']

2.@符号

  •   a/@href
  • div[@class='detail']
  • div[@id='content']
     

3.//

  • 任意位置开始选择

四.一些高级用法

  1.count:统计

tree.xpath('count(//li[@data])') #节点统计

  2.concat:字符串连接

tree.xpath('concat(//li[@data="one"]/text(),//li[@data="three"]/text())')

  3.string:解析当前节点下的字符

#string只能解析匹配到的第一个节点下的值,也就是作用于list时只匹配第一个
tree.xpath('string(//li)') 

  4. local-name:解析节点名称

tree.xpath('local-name(//*[@id="testid"])') #local-name解析节点名称

  5.not 布尔值(否)

tree.xpath('count(//li[not(@data)])') #不包含data属性的li标签统计
 #多用于表格中匹配中不包含表头信息的数据
 xpath('//table/tr[not(@class="tbhead")]'

  6.string-length:返回指定字符串的长度

#string-length函数+local-name函数定位节点名长度小于2的元素
tree.xpath('//*[string-length(local-name())<2]/text()')[0] 

  7.or:多条件匹配

tree.xpath('//li[@data="one" or @code="84"]/text()') #or匹配多个条件
tree.xpath('//li[@data="one"]/text() | //li[@code="84"]/text()') #|匹配多个条件

  8.<:小于

tree.xpath('//li[@code<200]/text()')

  9.div

tree.xpath('//div[@id="testid"]/ul/li[3]/@code div //div[@id="testid"]/ul/li[1]/@code')

  10.根据节点下的某一节点数量定位

tree.xpath('//ul[count(li)>5]/li/text()')

  11.将对象还原为字符串

>>> s = tree.xpath('//*[@id="testid"]')[0] #使用xpath定位一个节点
>>> s
<Element div at 0x2b6ffc8>
>>> s2 = etree.tostring(s).decode() #还原这个对象为html字符串
>>> s2
'<div id="testid">\n\t\t<h2>&#213;&#226;&#192;&#239;&#202;&#199;&#184;&#246;&#208;&#161;&#177;&#234;&#204;&#226;</h2>\n\t\t<ol>\n\t\t\t<li data="one">1</li>\n\t\t\t<li data="two">2</li>\n\t\t\t<li data="three">3</li>\n\t\t</ol>\n\t\t<ul>\n\t\t\t<li code="84">84</li>\n\t\t\t<li code="104">104</li>\n\t\t\t<li code="223">223</li>\n\t\t</ul>\n\t</div>\n\t'

  注:s2 = etree.tostring(s,encoding=‘utf-8’) 

  12. and

#匹配所有的tr中不包含 tbhead 属性 和包含 head 的tr标签
xpath('//table/tr[not(@class="tbhead") and @class="head"]')

  13. or

匹配包含class="speedbar" 或者 class="content-wrap" 的标签
xpath('//div[@class="speedbar" or @class="content-wrap"]')

  14.取货所有的属性

//div/@* 

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

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

相关文章

【Linux】有名管道介绍及使用

目录 有名管道有名管道使用 橙色 有名管道 有名管道(FIFO)和匿名管道(pipe)有一些特点是相同的,不一样的地方在于: FIFO在文件系统中作为一个特殊文件存在&#xff0c;但文件中是没有内容的&#xff0c; FIFO中的内容存放在内存中。当使用FIFO的进程退出后&#xff0c; FIFO文…

在离散混合制造环境中应用制造运营模型

介绍 本文所描述的所有制造过程、场景、操作模式和技术应用目前都在一个成熟的离散和离散/批量混合制造企业中使用&#xff0c;该企业生产和维修复杂的机器。该企业生产的产品范围从从棒材加工的简单零件到复杂的机械装配&#xff1b;最终产品包括许多内部和第三方提供的子装配…

5.2————运算符重载

对于基本的数据类型&#xff0c;C提供来许多预先定义的运算符&#xff0c;如“&#xff0c;-&#xff0c;*&#xff0c;/”等&#xff0c;他们的运用大家应该已经很熟悉了。那么我们引入运算符重载的概念到底是为什么&#xff0c;比如是我们的加号可以完成基本数据类型的相加&a…

mysql 修改最大连接数max_connections

mysql 修改最大连接数max_connections 1、编辑mysql service文件2、编辑mysql 配置文件3、重启MySQL服务4、查看max_connections 1、编辑mysql service文件 查找mysql service文件 find / -name mysql*.service先备份再编辑 cp /usr/lib/systemd/system/mysqld.service /usr…

【C++ STL】 那年我双手插兜,学会了stackqueuepriority_queue基础知识及其模拟实现【对话情景版】

文章目录 &#x1f4cd;前言C STL 之 stack&queue基础知识及其模拟实现&#x1f4cd;容器适配器&#x1f388;什么是适配器&#xff1f;&#x1f388;STL标准库中stack和queue的底层结构&#x1f388;deque的简单介绍(了解)&#x1f4cc;deque的原理介绍&#x1f4cc;deque…

基于SSM的书画拍卖网站

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

软件系统外包开发流程及注意事项

当企业发展到一定规模后&#xff0c;市场上通用的软件系统往往就无法满足自身的业务需要&#xff0c;这时就需要企业开发属于自己软件系统。软件系统是一项比较复杂的系统工程&#xff0c;从需求分析、代码开发到最后的上线需要比较长的时间&#xff0c;需要有系统的管理方法才…

问题记录:Datax+Datax-web2.1.2的一系列问题

问题1&#xff1a;DataX报错解决办法 - 在有总bps限速条件下&#xff0c;单个channel的bps值不能为空&#xff0c;也不能为非正数 问题原因&#xff1a; 正如中文字面上所说&#xff0c;DataX的配置有问题&#xff0c;单个channel的bps值不能为空&#xff0c;也不能为非正数。…

教你怎么翻译英语语音

在当今全球化的时代&#xff0c;跨语言交流是一种常态。无论你是在国外旅游时无法理解当地人说的英文意思&#xff0c;还是因为职业需要与国外客户、供应商进行交流&#xff0c;这时候通过翻译英文语音就可以帮助你获取对话内容&#xff0c;缩短沟通时间和提升工作效率。那对于…

【windows批处理batch】.bat文件循环判断语句

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、…

计算机毕业论文内容参考|基于java的学生成绩分析系统的设计与实现

文章目录 导文摘要前言课题背景国内外现状与趋势课题内容相关技术与方法介绍技术分析技术设计系统架构设计数据库设计安全认证设计数据可视化设计技术实现后端实现安全认证实现数据可视化实现总结与展望本文总结后续工作展望导文 基于java的学生成绩分析

【逆向工程核心原理:TLS回调函数】

TLS 代码逆向分析领域中&#xff0c;TLS&#xff08;Thread Local Storage&#xff0c;线程局部存储&#xff09;回调函数&#xff08;Callback Function&#xff09;常用反调试。TLS回调函数的调用运行要先于EP代码的执行&#xff0c;该特征使它可以作为一种反调试技术的使用…

【经验总结】你想知道的BGA焊接问题都在这里

BGA是一种芯片封装的类型&#xff0c;英文 (Ball Grid Array)的简称&#xff0c;封装引脚为球状栅格阵列在封装底部&#xff0c;引脚都成球状并排列成一个类似于格子的图案&#xff0c;由此命名为BGA。 主板控制芯片诸多采用此类封装技术&#xff0c;采用BGA技术封装的内存&am…

聚焦 TimescaleDB VS TDengine 性能对比报告,五大场景全面分析写入与查询

基于第三方基准性能测试平台 TSBS&#xff08;Time Series Benchmark Suite&#xff09; 标准数据集&#xff0c;TDengine 团队分别就 TSBS 指定的 DevOps 中 cpu-only 五个场景&#xff0c;对时序数据库&#xff08;Time Series Database&#xff0c;TSDB&#xff09;Timescal…

ACT:非对称协同训练的半监督域自适应医学图像分割

文章目录 ACT: Semi-supervised Domain-Adaptive Medical Image Segmentation with Asymmetric Co-training摘要本文方法实验结果 ACT: Semi-supervised Domain-Adaptive Medical Image Segmentation with Asymmetric Co-training 摘要 作者建议以统一的方式利用标记的源域和…

nginx实现正向代理

1.下载nginx nginx: download 选择自己需要的版版本下载下来 2.解压文件修改ngixn.conf配置文件 events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout…

MySQL基础(三十六)其他数据库日志

千万不要小看日志。很多看似奇怪的问题&#xff0c;答案往往就藏在日志里。很多情况下&#xff0c;只有通过查看日志才能发现问题的原因&#xff0c;真正解决问题。所以&#xff0c;一定要学会查看日志&#xff0c;养成检查日志的习惯&#xff0c;对提升你的数据库应用开发能力…

【星戈瑞】Sulfo-CY3-COOH磺化/水溶性Cyanine3羧酸1121756-11-3

Sulfo-CY3 COOH是一种荧光染料&#xff0c;其分子结构中含有COOH官能团&#xff0c;最大吸收波长为550纳米左右&#xff0c;可以通过分光光度计等设备进行检测。Sulfo-CY3 COOH是一种带有羧基的荧光染料&#xff0c;可以与含有氨基的生物分子通过偶联反应形成共价键&#xff0c…

TMP的阴影性能如何

1&#xff09;TMP的阴影性能如何 ​2&#xff09;CommandBuffer.DrawMeshInstanced无法画阴影问题 3&#xff09;Unity编辑器在Require大量加载Lua文件时&#xff0c;经常报出not enough memory 4&#xff09;场景制作的时候&#xff0c;2D资源受后处理调色影响比较大 这是第33…

JVM面试题(一)

JVM内存分哪几个区&#xff0c;每个区的作用是什么? java虚拟机主要分为以下几个区: JVM中方法区和堆空间是线程共享的&#xff0c;而虚拟机栈、本地方法栈、程序计数器是线程独享的。 &#xff08;1&#xff09;方法区&#xff1a; a. 有时候也成为永久代&#xff0c;在该区内…