xpath入门

在上次我详细的讲了一下什么是xpath,具体了解可以先看下面这篇博客:https://www.cnblogs.com/yanjiayi098-001/p/12009963.html

使用xpath之前先安装lxml库

pip install lxml

先看一段简单的示例:

from lxml import etree

text = '''
<div>
<ul>
<li class="item-0"><a href="link1.html">first</a></li>
<li class="item-1"><a href="link2.html">second</a>
<li class="item-2"><a href="link3.html">third</li>
<li class="item-3"><a href="link4.html">fourth</a></li>
</ul>
</div>
''' html = etree.HTML(text)
result = etree.tostring(html)
print(result.decode('utf-8'))

注意查看代码中的html片段,第二个li没有闭合,第三个li的a标签没有闭合

查看结果:

新建 hello.html

<div>
<ul>
<li class="item-0"><a href="link1.html">first</a></li>
<li class="item-1"><a href="link2.html">second</a></li>
<li class="item-2"><a href="link3.html">third</a></li>
<li class="item-3"><a href="link4.html">fourth</a></li>
</ul>
</div>

.py文件

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = etree.tostring(html)
print(result.decode('utf-8'))

结果:

<html><body>
<div>
<ul>
<li class="item-0"><a href="link1.html">first</a></li>
<li class="item-1"><a href="link2.html">second</a></li>
<li class="item-2"><a href="link3.html">third</a></li>
<li class="item-3"><a href="link4.html">fourth</a></li>
</ul>
</div>
</body></html>

获取节点

获取所有节点

//*表示匹配所有节点

html = etree.parse('./hello.html', etree.HTMLParser())
result = html.xpath('//*')
print(result)

结果:

[<Element html at 0x252593df0c8>, <Element head at 0x252596a7c88>, <Element meta at 0x252596a7cc8>, <Element title at 0x252596a7d48>, <Element body at 0x252596a7f48>, <Element div at 0x252596b40c8>, <Element ul at 0x252596b4148>, <Element li at 0x252596b4188>, <Element a at 0x252596b41c8>, <Element li at 0x252596b4088>, <Element a at 0x252596b4208>, <Element li at 0x252596b4248>, <Element a at 0x252596b4288>, <Element li at 0x252596b42c8>, <Element a at 0x252596b4308>]

匹配指定节点,如获取所有li节点

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li')
print(result) # 所有li节点
print(result[0]) # 第一个li节点

结果:

[<Element li at 0x29d8c7f7bc8>, <Element li at 0x29d8c7f7c08>, <Element li at 0x29d8c7f7c88>, <Element li at 0x29d8c7f7f88>]

<Element li at 0x29d8c7f7bc8>

获取子节点

/表示匹配子节点

获取li节点的直接子节点

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li/a') # 获取所有li节点的直接子节点a
print(result)

结果:

[<Element a at 0x2305cda7c88>, <Element a at 0x2305cda7cc8>, <Element a at 0x2305cda7d48>, <Element a at 0x2305cda7f48>]

改成 // 可以这么写:

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//div//a') # 获取div的所有后代a节点
print(result)

获取父节点

..表示匹配父节点

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())

# 获取href属性为link2.html的a标签的父节点的class名
result = html.xpath('//a[@href="link2.html"]/../@class') print(result) # ['item-1'] #结果

属性匹配

@表示匹配属性

根据属性值匹配节点

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
# 获取属性class值为item-0的li
result = html.xpath('//li[@class="item-0"]') print(result)
# [<Element li at 0x2aa50947cc8>]

属性多值匹配

使用contains函数匹配

可以看出 contains函数表示意思是,第一个参数字符串包含第二个参数时,返回true

实际用起来可能会有点差异(由于结合了路径表达式和属性)

from lxml import etree

text = '''
<li class="li li-first"><a href="link.html">first item</a></li>
''' html = etree.HTML(text)
result = html.xpath('//li[@class="li"]/a/text()')
print(result)
# [] result = html.xpath('//li[contains(@class, "li")]/a/text()')
##选取class属性包含字符串"li"的节点
print(result)
# ['first item']

多属性匹配

需要匹配满足多个属性的节点,使用 and 运算符

from lxml import etree

text = '''
<li class="li li-first" name="item"><a href="link.html">first item</a></li>
''' html = etree.HTML(text)
# 通过class和name两个属性进行匹配
result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')
print(result)
# ['first item']

文本获取

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())

# 获取属性class值为item-0的li的子节点a的文本内容
result = html.xpath('//li[@class="item-0"]/a/text()') print(result)
# ['first']

如果想要获取后代节点内部的所有文本,使用 //text()

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())
# 获取所有li的后代节点中的文本
result = html.xpath('//li//text()') print(result)
# ['first', 'second', 'third', 'fourth']

按序选择

根据节点所在的顺序进行提取

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())

# 按索引排序
result = html.xpath('//li[1]/a/text()')
print(result)
# ['first'] # last 最后一个
result = html.xpath('//li[last()]/a/text()')
print(result)
# ['fourth'] # position 位置查找
result = html.xpath('//li[position()<3]/a/text()')
print(result)
# ['first', 'second'] # - 运算符
result = html.xpath('//li[last()-2]/a/text()')
print(result)
# ['second']

节点轴选择

from lxml import etree

html = etree.parse('./test.html', etree.HTMLParser())

# 所有祖先节点
result = html.xpath('//li[1]/ancestor::*')
print(result)
# [<Element html at 0x106e4be88>, <Element body at 0x106e4bf88>, <Element div at 0x106e4bfc8>, <Element ul at 0x106e6f048>] # 祖先节点中的div
result = html.xpath('//li[1]/ancestor::div')
print(result)
# [<Element div at 0x106ce4fc8>] # 第一个节点的所有属性
result = html.xpath('//li[1]/attribute::*')
print(result)
# ['item-0'] # 子节点
result = html.xpath('//li[1]/child::a[@href="link1.html"]')
print(result)
# [<Element a at 0x107941fc8>] # 后代节点中的a
result = html.xpath('//li[1]/descendant::a')
print(result)
# [<Element a at 0x10eeb7fc8>] # 该节点后面所有节点中的第2个 从1开始计数
result = html.xpath('//li[1]/following::*[2]')
print(result)
# [<Element a at 0x10f188f88>] # 该节点后面的所有兄弟节点
result = html.xpath('//li[1]/following-sibling::*')
print(result)
# [<Element li at 0x104b7f048>, <Element li at 0x104b7f088>, <Element li at 0x104b7f0c8>]

补充

xpath的运算符介绍

xpath轴

XPath库详解的更多相关文章

  1. Lua的协程和协程库详解

    我们首先介绍一下什么是协程.然后详细介绍一下coroutine库,然后介绍一下协程的简单用法,最后介绍一下协程的复杂用法. 一.协程是什么? (1)线程 首先复习一下多线程.我们都知道线程——Thre ...

  2. Python--urllib3库详解1

    Python--urllib3库详解1 Urllib3是一个功能强大,条理清晰,用于HTTP客户端的Python库,许多Python的原生系统已经开始使用urllib3.Urllib3提供了很多pyt ...

  3. Struts标签库详解【3】

    struts2标签库详解 要在jsp中使用Struts2的标志,先要指明标志的引入.通过jsp的代码的顶部加入以下的代码: <%@taglib prefix="s" uri= ...

  4. STM32固件库详解

    STM32固件库详解   emouse原创文章,转载请注明出处http://www.cnblogs.com/emouse/ 应部分网友要求,最新加入固件库以及开发环境使用入门视频教程,同时提供例程模板 ...

  5. MySQL5.6的4个自带库详解

    MySQL5.6的4个自带库详解 1.information_schema详细介绍: information_schema数据库是MySQL自带的,它提供了访问数据库元数据的方式.什么是元数据呢?元数 ...

  6. php中的PDO函数库详解

    PHP中的PDO函数库详解 PDO是一个“数据库访问抽象层”,作用是统一各种数据库的访问接口,与mysql和mysqli的函数库相比,PDO让跨数据库的使用更具有亲和力:与ADODB和MDB2相比,P ...

  7. STM32 HAL库详解 及 手动移植

    源: STM32 HAL库详解 及 手动移植

  8. 爬虫入门之urllib库详解(二)

    爬虫入门之urllib库详解(二) 1 urllib模块 urllib模块是一个运用于URL的包 urllib.request用于访问和读取URLS urllib.error包括了所有urllib.r ...

  9. Python爬虫系列-Urllib库详解

    Urllib库详解 Python内置的Http请求库: * urllib.request 请求模块 * urllib.error 异常处理模块 * urllib.parse url解析模块 * url ...

随机推荐

  1. mac 安装docker

    下载地址: https://download.docker.com/mac/stable/Docker.dmg 从应用中找到 Docker 图标并点击运行.可能会询问 macOS 的登陆密码,输入即可 ...

  2. c语言 内存,可执行文件

    c语言代码与可执行文件的映射关系 函数中的代码 存储在.text 段中 已初始化的全局变量 存储在.data段 未初始化的全局变量 存储在.bss段中 程序类型 映射到file header中 面试题 ...

  3. Egyptian Collegiate Programming Contest (ECPC 2015)

    题目链接:https://vjudge.net/contest/155219#overview. A题,用全排列来找出比当前这个数字字典序还大的排列有几个,然后前缀和dp即可.据说可以康拓展开来快速找 ...

  4. Matlab下imwrite,Uint16的深度图像

    Matlab下imwrite,Uint16的深度图像 1. 在Matlab命令窗口输入命令: help imwrite 会有如下解释: If the input array is of class u ...

  5. 游览器中javascript的执行过程

    在讲这个问题之前,先来补充几个知识点,如果对此已经比较了解可以直接跳过 大多数游览器的组件构成如图 在最底层的三个组件分别是网络,UI后端和js解释器.作用如下: (1)网络- 用来完成网络调用,例如 ...

  6. ubuntu dnsmasq问题

    在很多ubuntu开启wifi热点的教程中,配置比较繁琐的是hostapd+dnsmasq,很多教程都给出了dnsmasq的安装过程,其实在ubuntu桌面版系统下,已经集成到NetworkManag ...

  7. 基础遗传算法的TSP问题

    一.简介 旅行商问题是一个经典的组合优化问题.一个经典的旅行商问题可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地.应如何选择行进路线,以使总的 ...

  8. 在Ubuntu18.04上安装Nvidia驱动

    拿到了一台新机子,带显卡的那种,当然是各种倒腾了!于是我又一天装了三遍机子来进行各种尝试熟悉配置啥的. 所以首先是在裸机上安装Nvidia驱动. 环境:Ubuntu18.04 刚安装完系统,当然是把软 ...

  9. AddLayer和AddTag

    using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; pu ...

  10. 20182332 实验一《Linux基础与Java开发环境》实验报告

    20182332 实验一<Linux基础与Java开发环境>实验报告 课程:<程序设计与数据结构> 班级: 1823 姓名: 盛国榕 学号:20182332 实验教师:王志强 ...