Python3爬虫——用Xpath提取网页信息

2023-11-19

Python3爬虫——用Xpath提取网页信息

前言

本笔记用于记录整理requests库的一些基本知识,内容会根据博主自己的认知作增添或压缩。
水平有限,如有错误请不吝赐教。
本文需要读者初步了解HTML有关节点的相关知识。


Xpath的梗概和安装

XPath即为XML路径语言(XML Path Language),它是一种用来确定XML文档中某部分位置的语言。XPath基于XML的树状结构,提供在数据结构树中找寻节点的能力。使用Xpath最初是用于搜寻XML文档的,但同样适用于HTML文档的搜索。

使用Xpath前,请先保证其已经安装,可以利用pip进行安装:

pip3 install lxml

这里主要用到lxml包内的etree的库,其提供了Xpath的方法。

Xpath常用规则

表达式 描述
nodename 选取此节点的所有子节点
/ 进入当前节点的直接子节点
// 进入当前节点的子孙节点
. 选取当前节点
.. 选取当前节点的父节点
@ 选取当前节点的属性

小试牛刀:

//title[@endtime="2023-02-04"]

意思是选取所有名为title并带有属性endtime"2023-02-04"的节点

使用Xpath

接入HTML文本

从内存中读取

假设已经存在这样一段HTML文本:

text = '''
<div class="device-notification">
  <a class="device-notification--logo" href="#0">
    <img src="assets/img/logo.png" alt="Global">
    <p>Emoreの云</p>
  </a>
  <p class="device-notification--message">请将手机横向放置以继续体验</p>
</div>
'''

这意味着这段HTML存在内存内,可能是网上抓取来的或是提前读取好的,接入Xpath的方法如下:

import lxml import etree  # 载入etree库

html = etree.HTML(text)  # 构造Xpath解析对象
从文件中读取

假设有一个text.html文件在你的程序所在的文件夹中,里面这需要解析的HTML文本:

from lxml import etree  # 载入etree库

html = etree.parse('./text.html', etree.HTMLParser())  # 从文本构造Xpath解析对象

不论是哪种方法构造Xpath解析对象,etree都会对HTML文本进行修正。如果从文件读取,修正时可能额外出现DOCTYPE声明。

查找节点

所有节点

利用Xpath查找结点时,一般采用以//开头的Xpath规则选择所有符合要求的节点。以上文的HTML文本为例:

>>> html = etree.HTML(text)
>>> result1 = html.xpath('//*')  # *代表选择当前目录的所有节点
>>> print(result1)  # 返回结果是列表
[<Element html at 0x27378d2c440>, <Element body at 0x27378e98140>, <Element div at 0x27378e98300>, <Element a at 0x27378e98400>, <Element img at 0x27378e98440>, <Element p at 0x27378e98480>, <Element p at 0x27378e98240>]

>>> print(result1[0])  # 选取结果中的第一个
<Element html at 0x27378d2c440>

其中Element后面的内容便是节点名,本身不存在的html节点和body节点都自动补全了。

指定节点

//后面的内容换成节点名,即可查找指定节点,如查询上文所有的p节点:

>>> result2 = html.xpath('//p')
>>> print(result2)
[<Element p at 0x27378e98480>, <Element p at 0x27378e98240>]

同时可以查询具有指定属性的p节点,只需要在节点名后面附带筛选属性,利用[@]将其包裹起来:

>>> result3 = html.xpath('//p[@class="device-notification--message"]')
>>> print(result3)
[<Element p at 0x27378e98240>]

如此只返回了最后一个p节点。

属性多值匹配

有的属性不止有一个值(上文HTML并没有这种情况),需要用contains()方法进行匹配。该方法第一个参数为属性名,第二个参数填入属性值,只要拥有该属性值的节点都会被返回。

result = html.xpath('//p[contains(@class, "device-notification--message")]')
多属性匹配

需要通过多个属性匹配一个节点,可以利用and进行连接,比如匹配一个class含有值device并且nameEmorep节点:

result = html.xpath('//p[contains(@class, "device") and @name="Emore"]')  # 仅举例

除了and,Xpath还含有很多运算符(摘自菜鸟编程),

运算符 描述 实例 返回值
| 计算两个节点集 //book | //cd 返回所有拥有 book 和 cd 元素的节点集
+ 加法 6 + 4 10
- 减法 6 - 4 2
* 乘法 6 * 4 24
div 除法 8 div 4 2
= 等于 price=9.80 如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。
!= 不等于 price!=9.80 如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
< 小于 price<9.80 如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
<= 小于或等于 price<=9.80 如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。
> 大于 price>9.80 如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。
>= 大于或等于 price>=9.80 如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。
or price=9.80 or price=9.70 如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。
and price>9.00 and price<9.90 如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。
mod 计算除法的余数 5 mod 2 1
选择顺序

有时候有两个或者多个节点,可以像列表一样选择其中某个节点。需要注意的是,Xpath是从1开始计数的。

# 仅举例
result = html.xpath('//div/p[0]')  # 选择第一个p节点
result = html.xpath('//div/p[last()]')  # 选择最后一个p节点
result = html.xpath('//div/p[posision()<3]')  # 选择前面两个p节点
result = html.xpath('//div/p[last()-2]')  # 选择倒数第三个p节点 
查找子孙节点

查找子孙节点只需要像文件路径一样/下去就好了,不同的是/是只访问直接子节点,而//是访问所有的子孙节点:

例如我需要寻找div节点下的p节点:

>>> result4 = html.xpath('//div/p')  # 利用'/'搜索节点p
>>> result5 = html.xpath('//div//p')  # 利用'//'搜索节点p
>>> print(result4)
[<Element p at 0x27378e98240>]

>>> print(result5)
[<Element p at 0x27378e98480>, <Element p at 0x27378e98240>]

div节点的直接子节点中含有一个p节点,还有一个a节点。其中a节点内含有一个img节点和一个p节点。利用/只检索到一个p节点,而利用//检索到了两个p节点,即访问了子节点和孙节点。

查找父节点

同样类似命令cd ..打开上级目录,Xpath中的..可以用于进入父节点。

>>> result6 = html.xpath('//div/p/../a/img')
>>> print(result6)
[<Element img at 0x27378e98440>]

首先进入了div节点的p节点,然后从p节点返回绕到了a节点,并取得里面的img节点。

获得属性和文本

利用Xpath内的text()方法可以获得节点的文本,利用@可以获得指定属性的值。

>>> print(result7)
['请将手机横向放置以继续体验']

>>> result8 = html.xpath('//div/p/@class')
>>> print(result8)
['device-notification--message']

同样输出为列表。

节点轴选择

通过轴节点可以快速选择具有相关关系的节点,如选择div节点的所有直接子节点:

>>> result10 = html.xpath('//div/child::*')
>>> print(result10)
[<Element a at 0x27378e98400>, <Element p at 0x27378e98240>]

首先需要调用child轴,获得所有匹配的节点,然后使用两个冒号::进入选择器,接着用*选择所有节点。

还有很多轴可供选择(摘自菜鸟编程):

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

小结

使用XPath可以快速而准确地进行HTML节点选择,并提取信息,但是要注意构造XPath表达式,以避免提取错误。

同时还有一些需要注意的地方:

  • 顺序选择节点时,起始数为1
  • 选择文本的时候需要精准地进入节点,否则text()会返回错误的文本,如一个换行符或一个缩进。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python3爬虫——用Xpath提取网页信息 的相关文章

随机推荐

  • 数据结构——哈希排序

    哈希排序 就是用空间换取时间的一种排序方式 空间利用率达O n 算法思想 如果一个元素序列a里没有重复的元素 而我们需要找最大值或者前几个最大值时 怎么办呢 1 将这个a序列排序 然后直接选出目标值 2 开辟一个b数组 a里的每一个元素对应
  • WDK李宏毅学习笔记第八周01_Point Network

    文章目录 摘要 一 Pointer Network 1 1 目的 1 2 原理 1 3 优点 二 Applications Summarization 2 1 原理 2 2 优点 三 Applications Translation and
  • TensorFlow实战练习

    TensorFlow实战1 TensorFlow实现手写数字识别 前言 MNIST数据集 学习心得 全代码如下 TensorFlow实现手写数字识别 前言 本人正在学习TensorFlow的使用 使用的书籍是 TensorFlow实战 黄文
  • U-net源码讲解(Keras)

    更新 这个项目是2018 8月份写的 时间过得真快 现在都快一年了 其实深度学习这方面各种软硬件更新很快 如果你是新手学Unet 那么用keras版的也是蛮好的 但是到最后有自己的一点需求后再在此基础上搭自己的模块后Keras就显得很麻烦了
  • 浅谈HTTP中Get、Post、Put与Delete请求方式的区别

    1 GET请求会向数据库发索取数据的请求 从而来获取信息 该请求就像数据库的select操作一样 只是用来查询一下数据 不会修改 增加数据 不会影响资源的内容 即该请求不会产生副作用 无论进行多少次操作 结果都是一样的 2 与GET不同的是
  • 房价预测回归模型--tensorflow2.0学习笔记--tf.keras使用实例

    import tensorflow as tf import matplotlib as mpl import matplotlib pyplot as plt matplotlib inline import numpy as np im
  • Netty框架之概述及基本组件介绍

    概述 Netty是由JBOSS提供的一个java开源框架 是一个高性能 高可扩展性的异步事件 驱动的 网络应用程序框架 它极大地简化了TCP和UDP客户端和服务器开发等网络编 程 NIO有下面的缺点 JDK 的 NIO 底层由 epoll
  • 计算机文件及文件夹管理软件,常用管家(电脑文件夹管理工具)V1.1 免费版

    常用管家 电脑文件夹管理工具 是一款很优秀好用的文件夹管理助手 如果你需要一款好用的文件夹管理工具 不妨试试小编带来的这款常用管家软件 功能强大全面 使用后可以帮助用户更轻松便捷的管理文件夹 软件能够快速收藏和打开常用的文件夹 网站 并且能
  • 决策树实战:california房价预测

    Python3 7 决策树实战 california房价预测 网上有好多2 版本的代码 但是本地安装的是python3 7版本 在学习中遇到很多问题 有很多地方和2 版本的不一样 所以记录下来方便参考 侵权必删 导入模块 import pa
  • CISCN2018-WP

    MISC 验证码 用token登录 输入好验证码就可以得到flag Picture 图片隐写 一下就想到binwalk或者winhex打开试试 binwalk打开无果 将这段数据ctrl shift c复制出来 用下面python脚本生成z
  • HTML标签及浮动

  • 7.块设备驱动的I/O请求处理(2)

    不适用请求队列 使用请求队列对于一个机械磁盘设备而言的确有助于提高系统的性能 但是对于RAMDISK ZRAM Compressed RAM Block Device 等完全可真正随机访问的设备而言 无法从高级的请求队列逻辑中获益 对于这些
  • 稳定性相关大纲

    稳定性建设的几个维度 个人渣记录仅为自己搜索用的博客 CSDN博客 道法术器 稳定性相关 代码 产品灰度能力 降级百分比能力 动态diamond doom测试 单元测试 稳定性改造 高资源占用优化 方法 架构上改造降流量 例如心跳 内部逻辑
  • 真正的阅读者,是不需要荐书的

    From http www luanxiang org blog archives 2136 html 早上一个朋友在朋友圈里跟我说 上次你推荐的 信息简史 和 知识的边界 两本书 我觉得很不错 这条消息让我比较差异 首先我并没有 推荐 过
  • 数据集分割

    步骤 1 确定训练集和测试集是否同分布 常用方法 1 留出法 实现 直接将数据集拆分为互斥的训练集 验证集和测试集 划分比例 训练集 验证集 测试集 7 1 5 1 5 注意事项 单次使用留出法会导致模型不稳定 保证三种数据集中样本比例的相
  • Linux 下使用 C++ 实现的 Web 文件服务器

    项目地址 Github https github com shangguanyongshi WebFileServer 在学习完成 TCP IP 网络编程 和 Linux高性能服务器编程 后 阅读了一些Web服务器的相关代码 自动动手使用
  • code style

    最近一直在看java convention和google c style 因为老板要提高代码质量 我们小公司一个 因为客户说我们的代码质量太烂了 于是开始搞代码质量 先从静态 代码质量开始 于是就研究起来code style 但是 我发现
  • Pthread 并发编程(三)——深入理解线程取消机制

    基本介绍 线程取消机制是 pthread 给我们提供的一种用于取消线程执行的一种机制 这种机制是在线程内部实现的 仅仅能够在共享内存的多线程程序当中使用 基本使用 include
  • 【ARM】程序快速定位segmentation fault core dumped错误

    1 应用场景 ARM开发过程中经常进程运行着出现段错误 这时候单纯靠加日志打log效率太低 使用gdb的话 由于APP进程太多 生成的core的文件特别大 而且gdb在arm板子也不好单步调试 不太友好还是pass掉 目前使用段错误捕捉SI
  • Python3爬虫——用Xpath提取网页信息

    Python3爬虫 用Xpath提取网页信息 前言 本笔记用于记录整理requests库的一些基本知识 内容会根据博主自己的认知作增添或压缩 水平有限 如有错误请不吝赐教 本文需要读者初步了解HTML有关节点的相关知识 文章目录 Pytho