python 爬虫解析库: jsonpath
0 背景
在之前的文章中, 我写了关于parsel
的用法, 在爬虫中我们可以使用parsel
快速解析和提取 HTML 和 XML 类型的数据。详情可以看: python强大的爬虫css+xpath解析器:parsel .
但有时候, 在请求响应的数据中, 不一定所有的数据都是以html格式返回来的, 通过ajax请求发送的数据通常是以json格式返回, 因为我们需要对json数据进行解析.
那有什么可以快速解析json的方法呢, 另外, 有时我们只需要提取下面这一段json文本中的link的字段, 其他的我可能就不需要了.
{
"data": {
"items": [
{
"name": "orange",
"link": "https://orange.com"
},
{
"name": "apple",
"link": "https://apple.cn"
}
]
}
}
如果通过python直接写, 那么可以多行代码去完成, 当然, 实际情况可能会更复杂些, 因此, 本文主要介绍一个快速解析json的库, 通过特定的语法, 快速地提取我们需要地数据.
jsonpath
是一个用于 Python 的第三方解析库,专门设计用于处理 JSON 数据。它基于 JSONPath 表达式,这是一种从 JSON 对象中提取特定数据的查询语言。
相比自带的json库, jsonpath
的一些关键特点和优势:
-
简单的查询语法: jsonpath
提供了一种非常直观且易于理解的方式来查询 JSON 数据。这让我们能够快速编写出精准的查询,而无需遍历整个 JSON 结构。 -
灵活性:它允许用户编写复杂的查询,包括条件、通配符和递归查询等。这意味着即使面对复杂的 JSON 结构,我们也可以轻松提取所需数据。 -
高效的数据提取:对于大型 JSON 对象,使用 jsonpath
可以更高效地提取数据,因为它直接定位到所需的数据点,而不是遍历整个对象。 -
适用于多种场景:无论是在数据分析、Web 爬虫还是在处理来自 RESTful API 的响应时, jsonpath
都是一个非常有用的工具。 -
与其他Python库的良好兼容性: jsonpath
可以很好地与 Python 中的其他库如requests
(用于发送 HTTP 请求)和json
(用于处理 JSON 数据)等库一起使用,提高了开发的效率和便利性。
1 使用
安装和导入
通过pip安装jsonpath
库
pip install jsonpath
导入并加载示例数据
from jsonpath import jsonpath
from pprint import pprint
result = {
'data': {'items': [
{'name': 'orange', 'type': 'fruit'},
{'name': 'watermelon', 'type': 'fruit'},
{'name': 'huawei', 'type': 'phone'},
{'name': 'apple', 'type': 'fruit'},
{'name': 'xiaomi', 'type': 'phone'},
{'name': 'oppo', 'type': 'phone'},
]},
'status': 'success',
'msg': 'ok',
}
获取所有对象的名称
# 获取所有name
item = jsonpath(result, "$..name")
pprint(f'所有的item的名称: {item}')
item = jsonpath(result, "$.data.items[*].name")
pprint(f'所有的item的名称: {item}')
# "所有的item的名称: ['orange', 'watermelon', 'huawei', 'apple', 'xiaomi', 'oppo']"
# "所有的item的名称: ['orange', 'watermelon', 'huawei', 'apple', 'xiaomi', 'oppo']"
获取所有水果的名称
# 获取所有水果的名称
item = jsonpath(result, "$..[?(@.type=='fruit')].name")
pprint(f'所有的水果的名称: {item}')
# "所有的水果的名称: ['orange', 'watermelon', 'apple']"
判断是否存在apple的手机
# 判断是否存在apple的手机
item = bool(jsonpath(result, "$..[?(@.name=='apple' && @.type=='phone')]"))
pprint(f'是否存在apple: {item}')
# '是否存在apple: False'
查找第一个手机
# 查找第一个手机
item = jsonpath(result, "$..[?(@.type=='phone')].name")
pprint(f'查找第一个手机: {item}')
# '查找第一个手机: huawei'
以上是一些示例.
2 语法
除了以上, 示例, 还有很多方法可以供我们使用, 这里我提供一个对比于xpath语法的jsonpath的语法, 可供参考:
操作符
符号 | 描述 |
---|---|
$ | 查询的根节点对象,用于表示一个json数据,可以是数组或对象 |
@ | 过滤器(filter predicate)处理的当前节点对象 |
* | 获取所有节点 |
. | 获取子节点 |
.. | 递归搜索,筛选所有符合条件的节点 |
?() | 过滤器表达式,筛选操作 |
[start:end] | 数组片段,区间为[start,end),不包含end |
[A]或[A,B] | 迭代器下标,表示一个或多个数组下标 |
语法在上面的例子也有一些体现了.
对比xpath
XPATH路径 | JSONPATH路径 | 描述 |
---|---|---|
/ | $ | 根对象/元素 |
. | @ | 当前对象/元素 |
/ | . 或者 [] | 子操作员 |
.. | 不适用 | 母运营商 |
// | .. | 递归下降。JSONPath 从 E4X 借用了这种语法。 |
* | * | 通配符。所有对象/元素,无论其名称如何。 |
@ | 不适用 | 属性访问。JSON 结构没有属性。 |
[] | [] | 下标运算符。XPath 使用它来迭代元素集合和谓词。 |
| | [,] | XPath 中的联合运算符会产生节点集的组合。 JSONPath 允许将备用名称或数组索引作为一个集合。 |
不适用 | [开始:结束:步骤] | 数组切片运算符借鉴自 ES4。 |
[] | ?() | 应用过滤器(脚本)表达式。 |
不适用 | () | 脚本表达式,使用底层脚本引擎。 |
() | 不适用 | 在 Xpath 中分组 |
更多的语法可以参考官方文档.
3 关于
jsonpath
地语法说起来还是挺多地, 笔者写这篇推文的目的主要是想快速地提取在复杂json中地数据, 所以更多的场景下, 我们了解一些它的基本语法即可, 比如, 如何利用递归搜索..
快速的提取复杂json里面的url, 这在爬虫中是非常有用而且省事的. 高端的场景往往还是需要最朴素的解决办法.
欢迎关注的微信公众号
原文始发于微信公众号(其之):python 爬虫解析库: jsonpath
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/204874.html