当前位置: 首页 > article >正文

Python学习第二十三天

数据解析

        主要的作用是解析HTML、XML,urllib是用来爬取数据我们将数据爬取后,我们需要将爬取的数据部分进行解析功能。

        分类:xpath、jsonpath、bs4(beautiful soup)

xpath

官网概念

        xpath没有官网是由一些社区维护发布的、官网目前可以认定为W3C(万维网)在维护,也可以通过其他的学习网站进行学习。

安装

# lxml支持了xpath
pip install lxml

作用

  • 主要用于 XML 和 HTML 文档的节点定位。

  • 语法强大,支持复杂的查询和条件过滤。

  • 适用于需要精确查找的场景。

使用

from lxml import etree
# 解析本地文件 如果报错 需要看下meta是否有结尾 检查自己的html中是不是有没有结尾的<meta charset="utf-8" /> 注意必须要有结尾/>
tree = etree.parse('test_xpath.html')
# 用法
# /	从根节点开始选取
value = tree.xpath("/html/body/ul/li")
print(f"/从根节点开始选取:{value}") # [<Element li at 0x22cf8c3df80>, <Element li at 0x22cf8c3dfc0>, <Element li at 0x22cf8c3e000>]
# //从当前节点开始,递归选取所有匹配的节点,无论它们在文档中的位置
value = tree.xpath("//ul")
print(f"//从当前节点开始,递归选取所有匹配的节点,无论它们在文档中的位置:{value}") # [<Element ul at 0x23ccd56dc40>]
# .	选取当前节点
value = tree.xpath(".")
print(f".选取当前节点:{value}") # [<Element html at 0x19bff2afcc0>]
# ..	选取当前节点的父节点
value = tree.xpath("..//ul")
print(f"..选取当前节点的父节点:{value}") # [<Element ul at 0x19bff39d980>]
# @	选取属性
value = tree.xpath("//ul/li/@style")
print(f"@选取属性:{value}") # ['font-size: 10px', 'font-size: 20px', 'font-size: 30px']
# *	匹配任何元素节点
value = tree.xpath("//ul/*")
print(f"*匹配任何元素节点:{value}") # [<Element li at 0x1a20b761500>, <Element li at 0x1a20b761540>, <Element li at 0x1a20b7616c0>, <Element a at 0x1a20b761640>]
# @*匹配任何属性节点
value = tree.xpath("//ul/li/@*")
print(f"@*匹配任何属性节点:{value}") # ['font-size: 10px', 'font-size: 20px', 'font-size: 30px']
# node()匹配任何类型的节点(元素、属性、文本等)
value = tree.xpath("//ul/li/node()")
print(f"node()匹配任何类型的节点(元素、属性、文本等):{value}") # ['python', 'java', 'js']
# text()选取节点的文本内容
value = tree.xpath("//ul/li/text()")
print(f"text()选取节点的文本内容:{value}")  # ['python', 'java', 'js']
# []用于过滤节点,括号内为条件
value = tree.xpath("//li[@id='java']")
print(f"[]用于过滤节点,括号内为条件:{value}") # [<Element li at 0x1ee12a8d780>]
# |	用于组合多个路径,返回所有匹配的节点
value = tree.xpath("//ul/li/text()|//ul/a/text()")
print(f"|	用于组合多个路径,返回所有匹配的节点:{value}") # ['python', 'java', 'js', 'test_a']
# position()返回节点在节点集中的位置
value = tree.xpath("//ul/li[position()<2]")
print(f"position()	返回节点在节点集中的位置:{value}") # [<Element li at 0x206623c2180>] 返回第一个li
# last()返回节点集中最后一个节点
value = tree.xpath("//ul/li[last()]") # [<Element li at 0x134ce211bc0>]
print(f"last()返回节点集中最后一个节点:{value}") # [<Element li at 0x13428cd1e40>] li最后一个
# contains(str1, str2)	判断str1是否包含str2,返回布尔值
value = tree.xpath("//ul/li[contains(text(),'java')]")
print(f"contains(str1, str2)判断str1是否包含str2,返回布尔值:{value}") # [<Element li at 0x1e48dbc1c00>]
# starts-with(str1, str2)	判断str1是否以str2开头,返回布尔值
value = tree.xpath("//ul/li[starts-with(text(),'p')]")
print(f"starts-with(str1, str2)判断str1是否以str2开头,返回布尔值:{value}") # [<Element li at 0x230bb061c80>]
# not(expression)对表达式取反
value = tree.xpath("//ul/li[not(text()='java')]/text()")
print(f"not(expression)对表达式取反:{value}") # ['python', 'js']
# and逻辑与操作
value = tree.xpath("//ul/li[text()='java'  and position()<3 ]")
print(f"and逻辑与操作:{value}") # [<Element li at 0x1946f761ec0>]
# or逻辑或操作
value = tree.xpath("//ul/li[text()='java'  or text()='python' ]/text()")
print(f"or逻辑或操作:{value}") # ['python', 'java']

语法

语法描述
/从根节点开始选取。
//从当前节点开始,递归选取所有匹配的节点,无论它们在文档中的位置。
.选取当前节点。
..选取当前节点的父节点。
@选取属性。
*匹配任何元素节点。
@*匹配任何属性节点。
node()匹配任何类型的节点(元素、属性、文本等)。
text()选取节点的文本内容。
[]用于过滤节点,括号内为条件。
|

用于组合多个路径,返回所有匹配的节点。

position()返回节点在节点集中的位置。
last()返回节点集中最后一个节点。
contains(str1, str2)判断 str1 是否包含 str2,返回布尔值。
starts-with(str1, str2)判断 str1 是否以 str2 开头,返回布尔值。
not(expression)对表达式取反。
and逻辑与操作。
or逻辑或操作。

jsonpath

官网概念

        其实jsonpath主要是对于xpath的一个补充、因为xpath处理的是html或者xml,所以当需要解析json时来使用jsonpath。

安装

# 支持一般的语法
pip install jsonpath
# 支持函数 length()、min()等
pip install jsonpath-ng

作用

  • 主要用于 JSON 数据的查询和提取。

  • 语法简单,适合处理嵌套的 JSON 结构。

  • 适用于 API 返回的 JSON 数据处理。

使用

import jsonpath,json
from django.template.defaultfilters import length
# 官网:https://pypi.org/project/jsonpath-ng/ 注意了 必须要使用ext下才可以使用函数  否则会一直报错 这里说的是 表达式内直接写函数 `len`|`sub(/foo\\+(.*)/, \\1)`|`split(+, 2, -1)`|`sorted`
from jsonpath_ng.ext import parse
# 将json加载成jsonobject对象 之后对于jsonobject进行处理
obj = json.load(open("test_jsonpath.json",'r',encoding='utf-8'))
# $	根节点
value = jsonpath.jsonpath(obj,"$.store")
print(f"$根节点:{value}") # $.store输出全部 $.clothing不是根目录 输出false
# @	当前节点 通常于过滤连用[]
value = jsonpath.jsonpath(obj,"$.store.clothing[?(@.price > 10)]")
print(f"@当前节点:{value}") # [{'name': '绿色衣服', 'color': 'green', 'remark': '一件漂亮的绿色衣服', 'price': 179.99}]
# .key	选择当前节点的key子节点
value = jsonpath.jsonpath(obj,"$.store.clothing")
print(f".key选择当前节点的key子节点:{value}") # 太长了
# ['key']	选择当前节点的key子节点(支持特殊字符)
value = jsonpath.jsonpath(obj,"$.store['food']")
print(f"['key']	选择当前节点的key子节点(支持特殊字符):{value}") # [[{'name': '大面包', 'price': 1.5}, {'name': '烤鸡', 'price': 20}]]
# ..key	递归查找所有key节点
value = jsonpath.jsonpath(obj,"$.store..['food']")
print(f"..key	递归查找所有key节点:{value}") # [[{'name': '大面包', 'price': 1.5}, {'name': '烤鸡', 'price': 20}]]
# 通配符 *
value = jsonpath.jsonpath(obj,"$.store.clothing[*].name")
print(f"通配符 *:{value}") # ['红色衣服', '蓝色衣服', '绿色衣服']
# 数组索引 [n]	选择数组中的第n个元素(从 0 开始)
value = jsonpath.jsonpath(obj,"$.store.clothing[0].name")
print(f"数组索引 [n]	选择数组中的第n个元素(从 0 开始):{value}") # ['红色衣服']
# [start:end:step]	选择数组中的切片(支持 Python 切片语法)
value = jsonpath.jsonpath(obj,"$.store.clothing[0:1,1].name")
print(f"[start:end:step]选择数组中的切片(支持 Python 切片语法):{value}") # ['红色衣服', '蓝色衣服']
# [?(表达式)]使用过滤表达式筛选数组元素
value = jsonpath.jsonpath(obj,"$.store.clothing[?(@.name == '绿色衣服')]")
print(f" [?(表达式)]使用过滤表达式筛选数组元素:{value}") # [{'name': '绿色衣服', 'color': 'blue', 'remark': '一件漂亮的绿色衣服', 'price': 179.99}]
# =~	正则表达式匹配

# len	返回数组或字符串的长度 函数这些需要jsonpath-ng库才可以支持 否则会返回False 安装pip install jsonpath-ng
try:
    jsonpath_expr = parse('$.store.clothing.`len`')
except Exception as e:
   raise e
# 下面的部分为 jsonpath_ng模块中的规定匹配写法
matches = [match.value for match in jsonpath_expr.find(obj)]
#或者 print(f"length()返回数组或字符串的长度:{length(matches)}") 这种方式就不用引入ext那个包了  引入 jsonpath_ng即可
print(f"`len`返回数组或字符串的长度:{matches}")
# min	返回数组中的最小值
try:
    jsonpath_expr = parse('$.store.clothing[?(@.price < 10)].price')
except Exception as e:
   raise e
# 下面的部分为 jsonpath_ng模块中的规定匹配写法
matches = [match.value for match in jsonpath_expr.find(obj)]
price = min(matches)
print(f"min()返回数组或字符串的长度:{price}")
# max()	返回数组中的最大值
price = max(matches)
print(f"max()返回数组中的最大值:{price}")
# sum()	返回数组中的总和
price = sum(matches)
print(f"sum()返回数组中的总和:{price}")
# sorted	排序
try:
    jsonpath_expr = parse('$.store.clothing[?(@.price < 10)].`sorted`')
except Exception as e:
   raise e
matches = [match.value for match in jsonpath_expr.find(obj)]
print(f"`sorted`排序:{matches}")

语法

语法描述
根节点
$根节点。
当前节点
@当前节点。
子节点
.key选择当前节点的 key 子节点。
['key']选择当前节点的 key 子节点(支持特殊字符)。
递归查找
..key递归查找所有 key 节点。
通配符
*匹配任何属性名或数组索引。
数组索引
[n]选择数组中的第 n 个元素(从 0 开始)。
[start:end:step]选择数组中的切片(支持 Python 切片语法)。
[?(表达式)]使用过滤表达式筛选数组元素。
组合路径
key1.key2选择 key1 下的 key2 子节点。
key1[*].key2选择 key1 下所有元素的 key2 子节点。
过滤表达式
==等于。
!=不等于。
<小于。
<=小于等于。
>大于。
>=大于等于。
=~正则表达式匹配。
in包含于。
nin不包含于。
&&逻辑与。
|逻辑或
函数
length()返回数组或字符串的长度。
min()返回数组中的最小值。
max()返回数组中的最大值。
sum()返回数组中的总和。

对比

功能JSONPathXPath
根节点$/
当前节点@.
父节点无直接支持..
子节点.key 或 ['key']/nodename 或 //nodename
递归查找..key//nodename
通配符**
属性选择无直接支持(需通过过滤表达式)@attr
数组索引[n][n]
数组切片[start:end:step]无直接支持
过滤表达式[?(表达式)][表达式]
逻辑运算符&&,|andor
比较运算符==!=<<=>>==!=<<=>>=
正则表达式=~matches()
函数length()min()max()avg()sum()text()contains()starts-with()position()last()
组合路径key1.key2 或 key1[*].key2/path1/path2 或 //path1//path2
文本内容无直接支持text()

Beautiful Soup

官网概念

       Beautiful Soup 是一个 可以从 HTML 或 XML 文件中提取数据的 Python 库。它能用你喜欢的解析器和习惯的方式实现 文档树的导航、查找、和修改。它会帮你节省数小时甚至数天的工作时间。(主要的作用是解析HTML,获取指定的标签内容)。

安装

# 需要安装requests 联合使用
pip install beautifulsoup,requests

使用

import requests,re
from bs4 import BeautifulSoup
#
html_doc = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>

<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>

<p class="story1">...</p>
<p class="story2">2222</p>
<div data-foo="value">foo!</div>
"""
soup = BeautifulSoup(html_doc, 'html.parser')

# 获取title标签
print(soup.title)

# 获取title标签的名称 不是标签内部的
print(soup.title.name)

# 获取title标签的名称 是标签内部的
print(soup.title.string)

# parent的名称
print(soup.title.parent.name)

# 获取 第一个p标签
print(soup.p)

# 获取第一个p标签的class['title']
print(soup.p['class'])

# 获取第一个a标签
print(soup.a)

# 获取所有的a标签 find_all(标签名)
print(soup.find_all("a"))

# 获取所有的p标签
print(soup.find_all("p"))

# 使用多个引入正则re
print(soup.find_all(href=re.compile("elsie"), id='link1'))

# 获取自定义标签内容
print(soup.find_all(attrs={"data-foo": "value"}))

# 按css来搜索
print(soup.find_all("a", class_="sister"))

语法

方法或属性描述
初始化
BeautifulSoup(html, 'html.parser')创建 BeautifulSoup 对象,解析 HTML 文档。
BeautifulSoup(html, 'lxml')使用 lxml 解析器创建 BeautifulSoup 对象(需安装 lxml 库)。
BeautifulSoup(html, 'html5lib')使用 html5lib 解析器创建 BeautifulSoup 对象(需安装 html5lib 库)。
查找元素
soup.find(tag)查找第一个匹配的标签。
soup.find_all(tag)查找所有匹配的标签,返回列表。
soup.select(css_selector)使用 CSS 选择器查找元素,返回列表。
soup.find(tag, attrs={})根据标签和属性查找元素。
soup.find_all(tag, attrs={})根据标签和属性查找所有匹配的元素。
获取内容
tag.text获取标签的文本内容。
tag.get_text()获取标签的文本内容(与 tag.text 相同)。
tag.string获取标签的文本内容(仅当标签内没有子标签时有效)。
tag['attr']获取标签的属性值。
tag.get('attr')获取标签的属性值(推荐使用,避免属性不存在时报错)。
tag.contents获取标签的直接子节点列表。
tag.children获取标签的直接子节点迭代器。
tag.descendants获取标签的所有后代节点迭代器。
导航文档树
tag.parent获取标签的父节点。
tag.parents获取标签的所有祖先节点迭代器。
tag.next_sibling获取标签的下一个兄弟节点。
tag.previous_sibling获取标签的上一个兄弟节点。
tag.next_element获取文档中的下一个节点(不一定是兄弟节点)。
tag.previous_element获取文档中的上一个节点(不一定是兄弟节点)。
修改文档
tag.name = 'new_tag'修改标签的名称。
tag['attr'] = 'value'修改标签的属性值。
tag.append(new_tag)在标签内追加新标签或字符串。
tag.insert(index, new_tag)在标签内插入新标签或字符串。
tag.replace_with(new_tag)替换当前标签。
tag.decompose()删除当前标签及其内容。
tag.clear()删除当前标签的内容,保留标签本身。
其他方法
soup.prettify()格式化输出 HTML 文档。
soup.encode()将文档编码为字节字符串。
soup.decode()将字节字符串解码为文档。

对比

特性/工具XPathJSONPathBeautifulSoup
用途用于在 XML 和 HTML 文档中定位元素用于在 JSON 数据中定位元素用于解析和操作 HTML/XML 文档
语法基于路径表达式基于路径表达式基于 Python 对象的 API
数据格式XML、HTMLJSONHTML、XML
定位元素通过节点路径、属性、文本等通过键、索引、条件等通过标签名、属性、CSS 选择器等
示例/bookstore/book[1]/title$.store.book[0].titlesoup.find('div', class_='title')
灵活性高,支持复杂查询中,适合 JSON 结构高,支持多种查找方式
学习曲线
适用场景XML/HTML 文档解析JSON 数据解析HTML/XML 文档解析和操作
跨语言支持是(多种编程语言支持)是(多种编程语言支持)仅限 Python
性能
扩展性

选择建议

  • 如果需要处理 XML/HTML 文档并需要复杂的查询,选择 XPath。

  • 如果需要处理 JSON 数据,选择 JSONPath。

  • 如果需要解析和操作 HTML/XML 文档,并且使用 Python,选择 BeautifulSoup。


http://www.kler.cn/a/600123.html

相关文章:

  • Flink CEP:复杂事件处理详解
  • 架构思维:从代码实现到系统思维的进阶之路
  • 基于ConcurrentHashMap+Redisson的轻量级分布式锁架构设计与工业级实现
  • [特殊字符] C++ 常见 Socket 错误与优化指南
  • gdb/cgdb:调试器
  • Win98模拟器(安卓):重温经典,一键怀旧
  • 人工智能之数学基础:广义特征值和广义特征向量是什么?
  • idea中快速注释函数
  • pytorch构建线性回归模型
  • 【LInux 维测专栏 1 -- printk extension 介绍】
  • 11-scala多参数列表(柯里化)
  • 小白闯AI:Llama模型Lora中文微调实战
  • Java 代理模式深度解析:从静态到动态的实现与原理
  • 【jvm】垃圾回收的并行和并发
  • 鸿蒙harmonyOS:笔记 正则表达式
  • JVM常用概念之编译器黑洞
  • 数学建模:MATLAB卷积神经网络
  • Langchain 自定义工具和内置工具
  • FRP结合Nginx实现HTTPS服务穿透
  • LVGL移植详细教程(基于STM32F407+rt-thread+FSMC接口屏+V9版本)