开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第22天,点击查看活动详情
JsonPath
JSONPath是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本,包括:Javascript,Python,PHP和Java。JSONPath对于JSON来说,相当于XPath对于XML。
安装
pip install jsonpath
基本使用
import jsonpath
jsonObj = json.load(open('xxx.json', 'r', encoding='utf-8'))
result = jsonpath.jsonpath(jsonObj, 'jsonpath语法')
语法
JSON结构清晰,可读性高,复杂度低,非常容易匹配。JSONPath的语法与Xpath类似,下表展示了JSONPath与XPath的语法对比:
| XPath | JSONPath | Description |
|---|---|---|
| / | $ | 表示根元素 |
| . | @ | 当前元素 |
| / | . or [] | 子元素 |
| .. | n/a | 父元素 |
| // | .. | 递归下降,JSONPath是从E4X借鉴的。 |
| * | * | 通配符,表示所有的元素 |
| @ | n/a | 属性访问字符 |
| [] | [] | 子元素操作符 |
| | | [,] | 连接操作符在XPath 结果合并其它结点集合。JSONP允许name或者数组索引。 |
| n/a | [start:end:step] | 数组分割操作从ES4借鉴。 |
| [] | ?() | 应用过滤表示式 |
| n/a | () | 脚本表达式,使用在脚本引擎下面。 |
| () | n/a | Xpath分组 |
语法案例演示
首先,我们到沸点评论区找一条沸点,打开评论区,拿到服务器响应回来的json数据,并将其保存到我们项目文件中。不想找的小伙伴也可以直接复制下面的json内容。
{
"err_no": 0,
"err_msg": "success",
"data": [
{
"comment_id": "7177213960243381053",
"comment_info": {
"comment_id": "7177213960243381053",
"user_id": "2189882895379623",
"item_id": "7176819484424929337",
"item_type": 4,
"comment_content": "必须N+1,闹到底",
"comment_pics": [],
"comment_status": 1,
"ctime": 1671075466,
"comment_replys": [],
"digg_count": 0,
"bury_count": 0,
"reply_count": 0,
"is_digg": false,
"is_bury": false,
"level": 0
},
"user_info": {
"user_id": "2189882895379623",
"user_name": "知识搅拌机",
"company": "",
"job_title": "项目经理",
"avatar_large": "https://p26-passport.byteacctimg.com/img/user-avatar/6a74bbc65a694653ed30a1b76c16ccbc~300x300.image",
"level": 1,
"description": "为什么可乐一定要加冰"
}
},
{
"comment_id": "7177204289558496059",
"comment_info": {
"comment_id": "7177204289558496059",
"user_id": "2506542243125469",
"item_id": "7176819484424929337",
"item_type": 4,
"comment_content": "回家休息个把月,再回去仲裁它",
"comment_pics": [],
"comment_status": 1,
"ctime": 1671073224,
"comment_replys": [
{
"user_id": "1415826709428494",
"reply_id": "7177209524732953381",
"reply_comment_id": "7177204289558496059",
"reply_to_reply_id": "0",
"reply_to_user_id": "0",
"item_id": "7176819484424929337",
"item_type": 4,
"reply_content": "在收集证据了",
"reply_pics": [],
"reply_status": 1,
"ctime": 1671074413,
"digg_count": 0,
"burry_count": 0
}
],
"digg_count": 0,
"bury_count": 0,
"reply_count": 1,
"is_digg": false,
"is_bury": false,
"level": 0
},
"user_info": {
"user_id": "2506542243125469",
"user_name": "花染醉墨",
"company": "",
"job_title": "",
"avatar_large": "https://p6-passport.byteacctimg.com/img/user-avatar/0b32cad711929b8817c1365cab56420d~300x300.image",
"level": 5,
"description": ""
},
"cursor": "5",
"count": 84,
"has_more": true
}
]
}
案例1
找到沸点回复评论中的所有掘友,语法如下:
$:根目录data[*]:data属性是一个列表,用*代表全部.comment_info:表示data对象的comment_info属性.user_id:同上
import json
import jsonpath
jsonObj = json.load(open('沸点评论.json', 'r', encoding='utf-8'))
result = jsonpath.jsonpath(jsonObj, '$.data[*].comment_info.user_id')
print(result)
可以看到筛选出来了评论中的掘友,如果只要找其中的一条,则将data[*]修改为对应索引值即可。
案例2
上面的案例找的是沸点评论中的用户ID,但是只有评论的,评论的回复用户ID并没有一起查询出来,如果需要需要加上回复的用户ID,则需要使用..:
可以看到只要是在json中出现的user_id属性都查出来了,但是这里有个小问题,就是该功能并不会帮我们去重。
案例3
查询某个字段下所有的信息,如user_info字段:
import json
import jsonpath
jsonObj = json.load(open('沸点评论.json', 'r', encoding='utf-8'))
result = jsonpath.jsonpath(jsonObj, '$.data[0].user_info.*')
print(result)
案例4
找到某个字段下的所有指定字段,如data属性下的所有user_id字段,包括子孙节点:
import json
import jsonpath
jsonObj = json.load(open('沸点评论.json', 'r', encoding='utf-8'))
result = jsonpath.jsonpath(jsonObj, '$.data[*]..user_id')
print(result)
案例5
找到列表中的后N条数据:
import json
import jsonpath
jsonObj = json.load(open('沸点评论.json', 'r', encoding='utf-8'))
result = jsonpath.jsonpath(jsonObj, '$.data[(@.length-1)]')
print(result)
案例6
找到列表的前N条数据:
import json
import jsonpath
jsonObj = json.load(open('沸点评论.json', 'r', encoding='utf-8'))
result = jsonpath.jsonpath(jsonObj, '$.data[0,]')
print(result)
import json
import jsonpath
jsonObj = json.load(open('沸点评论.json', 'r', encoding='utf-8'))
result = jsonpath.jsonpath(jsonObj, '$.data[:1]')
print(result)
案例7
在小括号前面加?, 过滤出包含指定属性的数据:
import json
import jsonpath
jsonObj = json.load(open('沸点评论.json', 'r', encoding='utf-8'))
result = jsonpath.jsonpath(jsonObj, '$.data[*]..[?(@.reply_comment_id)]')
print(result)
案例8
过滤出等级大于2的用户:
result = jsonpath.jsonpath(jsonObj, '$.data[*][?(@.level > 2)]')
print(result)
相信通过上面的几个案例,对于jsonpath的使用都有一定的了解了,跟xpath用法是差不多的,多练习几次很快就能熟练使用了。