赞
踩
Github :https://github.com/json-path/JsonPath
JsonPath 在线解析:https://jsonpath.com/ https://www.jsonpath.cn/
安装 dpath :pip install dpath
- import dpath.util
-
- data = {
- "foo": {
- "bar": {
- "a": 10,
- "b": 20,
- "c": [],
- "d": ['red', 'buggy', 'bumpers'],
- }
- }
- }
-
- print(dpath.util.get(data, "/foo/bar/d"))
JsonPath 是用来提取指定 JSON 文档的部分内容。 许多编程语言都提供的了对 json 的解析。
JsonPath 对于 JSON 来说,相当于 XPath 对于 XML。通过使用 JsonPath 可以方便的查找节点、获取想要的数据,JsonPath 就是 Json版的XPath。
jsonpath 安装:pip install jsonpath
jsonpath-rw:JSONPath 健壮且显著扩展的Python实现,带有一个明确的AST用于元编程。
jsonpath-rw 介绍:https://pypi.org/project/dt-jsonpath-rw/
安装:pip install dt-jsonpath-rw
JsonPath中的 "根成员对象" 总是被引用为 $,不管它是对象还是数组。
JsonPath 使用方法:
- 方法 1:使用 点 表示法:$.store.book[0].title
- 方法 2:使用 括号 表示法:$['store']['book'][0]['title']
JsonPath 中字符串使用单引号表示,例如:$.store.book[?(@.category=='reference')]
"过滤器" 是用于筛选数组的逻辑表达式。一个典型的过滤器应该是 [?(@.age > 18)],其中 @ 表示当前正在处理的项。可以使用逻辑运算符 && 和 || 创建更复杂的过滤器。字符串文字 必须用 单引号 或 双引号 括起来 ([?(@.color == 'blue')] or [?(@.color == "blue")])。
操作符 | 描述 |
---|---|
== | 左边得值 等于 右边的值 ( 注意:数字 1 不等于 字符串 '1' ) |
!= | 不等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
=~ | 匹配正则表达式 [?(@.name =~ /foo.*?/i)] |
in | 左边 in 右边 [?(@.size in ['S', 'M'])] |
nin | 左边 not in 右边 |
subsetof | 左边是右边的一个子字符串 [?(@.sizes subsetof ['S', 'M', 'L'])] |
anyof | 左边和右边相交 [?(@.sizes anyof ['M', 'L'])] |
noneof | 左边和右边不相交 [?(@.sizes noneof ['M', 'L'])] |
size | (数组或字符串)长度 |
empty | (数组或字符串)为空 |
JsonPath 表达式示例:
JsonPath ( 点击链接测试 ) | 结果 |
---|---|
$.store.book[*].author | 获取 Json 中 store下book下的所有author值 |
$..author | 获取 Json 中 所有 author 的值。 |
$.store.* | 获取 store 下所有东西( book 和 bicycle ) |
$.store..price | 获取 store下以及所有子节点下的所有 price |
$..book[2] | 获取 book数组的第3个值 |
$..book[-2] | 获取 book数组的倒数第二个值 |
$..book[0,1] | 获取 book数组的第一、第二的值 |
$..book[:2] | 获取 book数组从索引 0 (包括) 到 索引 2 (不包括) 的所有值 |
$..book[1:2] | 获取 book数组从索引 1 (包括) 到 索引 2 (不包括) 的所有值 |
$..book[-2:] | 获取 book数组从索引 -2 (包括) 到 结尾 的所有值 |
$..book[2:] | 获取 book数组从索引 2 (包括) 到 结尾 的所有值 |
$..book[?(@.isbn)] | 获取 所有节点以及子节点中 book 数组包含 isbn 的所有值 |
$.store.book[?(@.price < 10)] | 获取 store下 book 数组中 price < 10 的所有值 |
$..book[?(@.price <= $['expensive'])] | 获取 所有节点以及子节点下 book 数组中 price <= expensive 的所有值 |
$..book[?(@.author =~ /.*REES/i)] | 获取所有匹配正则的 book ( 不区分大小写 ) |
$..* | 逐层列出 json 中 的所有值,层级由外到内 |
$..book.length() | book 数组的长度 |
代码来源于https://goessner.net/articles/JsonPath/,JSON文档如下:
- {
- "store": {
- "book": [{
- "category": "reference",
- "author": "Nigel Rees",
- "title": "Sayings of the Century",
- "price": 8.95
- }, {
- "category": "fiction",
- "author": "Evelyn Waugh",
- "title": "Sword of Honour",
- "price": 12.99
- }, {
- "category": "fiction",
- "author": "Herman Melville",
- "title": "Moby Dick",
- "isbn": "0-553-21311-3",
- "price": 8.99
- }, {
- "category": "fiction",
- "author": "J. R. R. Tolkien",
- "title": "The Lord of the Rings",
- "isbn": "0-395-19395-8",
- "price": 22.99
- }
- ],
- "bicycle": {
- "color": "red",
- "price": 19.95
- }
- }
- }

示例:
- import jsonpath
-
-
- def learn_json_path():
- book_store = {
- "store": {
- "book": [
- {
- "category": "reference",
- "author": "Nigel Rees",
- "title": "Sayings of the Century",
- "price": 8.95
- },
- {
- "category": "fiction",
- "author": "Evelyn Waugh",
- "title": "Sword of Honour",
- "price": 12.99
- },
- {
- "category": "fiction",
- "author": "Herman Melville",
- "title": "Moby Dick",
- "isbn": "0-553-21311-3",
- "price": 8.99
- },
- {
- "category": "fiction",
- "author": "J. R. R. Tolkien",
- "title": "The Lord of the Rings",
- "isbn": "0-395-19395-8",
- "price": 22.99
- }
- ],
- "bicycle": {
- "color": "red",
- "price": 19.95
- }
- },
- "expensive": 10
- }
- # print(type(book_store))
-
- # 查询store下的所有元素
- print(jsonpath.jsonpath(book_store, '$.store.*'))
-
- # 获取json中store下book下的所有author值
- print(jsonpath.jsonpath(book_store, '$.store.book[*].author'))
-
- # 获取所有json中所有author的值
- print(jsonpath.jsonpath(book_store, '$..author'))
-
- # 获取json中store下所有price的值
- print(jsonpath.jsonpath(book_store, '$.store..price'))
-
- # 获取json中book数组的第3个值
- print(jsonpath.jsonpath(book_store, '$.store.book[2]'))
-
- # 获取所有书
- print(jsonpath.jsonpath(book_store, '$..book[0:1]'))
-
- # 获取json中book数组中包含isbn的所有值
- print(jsonpath.jsonpath(book_store, '$..book[?(@.isbn)]'))
-
- # 获取json中book数组中price<10的所有值
- print(jsonpath.jsonpath(book_store, '$..book[?(@.price<10)]'))
-
-
- if __name__ == '__main__':
- learn_json_path()
-

示例:
- import json
- from jsonpath import jsonpath
-
- data_dict = {
- "family": {
- "parent": "John",
- "children": [
- {"name": "Alice", "age": 10},
- {"name": "Bob", "age": 8},
- {"name": "Charlie", "age": 6},
- {"name": "David", "age": 4}
- ]
- }
- }
- result_list_1 = jsonpath(data_dict, '$..children[?(@.name=="Charlie")]')
- print(result_list_1)
- result_list_2 = jsonpath(data_dict, '$..[?(@.name=="Charlie")]')
- print(result_list_2)

拉勾网城市 JSON 文件 http://www.lagou.com/lbs/getAllCitySearchLabels.json 获取所有城市。
- import json
- import jsonpath
- import requests
-
- url = 'http://www.lagou.com/lbs/getAllCitySearchLabels.json'
-
- custom_headers = {
- "Accept": "*/*",
- "Accept-Encoding": "gzip, deflate, br",
- "Accept-Language": "zh-CN,zh;q=0.9",
- "Cache-Control": "max-age=0",
- "Connection": "keep-alive",
- "Host": "www.lagou.com",
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
- "(KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36"
- }
-
- response = requests.get(url, headers=custom_headers)
- json_obj = json.loads(response.text)
- print(json_obj)
-
- # 从根节点开始,匹配name节点
- city_list = jsonpath.jsonpath(json_obj, '$..name')
- print(city_list)
- print(type(city_list))
-
- # A 下面的节点
- jp = jsonpath.jsonpath(json_obj, '$..A.*')
- print(jp)
-
- # A 下面节点的name
- jp = jsonpath.jsonpath(json_obj, '$..A.*.name')
- print(jp)
-
- # C 下面节点的name
- jp = jsonpath.jsonpath(json_obj, '$..C..name')
- print(jp)
-
- # C 下面节点的第二个
- jp = jsonpath.jsonpath(json_obj, '$..C[1]')
- print(jp)
-
- # C 下面节点的第二个的name
- jp = jsonpath.jsonpath(json_obj, '$..C[1].name')
- print(jp)
-
- # C 下面节点的2到5的name
- jp = jsonpath.jsonpath(json_obj, '$..C[1:5].name')
- print(jp)
-
- # C 下面节点最后一个的name
- jp = jsonpath.jsonpath(json_obj, '$..C[(@.length-1)].name')
- print(jp)
-
- with open('city.json', 'w', encoding='utf-8') as f:
- content = json.dumps(city_list, ensure_ascii=False, indent=4)
- print(content)
- f.write(content)

注意事项:json.loads() 是把 Json 格式字符串解码转换成 Python 对象,如果在 json.loads 的时候出错,要注意被解码的 Json 字符的编码。
如果传入的字符串的编码不是 UTF-8 的话,需要制定字符编码的参数:encoding
jsonpath-ng:https://pypi.org/project/jsonpath-ng/
jsonpath-ng 库可以对 JSON 数据进行复杂查询,包括选择父节点。比 jsonpath 库更强大。
安装:pip install --upgrade jsonpath-ng
$ 根节点。
`this` 当前节点。
`foo` foo 节点。
[ field ] 包含field字段。fieldname 字段名
"fieldname" 同上,如果包含特殊字符,使用引号包括。
'fieldname' 同上
* 任何字段
field , field 指定多个字段,等价于 field | field
[ idx ] 数组访问[*n*]
[start?:end?]
[*]jsonpath1.jsonpath2 在 jsonpath1节点下,查找所有与jsonpath2匹配的子节点
jsonpath[whatever] 等价于 jsonpath.whatever
jsonpath1..jsonpath2 在jsonpath1节点下,查找所有与jsonpath2匹配的子孙节点
jsonpath1 where jsonpath2 匹配 jsonpath1节点有个子节点jsonpath2 的所有节点
jsonpath1 | jsonpath2 匹配 jsonpath1 和 jsonpath2 并集的任何节点
- import json
- from jsonpath_ng import jsonpath
- from jsonpath_ng import parse
- from jsonpath_ng.ext import parse as ext_parse
-
-
- # 假设我们有以下JSON数据
- json_data = json.loads("""
- {
- "store": {
- "book": [
- {
- "title": "Sword of Honour",
- "category": "fiction"
- },
- {
- "title": "Moby Dick",
- "category": "fiction"
- },
- {
- "title": "The Lord of the Rings",
- "category": "fiction"
- }
- ],
- "bicycle": {
- "color": "red",
- "price": 19.95
- }
- }
- }
- """)
-
- # JsonPath 表达式,选择所有category为fiction的book的父节点
- jsonpath_expr = ext_parse("$.store.book[?(@.category=='fiction')].title")
-
- # 执行 JsonPath 查询
- matches = jsonpath_expr.find(json_data)
-
- # 打印出所有符合条件的节点的父节点的标题
- for match in matches:
- print(match.value)

下面一些示例是一种更健壮的方法来创建不依赖于解析器的 JSONPath 表达式。
Root()
Slice(start=0, end=None, step=None)
Fields('foo', 'bar')
Index(42)
Child(Fields('foo'), Index(42))
Where(Slice(), Fields('subfield'))
Descendants(jsonpath, jsonpath)
要使用下面的扩展,必须从 jsonpath_ng.ext 导入。
字符串 的算术运算。操作是使用 python 运算符完成的,并允许 python 允许的类型,如果由于类型不兼容而可以执行操作,则返回 []。
{
'cow': 'foo',
'fish': 'bar'
}cow + fish 返回值为 cowfish
$.cow + $.fish 返回值为 foobar
$.cow + "_" + $.fish 返回值为 foo_bar
$.cow + "_" + fish 返回值为 foo_fish
列表 的 算术运算。如果两个列表的大小相同,则可以对它们使用算术。
{'objects': [
{'cow': 2, 'cat': 3},
{'cow': 4, 'cat': 6}
]}$.objects[\*].cow + $.objects[\*].cat 返回值为 [6, 9]
- from jsonpath_ng import jsonpath, parse
- from jsonpath_ng.jsonpath import Fields
- from jsonpath_ng.jsonpath import Slice
-
- json_dict = {'foo': [{'baz': 1}, {'baz': 2}]}
- # 一个健壮的解析器,而不仅仅是一个正则表达式。
- jsonpath_expr = parse('foo[*].baz')
-
- temp = [match.value for match in jsonpath_expr.find(json_dict)]
- print(temp)
-
- temp = [str(match.full_path) for match in jsonpath_expr.find(json_dict)]
- print(temp)
-
- temp = jsonpath_expr.update(json_dict, 3)
- print(temp)
-
- matches = jsonpath_expr.find(json_dict)
- matches[0].full_path.update(json_dict, 3)
-
- jsonpath_expr.filter(lambda d: True, json_dict)
- jsonpath_expr.filter(lambda d: d == 2, json_dict)
-
- json_dict = {'foo': [{'id': 'bizzle'}, {'baz': 3}]}
- jsonpath.auto_id_field = 'id'
- temp = [match.value for match in parse('foo[*].id').find(json_dict)]
- print(temp)
-
- json_dict = {'a': {'x': {'b': 1, 'c': 'number one'}, 'y': {'b': 2, 'c': 'number two'}}}
- temp = [match.value for match in parse('a.*.b.`parent`.c').find(json_dict)]
- print(temp)
-
- jsonpath_expr_direct = Fields('foo').child(Slice('*')).child(Fields('baz'))

使用 extended parser
from jsonpath_ng.ext import parse
jsonpath_expr = parse('foo[*].baz')
ujson:https://github.com/ultrajson/ultrajson
ujson github 上有各种 json 库对比。一般使用 json 足够,要是追求性能,推荐 ujson
json 类型特征
官网文档:https://docs.python.org/zh-cn/3/library/json.html
json 提供了与标准库 marshal 和 pickle 相似的API接口。
对基本的 Python 对象层次结构进行编码:
- import json
- json.dumps(['foo', {'bar': ('baz', None, 1.0, 2)}])
-
- print(json.dumps("\"foo\bar"))
-
- print(json.dumps('\u1234'))
-
- print(json.dumps('\\'))
-
- print(json.dumps({"c": 0, "b": 0, "a": 0}, sort_keys=True))
-
- from io import StringIO
- io = StringIO()
- json.dump(['streaming API'], io)
- io.getvalue()
'运行
紧凑编码:就是把多余的空格全部删除。有的爬虫请求中就是使用的 紧凑编码
- import json
- json.dumps([1, 2, 3, {'4': 5, '6': 7}], separators=(',', ':'))
'运行
美化输出:
- import json
- print(json.dumps({'4': 5, '6': 7}, sort_keys=True, indent=4))
'运行
JSON解码:
- import json
- json.loads('["foo", {"bar":["baz", null, 1.0, 2]}]')
-
- json.loads('"\\"foo\\bar"')
-
- from io import StringIO
- io = StringIO('["streaming API"]')
- json.load(io)
'运行
命令行使用 json.tool 来验证并美化输出:
数据结构(可以是列表、字典等)转成字符串:dumps()方法:将一个数据结构编码为二进制数据
- import pickle
-
- data_dict = {'name': 'king', 'age': '100'}
- data_dict_list = [
- {'name': 'king', 'age': '100'},
- {'name': 'king', 'age': '100'}
- ]
-
- data_string_1 = pickle.dumps(data_dict)
- print(type(data_string_1))
- print(data_string_1)
-
- data_string_2 = pickle.dumps(data_dict)
- print(type(data_string_2))
- print(data_string_2)
-
- temp = pickle.loads(data_string_2)
- print(type(temp))
- print(temp)
'运行
安装 msgpack :pip install msgpack
msgpack 类型特征
- import msgpack
-
- data_dict = {'name': 'king', 'age': '100'}
- data_dict_list = [
- {'name': 'king', 'age': '100'},
- {'name': 'king', 'age': '100'}
- ]
-
- data_string_1 = msgpack.dumps(data_dict, use_bin_type=True)
- print(type(data_string_1))
- print(data_string_1)
-
- temp_1 = msgpack.loads(data_string_1, use_list=False)
- print(temp_1)
-
- data_string_2 = msgpack.dumps(data_dict_list)
- print(type(data_string_2))
- print(data_string_2)
-

示例:
- import datetime
- import msgpack
-
- useful_dict = {
- "id": 1,
- "created": datetime.datetime.now(),
- }
-
-
- def decode_datetime(obj):
- if b'__datetime__' in obj:
- obj = datetime.datetime.strptime(obj["as_str"], "%Y%m%dT%H:%M:%S.%f")
- return obj
-
-
- def encode_datetime(obj):
- if isinstance(obj, datetime.datetime):
- return {'__datetime__': True, 'as_str': obj.strftime("%Y%m%dT%H:%M:%S.%f")}
- return obj
-
-
- packed_dict = msgpack.packb(useful_dict, default=encode_datetime, use_bin_type=True)
- this_dict_again = msgpack.unpackb(packed_dict, object_hook=decode_datetime, raw=False)
-
- print(packed_dict)
- print(this_dict_again)

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。