Python 中使用 jsonpath
JSONPath 解析 JSON 內(nèi)容詳解(翻譯自 github):https://blog.csdn.net/freeking101/article/details/103048514
JSONPath Online Evaluator:http://jsonpath.com
Python 處理 JSON 我選擇 ujson 和 orjson:https://blog.csdn.net/weixin_40247412/article/details/109302522
一、jsonpath
1. jsonpath介紹
用來解析多層嵌套的 json 數(shù)據(jù);JsonPath 是一種信息抽取類庫(kù),是從 JSON 文檔中抽取指定信息的工具,提供多種語(yǔ)言實(shí)現(xiàn)版本,包括:Javascript, Python, PHP 和 Java。
使用方法:
import jsonpathres=jsonpath.jsonpath(dic_name,'$..key_name') # 嵌套 n 層也能取到所有 key_name 信息, # 其中:“$”表示最外層的{}, # “..”表示模糊匹配,當(dāng)傳入不存在的 key_name時(shí),程序會(huì)返回false2. JsonPath 對(duì)于 JSON 來說,相當(dāng)于 XPath 對(duì)于 XML
jsonpath 安裝:pip install jsonpath
官方文檔:http://goessner.net/articles/JsonPath
jsonpath-rw:JSONPath 的一個(gè)健壯且顯著擴(kuò)展的Python實(shí)現(xiàn),帶有一個(gè)明確的AST用于元編程。
jsonpath-rw 介紹:https://pypi.org/project/jsonpath-rw/
jsonpath-rw 安裝:pip install?jsonpath-rw
3. JsonPath 與 XPath 語(yǔ)法對(duì)比:
Json 結(jié)構(gòu)清晰,可讀性高,復(fù)雜度低,非常容易匹配,下表中對(duì)應(yīng)了XPath 的用法。
對(duì)比:
Python 使用示例:
# 使用格式: jsonpath.jsonpath(匹配的字典,'jsonpath表達(dá)式')# 找 d字典下面所有的name對(duì)應(yīng)的值,返回一個(gè)列表 res2 = jsonpath.jsonpath(d,'$..name')示例:
import jsonpathdef 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數(shù)組的第3個(gè)值print(jsonpath.jsonpath(book_store, '$.store.book[2]'))# 獲取所有書print(jsonpath.jsonpath(book_store, '$..book[0:1]'))# 獲取json中book數(shù)組中包含isbn的所有值print(jsonpath.jsonpath(book_store, '$..book[?(@.isbn)]'))# 獲取json中book數(shù)組中price<10的所有值print(jsonpath.jsonpath(book_store, '$..book[?(@.price<10)]'))if __name__ == '__main__':learn_json_path()4. 使用實(shí)例
示例代碼 1:
d={"error_code": 0,"stu_info": [{"id": 2059,"name": "小白","sex": "男","age": 28,"addr": "河南省濟(jì)源市北海大道32號(hào)","grade": "天蝎座","phone": "18378309272","gold": 10896,"info":{"card":434345432,"bank_name":'中國(guó)銀行'}},{"id": 2067,"name": "小黑","sex": "男","age": 28,"addr": "河南省濟(jì)源市北海大道32號(hào)","grade": "天蝎座","phone": "12345678915","gold": 100}] }res= d["stu_info"][1]['name'] #取某個(gè)學(xué)生姓名的原始方法:通過查找字典中的key以及l(fā)ist方法中的下標(biāo)索引 print(res) #輸出結(jié)果是:小黑import jsonpath res1=jsonpath.jsonpath(d,'$..name') #嵌套n層也能取到所有學(xué)生姓名信息,$表示最外層的{},..表示模糊匹配 print(res1) #輸出結(jié)果是list:['小白', '小黑']res2= jsonpath.jsonpath(d,'$..bank_name') print(res2) #輸出結(jié)果是list:['中國(guó)銀行']res3=jsonpath.jsonpath(d,'$..name123') #當(dāng)傳入不存在的key(name)時(shí),返回False print(res3) #輸出結(jié)果是:False示例代碼 2:
以拉勾網(wǎng)城市 JSON 文件?http://www.lagou.com/lbs/getAllCitySearchLabels.json 為例,獲取所有城市。
import json import jsonpath import requestsurl = '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)# 從根節(jié)點(diǎn)開始,匹配name節(jié)點(diǎn) city_list = jsonpath.jsonpath(json_obj, '$..name') print(city_list) print(type(city_list))# A 下面的節(jié)點(diǎn) jp = jsonpath.jsonpath(json_obj, '$..A.*') print(jp)# A 下面節(jié)點(diǎn)的name jp = jsonpath.jsonpath(json_obj, '$..A.*.name') print(jp)# C 下面節(jié)點(diǎn)的name jp = jsonpath.jsonpath(json_obj, '$..C..name') print(jp)# C 下面節(jié)點(diǎn)的第二個(gè) jp = jsonpath.jsonpath(json_obj, '$..C[1]') print(jp)# C 下面節(jié)點(diǎn)的第二個(gè)的name jp = jsonpath.jsonpath(json_obj, '$..C[1].name') print(jp)# C 下面節(jié)點(diǎn)的2到5的name jp = jsonpath.jsonpath(json_obj, '$..C[1:5].name') print(jp)# C 下面節(jié)點(diǎn)最后一個(gè)的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)注意事項(xiàng):
json.loads() 是把 Json 格式字符串解碼轉(zhuǎn)換成 Python 對(duì)象,如果在 json.loads 的時(shí)候出錯(cuò),要注意被解碼的 Json 字符的編碼。
如果傳入的字符串的編碼不是 UTF-8 的話,需要制定字符編碼的參數(shù):encoding
dataJsonStr 是 JSON 字符串,假設(shè)其編碼本身是非 UTF-8 的話而是 GBK 的,那么上述代碼會(huì)導(dǎo)致出錯(cuò),改為對(duì)應(yīng)的。
dataDict = json.loads(jsonStrGBK, encoding="GBK")如果 dataJsonStr 通過 encoding 指定了合適的編碼,但是其中又包含了其它編碼的字符,則需要先去將 dataJsonStr 轉(zhuǎn)換為Unicode,然后再指定編碼格式調(diào)用 json.loads()
dataJsonStrUni = data.JsonStr.decode("GB2312") dataDict = json.loads(dataJsontrUni, encoding="GB2312")字符串編碼轉(zhuǎn)換
其實(shí)編碼問題很好搞定,只要記住一點(diǎn):任何平臺(tái)的任何編碼,都能和Unicode互相轉(zhuǎn)換。UTF-8 與 GBK 互相轉(zhuǎn)換,那就先把 UTF-8 轉(zhuǎn)換成 Unicode,再?gòu)?Unicode 轉(zhuǎn)換成 GBK,反之同理。
# 這是一個(gè) UTF-8 編碼的字符串 utf8Str = "你好地球"# 1. 將 UTF-8 編碼的字符串 轉(zhuǎn)換成 Unicode 編碼 unicodeStr = utf8Str.decode("UTF-8")# 2. 再將 Unicode 編碼格式字符串 轉(zhuǎn)換成 GBK 編碼 gbkData = unicodeStr.encode("GBK")# 1. 再將 GBK 編碼格式字符串 轉(zhuǎn)化成 Unicode unicodeStr = gbkData.decode("gbk")# 2. 再將 Unicode 編碼格式字符串轉(zhuǎn)換成 UTF-8 utf8Str = unicodeStr.encode("UTF-8")- decode: 的作用是將其它編碼的字符串轉(zhuǎn)換成 Unicode 編碼
- encode :的作用是將 Unicode 編碼轉(zhuǎn)換成其他編碼的字符串
- 一句話:UTF-8 是對(duì) Unicode 字符集記性編碼的一種編碼格式
二、Python 序列化之 json、pickle、msgpack 之 dumps、loads 區(qū)別于用法
Python 之 Json 模塊
json 類型特征
- json 是一種通用的數(shù)據(jù)類型,一般情況下接口返回的數(shù)據(jù)類型都是json
- 長(zhǎng)得像 Python 字典,形式也是?k-v
- 其實(shí) json 是字符串
- 字符串不能用 key、value 來取值,所以要先轉(zhuǎn)換為 Python 的字典才可以
示例:
import jsontest_str = ''' {"noticeLoginFlag": "1","ticket_id": "gh_45679b88e7a","pgv_si": "s29623456176","pgv_pvi": "1328457192" } '''data_dict = json.loads(test_str) print(data_dict) # 打印字典 print(type(data_dict)) # 打印 data_dict 類型 print(list(data_dict.keys())) # 打印字典的所有keydata_string = json.dumps(data_dict, indent=4, ensure_ascii=False) print(type(data_string)) print(data_string)Python 之 simplejson 模塊
simplejson 更輕量級(jí),使用方法完全與 json 相同
Python 之 pickle 模塊
pickle 類型特征
- pickle 模塊用于實(shí)現(xiàn) 序列化 和 反序列化。
- 序列化 dumps 可以將 list、dict 等數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化為二進(jìn)制
- 反序列化 loads 可以將字符串轉(zhuǎn)化為 list、dict
數(shù)據(jù)結(jié)構(gòu)(可以是列表、字典等)轉(zhuǎn)成字符串:dumps()方法:將一個(gè)數(shù)據(jù)結(jié)構(gòu)編碼為二進(jìn)制數(shù)據(jù)
import pickledata_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)Python 之 msgpack 模塊
安裝?msgpack :pip install msgpack
msgpack 類型特征
- msgpack 是一種有效的二進(jìn)制序列化格式。它使您可以在多種語(yǔ)言(如JSON)之間交換數(shù)據(jù)。但是它更快,更小。
- 序列化 packb 可以將 list、dict 等數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)化為二進(jìn)制 ( packb 別名為 dumps )
- 反序列化 loads 可以將字符串轉(zhuǎn)化為 list、dict ( unpackb 別名為 loads )
示例:
import datetime import msgpackuseful_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 objdef encode_datetime(obj):if isinstance(obj, datetime.datetime):return {'__datetime__': True, 'as_str': obj.strftime("%Y%m%dT%H:%M:%S.%f")}return objpacked_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)總結(jié)
以上是生活随笔為你收集整理的Python 中使用 jsonpath的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 替换字符串中的空格
- 下一篇: Python3.2+ 的 concurr