五:爬虫-数据解析之xpath解析
五:数据解析之xpath
解析
1.xpath
介绍:
-
xpath
是XML
路径语言,它可以用来确定xml
文档中的元素位置,通过元素路径来完成对元素的查找,HTML
就是XML
的一种实现方式,所以xpath
是一种非常强大的定位方式 -
XPath
(XML Path Language
)是一种XML
的查询语言,它能在XML
树状图中寻找节点。XPath
用于在XML
文档中通过元素和属性进行导航 -
xml
是一种标记语法的文本格式,xpath
可以方便的定位xml
中的元素和其中的属性值。lxml
是Python中的一个第三方模块,它包含了将html
文本转成xml
对象,和对对象执行xpath
的功能
lxml
的安装:
#在终端输入
pip install lxml
xpath
的弊端:
当我们在批量获取数据的时候,如果存在的特别数据比较多,这个时候只用xpath
的话,会无法满足用户的需求,所以针对于不同的网页,我们要灵活的去运用我们的数据解析方式
(1)HTML
树状结构图:
HTML
的结构就是树形结构,HTML
是根节点,所有的其它元素节点都是从根节点发出的,其它的元素都是这棵树上的节点,每个节点还可能有属性和文本值,而路径就是指某个节点到另一个节点的路线
(2)节点之间的关系:
- 父节点:
HTML
是 body 和head
节点的父节点 - 子节点:
head
和body
是HTML
的子节点 - 兄弟节点:拥有相同的父节点,
head
和body
就是兄弟节点,title
和div
不是兄弟,因为他们不是同一个父节点 - 祖先节点:
body
是form
的祖先节点,爷爷辈及以上 - 后代节点:
form
是HTML
的后代节点,孙子辈及以下
2.Xpath
中的绝对路径与相对路径 :
Xpath
中的绝对路径是从HTML
根节点开始算的;而相对路径(使用的更多)则是从任意节点开始的。通过开发者工具,我们可以拷贝到Xpath
的绝对路径和相对路径代码:
注意: 绝对路径是以 Elements
为基准去寻找的,我们爬虫获取的是右键的网页源代码;右键的网页源代码 != Elements
,Elements
是前端页面最终渲染的结果,它与网页源代码是有属性上的差异的;但右键的网页源代码与Elements
是非常相似的,但是在某些元素或者元素属性上会存在不同。这就会导致我们直接右键复制的xpath
获取不到真正的数据;所以说只能手写,不能复制(把数据解析全部学会之后,可以复制,因为到那个时候就有能力对复制到的内容进行微调了)
(1)绝对路径(了解即可):
在Xpath
中最直观的定位策略就是绝对路径,绝对路径是从根节点/html
开始往下一层层的表示,直到出来需要的节点为止
(2)相对路径(常用):
在Xpath
中相对路径方法以 “//” 开头,相对路径可以从任意的节点开始,一般会选取一个可以唯一定位到的元素开始写,这样可以增加查找的准确性
相对路径的定位语法:
(1)基本定位语法:
表达式 | 说明 | 举例 |
---|---|---|
/ | 从根节点开始选取 | /html/div/span |
// | 从任意节点开始选取 | //input |
. | 选取当前节点 | |
.. | 选取当前节点的父节点 | //input/.. 选取input 的父节点 |
@ | 选取属性或者根据属性选取 | //input[@data] 选取具备data 属性的input 元素 //@data 选取所有data 属性 |
* | 通配符,表示任意节点或任意属性 |
(2)元素属性定位:
(3)层级属性结合定位:
遇到某些元素无法精确定位的时候,可以查找其父级及其祖先节点,找到有确定的祖先节点后通过层级依次向下定位
示例:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
<form action="search" id="form" method="post"><span class="bg"><span class="soutu">搜索</span></span><span class="soutu"><input type="text" name="key" id="su"></span><div></div>
</form>
</body>
</html>
图片解析:
(4)使用谓语定位:
谓语是Xpath
中用于描述元素位置,主要有数字下标、最后一个子元素last()
、元素下标函数position()
注意: Xpath
中的下标从 1 开始
图片解析:
1、使用下标的方式,从form找到input:
//form[@id="form"]/span[2]/input2、查找最后一个子元素,选取form下的最后一个span:
//form[@id="form"]/span[last()]3、查找倒数第几个子元素,选取 form下的倒数第二个span:
//form[@id="form"]/span[last()-1]4、使用 position() 函数,选取 from 下第二个span:
//form[@id="form"]/span[position()=2]5、使用 position() 函数,选取下标大于 2 的span:
//form[@id="form"]/span[position()>2]
(5)使用逻辑运算符定位:
用于嵌套的标签,如果元素的某个属性无法精确定位到这个元素,还可以用逻辑运算符and
连接多个属性进行定位
以百度首页为例:
使用and:
//*[@name='wd' and @class='s_ipt']
#查找 name 属性为 wd 并且 class 属性为 s_ipt 的任意元素使用or:
//*[@name='wd' or @class='s_ipt']
#查找 name 属性为 wd 或者 class 属性为 s_ipt 的任意元素,取其中之一满足即可
以上述示例代码为例:
使用|同时查找多个路径,取或:
//form[@id="form"]//span | //form[@id="form"]//input
(6)使用文本定位:
我们在爬取网站使用Xpath
提取数据的时候,最常使用的就是Xpath
的text()
方法,该方法可以提取当前元素的信息,但是某些元素下包含很多嵌套元素,这时候就用到了string()
方法
爬取别逗了网站示例代码:
import requests
from lxml import etreeurl = 'https://www.biedoul.com/article/180839'headers= {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'
}response = requests.get(url,headers=headers)
response.encoding = 'utf-8' # 在requests.get的时候,会默认指定一个编码,但默认指定的编码不一定会是utf-8,是随机的# 将获取的网页源代码html文件转换成xml对象,方便后续执行xpath语法
html = etree.HTML(response.text)
data = html.xpath('//div[@class="cc2"]//text()') # //text()指的是取标签中的文本值,不是属性值
# print(data)
#
# data = [i.replace('\r\n','') for i in data]
# print('\n'.join(data))data1 = html.xpath('//div[@class="cc2"]')[0].xpath('string(.)')
print(data1)
注意: xpath
对象获取的数据返回的是一个列表
(7)使用部分匹配函数:
函数 | 说明 | 示例 |
---|---|---|
contains | 选取属性或者文本包含某些字符 | //div[contains(@id, 'data')] 选取id 属性包含data 的div 元素 |
starts-with | 选取属性或者文本以某些字符开头 | //div[starts-with(@id, 'data')] 选取id 属性以data 开头的div 元素 |
ends-with | 选取属性或者文本以某些字符结尾 | //div[ends-with(@id, 'require')] 选取id 属性以require 结尾的div 元素 |
3.lxml
的使用与xpath
实战:
(1)lxml
的基本使用:
# 导入模块
from lxml import etree
# html源代码
web_data = """<div><ul><li class="item-0"><a href="link1.html">first item</a></li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-inactive"><a href="link3.html">third item</a></li><li class="item-1"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></ul></div>"""
# 将html转成xml对象
element = etree.HTML(web_data)
# print(element)
# 获取li标签下面的a标签的href
links = element.xpath('//ul/li/a/@href')
print(links) # 列表
# 获取li标签下面的a标签的文本数据
result = element.xpath('//ul/li/a/text()')
print(result)
(2)xpath
实战 – 豆瓣top250示例代码:
import requests
from lxml import etree
'''
目标:熟悉xpath解析数的方式
需求:爬取电影的名称 评分 引言 详情页的url 翻页爬取1-10页 保存到列表中如何实现?
设计技术与需要的库 requests lxml(etree)实现步骤
1 页面分析(一般讲数据解析模块 都是静态页面)1.1 通过观察看网页源代码中是否有我们想要的数据 如果有就分析这个url如果没有再通过ajax寻找接口 通过分析数据在网页源代码中1.2 确定目标urlhttps://movie.douban.com/top250?start=0&filter= 第一页通过页面分析发现所有我们想要的数据都在一个div[class="info"]里面具体实现步骤
1 获取整个网页的源码 html
2 将获取的数据源码转成一个element对象(xml)
3 通过element对象实现xpath语法 对数据进行爬取(标题 评分 引言 详情页的url)
4 保存数据 先保存到字典中-->列表中'''# 定义一个函数用来获取网页源代码
def getsource(pagelink):# 请求头headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36'}# 获取源码response = requests.get(pagelink, headers=headers)response.encoding = 'utf-8'html = response.textreturn html# 定义一个函数用于解析我们的网页源代码并获取我们想要的数据
def geteveryitem(html):element = etree.HTML(html)# 拿到[class="info"]的所有divmovieitemlist = element.xpath('//li//div[@class="info"]')# print(movieitemlist,len(movieitemlist))# 定义一个列表itemlist = []for item in movieitemlist:# 定义一个字典itemdict = {}# 标题title = item.xpath('./div[@class="hd"]/a/span[@class="title"]/text()')title = "".join(title).replace("\xa0", "")# print(title)# 副标题othertitle = item.xpath('./div[@class="hd"]/a/span[@class="other"]/text()')[0].replace("\xa0", "")# print(othertitle)# 评分grade = item.xpath('./div[@class="bd"]/div[@class="star"]/span[2]/text()')[0]# print(grade)# 详情页的urllink = item.xpath('div[@class="hd"]/a/@href')[0]# print(link)# 引言quote = item.xpath('div[@class="bd"]/p[@class="quote"]/span/text()')# print(quote)# list index out of range# 处理方式1 非空处理if quote:quote = quote[0]else:quote = ""# 将数据存放到字典中itemdict['title'] = ''.join(title + othertitle)itemdict['grade'] = gradeitemdict['link'] = linkitemdict['quote'] = quote# print(itemdict)itemlist.append(itemdict)# print(itemlist)return itemlistif __name__ == '__main__':url = 'https://movie.douban.com/top250?start=0&filter='html = getsource(url)itemlist = geteveryitem(html)print(itemlist)
dict['quote'] = quote# print(itemdict)itemlist.append(itemdict)# print(itemlist)return itemlistif __name__ == '__main__':url = 'https://movie.douban.com/top250?start=0&filter='html = getsource(url)itemlist = geteveryitem(html)print(itemlist)
相关文章:

五:爬虫-数据解析之xpath解析
五:数据解析之xpath解析 1.xpath介绍: xpath是XML路径语言,它可以用来确定xml文档中的元素位置,通过元素路径来完成对元素的查找,HTML就是XML的一种实现方式,所以xpath是一种非常强大的定位方式 XPa…...
什么是Laravel?它有哪些特性?
Laravel 是一款流行的 PHP Web 框架,设计用于构建现代、优雅且功能强大的 Web 应用程序。它提供了一套丰富的工具和库,以简化常见的开发任务,同时保持灵活性和可扩展性。以下是 Laravel 框架的一些主要特性: 优雅的语法࿱…...

[足式机器人]Part2 Dr. CAN学习笔记-自动控制原理Ch1-3燃烧卡路里-系统分析实例
本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-自动控制原理Ch1-3燃烧卡路里-系统分析实例 1. 数学模型2. 比例控制 Proprotional Control 1. 数学模型 2. 比例控制 Proprotional Control...

安恒明御安全网关 aaa_local_web_preview文件上传漏洞复现
0x01 产品简介 明御安全网关秉持安全可视、简单有效的理念,以资产为视角,构建全流程防御的下一代安全防护体系,并融合传统防火墙、入侵检测、入侵防御系统、防病毒网关、上网行为管控、VPN网关、威胁情报等安全模块于一体的智慧化安全网关。 0x02 漏洞概述 明御安全网关在…...

基于ssm企业人事管理系统的设计与实现论文
摘 要 进入信息时代以来,很多数据都需要配套软件协助处理,这样可以解决传统方式带来的管理困扰。比如耗时长,成本高,维护数据困难,数据易丢失等缺点。本次使用数据库工具MySQL和编程技术SSM开发的企业人事管理系统&am…...
你知道为什么要加 final 关键字了吗?
嗨,大家好,欢迎来到程序猿漠然公众号,我是漠然。 在Java编程中,我们经常会遇到需要使用final关键字的情况。那么,为什么要使用final关键字呢?它到底有什么作用?本文将从以下几个方面来详细…...

找不到mfc100u.dll,程序无法继续执行?三步即可搞定
在使用电脑过程中,我们经常会遇到一些错误提示,其中之一就是“找不到mfc100u.dll”。mfc100u.dll是Microsoft Foundation Class(MFC)库中的一个版本特定的DLL文件。MFC是微软公司为简化Windows应用程序开发而提供的一套C类库。它包…...

postman接口测试之Postman配置环境变量和全局变量
前言 我们在测试的过程中,遇到最多的问题也可以是环境的问题了吧,今天开发用了这个测试环境,明天又换了另一个测试环境,这样对于我们测试非常的麻烦,特别最接口的时候需要来回的输入环境地址比较麻烦,今天…...
OpenSSL 编程示例
参考:深入探索 OpenSSL:概念、原理、开发步骤、使用方法、使用场景及代码示例 地址:https://oneisall.blog.csdn.net/article/details/131489812?spm1001.2014.3001.5502 目录 1. OpenSSL 概念2. OpenSSL 原理3. OpenSSL 开发步骤4. OpenSSL…...
K8S学习指南(17)-k8s核心对象CronJob
文章目录 前言什么是CronJob?示例演示步骤1:创建CronJob步骤2:定义任务模板步骤3:部署CronJob步骤4:监视CronJob的执行 总结 前言 Kubernetes(简称K8s)是一种用于自动部署、扩展和管理容器化应…...
单片机Freertos入门(二)任务调度的介绍
简介: FreeRTOS支持的任务调度方法有抢占式、协作式、时间片轮转,下面分别来讲解。 1.抢占式调度 抢占式调度,是最高优先级的任务一旦就绪,总能得到CPU的执行权。 高优先级运行时候,低优先级不运行,等待…...

QT----自定义信号和槽
第二天 2.1自定义信号和槽 新建一个Qtclass 自定义信号:返回值是void ,只需要声明,不需要实现,可以有参数,可以重载 自定义槽:返回值void ,需要声明,也需要实现,可以有…...

【Vue第4章】Vue中的ajax_Vue2
目录 4.1 解决开发环境Ajax跨域问题 4.1.1 解决跨域的三种方法 4.1.2 使用代理服务器 4.1.3 笔记与代码 4.1.3.1 笔记 4.1.3.2 19_src_配置代理服务器 4.2 github用户搜索案例 4.2.1 效果 4.2.2 接口地址 4.2.3 笔记与代码 4.2.3.1 20_src_github搜索案例 4.3 vue项…...
力扣labuladong——一刷day72
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、力扣109. 有序链表转换二叉搜索树二、力扣1382. 将二叉搜索树变平衡 前言 二叉树的递归分为「遍历」和「分解问题」两种思维模式,这道题需要用到…...

Leetcode—509.斐波那契数【简单】
2023每日刷题(五十七) Leetcode—509.斐波那契数 实现代码 int fib(int n){if(n 0) {return 0;}if(n 1) {return 1;}return fib(n-1) fib(n-2); }运行结果 之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点…...

山峰个数 - 华为OD统一考试
OD统一考试 分值: 100分 题解: Java / Python / C++ 题目描述 给定一个数组,数组中的每个元素代表该位置的海拔高度。0表示平地,>=1时表示属于某个山峰,山峰的定义为当某个位置的左右海拔均小于自己的海拔时,该位置为山峰。数组起始位置计算时可只满足一边的条件。 …...

38、池化的特征不变性
池化操作有一个比较独特的特性,叫作特征不变性。 很多文章中是这么描述池化的特征不变性的:池化操作的特征不变性,可以提高模型对图片平移、缩放和旋转等变换的鲁棒性。 之前看到这句话的时候,似懂非懂。后来查了一些资料&#…...

051:vue项目webpack打包后查看各个文件大小
第051个 查看专栏目录: VUE ------ element UI 专栏目标 在vue和element UI联合技术栈的操控下,本专栏提供行之有效的源代码示例和信息点介绍,做到灵活运用。 (1)提供vue2的一些基本操作:安装、引用,模板使…...

JVM调优:参数(学习笔记)
一、jvm的运行参数 标准参数 -help、-version、-D参数 jvm的标准参数,一般都是很稳定的,在未来的JVM版本中不会改变,可以使用java -help 检索出所有的标准参数。 通过以下命令查看: 命令:java -help 可以看到我们经常…...

MVC Gantt Wrapper:RadiantQ jQuery
The RadiantQ jQuery Gantt Package includes fully functional native MVC Wrappers that let you declaratively and seamlessly configure the Gantt component within your aspx or cshtm pages just like any other MVC extensions. 如果您还没有准备好转向完全基于客户端…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...

React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
AGain DB和倍数增益的关系
我在设置一款索尼CMOS芯片时,Again增益0db变化为6DB,画面的变化只有2倍DN的增益,比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析: 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...
Go 语言并发编程基础:无缓冲与有缓冲通道
在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好࿰…...

基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...

android RelativeLayout布局
<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...