Json簡介
Json(JavaScript Object Notation)
很多網站都會用到Json格式來進行資料的傳輸和交換。
這因為Json是一種輕量級的資料交換格式,具有資料格式簡單,讀寫友善易懂等很多優點。用它來進行前後端的資料傳輸,大大的簡化了伺服器和用戶端的開發工作量。
而且相對于XML來說,更加的輕量級,更友善解析。
今天我們講講如何在python裡玩轉Json資料?
在Json中,遵循“key-value”的這樣一種方式。
比如最簡單的這種:“{"name" : "zhuxiao5"}”,跟python 裡的字典似的,也是一個Json格式的資料。
複雜一點的比如這種(後文會多次使用到這個例子):
{
"animals": {
"dog": [
{
"name": "Rufus",
"age":15
},
{
"name": "Marty",
"age": null
}
]
}
}
以上圖為例,再多說幾句Json格式的特點
- 對象通過鍵值對表現;
- 鍵通過雙引号包裹,後面跟冒号“:”,然後跟該鍵的值;
- 值可以是字元串、數字、數組等資料類型;
- 對象與對象之間用逗号隔開;
- “{}”用來表達對象;
- “[]”用來表達數組;
Python中的Json子產品
Python中也自帶了Json子產品,其中json.dumps()、json.loads()較為常用。
json.dumps() 是将 python 對象轉化為 json。
json.loads() 是将 json 轉化為 python 對象。
#json.dumps(),json.loads()
import json
dict_data = {"a": 1, "b": 2}
# 将dict格式資料轉換成json格式字元串
dump_data = json.dumps(dict_data)
# 将json格式字元串轉換成對應的python值
load_data = json.loads(dump_data)
# 列印轉換結果
print(type(dict_data),dict_data)
print(type(dump_data),dump_data)
print(type(load_data),load_data)
運作結果:
<class 'dict'> {'a': 1, 'b': 2}
<class 'str'> {"a": 1, "b": 2}
<class 'dict'> {'a': 1, 'b': 2}
在例子中一開始的變量 dict_data 是一個字典,json.dumps() 後,将dict格式資料轉換成json格式字元串。這時候雖然都是{'a': 1, 'b': 2},但是格式卻前後不一樣。随後又通過 json.loads(),重新将json格式字元串轉換成字典。
線上解析Json
在實際應用中,要 提取json資料,就要了解傳回json資料的結構。
可是Json格式的資料往往是這樣的。
大家别擔心,我們可以将資料複制到一些json插件或線上解析!
比如這個插件是小五常用的:
此時再打開剛才的網址
是不是清晰了很多呢?
如果用python來擷取裡面的資料怎麼做的?
先利用 json.loads() 來将 Json 轉成字典,再用 get() 函數直到得到我們想要的list 對象,那麼對于 list 裡面的資料我們用個 for 循環就行啦~
額,有點繞。
還是文章一開始的例子,我們想擷取其中所有狗狗的名字:
{
"animals": {
"dog": [
{
"name": "Rufus",
"age":15
},
{
"name": "Marty",
"age": null
}
]
}
}
我們可以這樣做:
load_data = json.loads(dump_data)
data = load_data.get("animals").get("dog")
result1 = []
for i in data:
result1.append(i.get("name"))
print(result1)
運作結果:
['Rufus', 'Marty']
這樣确實可以獲得我們想要的結果。
PS:類似的線上解析網站也有很多,比如 https://www.json.cn 。
JsonPath
不知道大家還記不記得,在一開始介紹Json時,我提到了它相對于XML來說,更加的輕量級,更友善解析。
既然 XML 人家都有 XPATH ,那麼Json有沒有類似的工具呢?
JsonPath 是一種資訊抽取類庫,是從Json文檔中抽取指定資訊的工具。
JsonPath 對于 Json 來說, 相當于 XPATH 對于 XML。
Json結構清晰,可讀性高,複雜度低,非常容易比對,下表是JsonPath的用法。
沒錯,還是這個例子,我們這次嘗試用 JsonPath 擷取其中所有狗狗的名字:
{
"animals": {
"dog": [
{
"name": "Rufus",
"age":15
},
{
"name": "Marty",
"age": null
}
]
}
}
我們可以這樣做:
load_data = json.loads(dump_data)
jobs=load_data['animals']['dog']
result2 = []
for i in data:
# 從根節點開始,比對name節點
result2.append(jsonpath.jsonpath(i,'$..name')[0])
print(result2)
其中 $..name 代表從根節點開始,比對name節點
運作結果:
['Rufus', 'Marty']
利用 JsonPath 同樣可以獲得我們想要的結果。
我們在後續執行個體演練中将繼續采用 JsonPath 來抽取資料。
執行個體演練
示例:我們利用
網易雲音樂評論API來生成Json資料,并從中擷取熱評資料。
http://music.163.com/api/v1/resource/comments/R_SO_4_483671599?limit=10&offset=0
在浏覽器(已安裝Json解析插件)中打開:
标紅區域的資料是我們本次想要擷取的。
def get_comments(url):
data = []
doc = get_json(url)
jobs=doc['hotComments']
for job in jobs:
dic = {}
#從根節點開始,比對content節點
dic['content']=jsonpath.jsonpath(job,'$..content')[0] #評論
dic['time']= stampToTime(jsonpath.jsonpath(job,'$..time')[0]) #時間
dic['userId']=jsonpath.jsonpath(job['user'],'$..userId')[0] #使用者ID
dic['nickname']=jsonpath.jsonpath(job['user'],'$..nickname')[0]#使用者名
dic['likedCount']=jsonpath.jsonpath(job,'$..likedCount')[0] #贊數
data.append(dic)
return pd.DataFrame(data)
final_result = get_comments('http://music.163.com/api/v1/resource/comments/R_SO_4_483671599?limit=10&offset=0')
(完整代碼見文末下載下傳位址)
運作結果:
成功擷取√
希望本文能讓大家以後玩轉Json資料更輕松~