溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

怎么快速從深層嵌套JSON中找到特定的Key

發(fā)布時間:2021-10-20 10:29:37 來源:億速云 閱讀:97 作者:iii 欄目:web開發(fā)

本篇內(nèi)容介紹了“怎么快速從深層嵌套JSON中找到特定的Key”的有關(guān)知識,在實(shí)際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

怎么快速從深層嵌套JSON中找到特定的Key

在爬蟲開發(fā)的過程中,我們經(jīng)常遇到一些 Ajax 加載的接口會返回 JSON 數(shù)據(jù)。如下圖所示,是 Twitter  的用戶時間線接口,返回了一段3000多行的深層嵌套 JSON:

怎么快速從深層嵌套JSON中找到特定的Key

其中的cursor這個字段,是請求下一頁的必要字段,我必須把它的 value 值讀取出來,拼接到請求 URL 中,才能請求下一頁的內(nèi)容。

現(xiàn)在問題來了,cursor字段在這個 JSON  里面的哪個位置?從最外層開始,我應(yīng)該怎么樣才能讀取到最里面的這個cursor中的value字段的值?

我知道已經(jīng)有一些第三方庫可以直接根據(jù)字段名讀取 JSON  內(nèi)部任意深度的值,不過用別人的東西總沒有自己寫一個輪子來得過癮。所以今天我們自己來手寫一個模塊,我把他叫做JsonPathFinder,傳入一個 JSON  字符串和需要讀取的字段名,返回從最外層開始直到這個字段的路徑。

效果演示

我們用 Python 之父龜叔的 Twitter 時間線來作為演示,運(yùn)行以后,效果如下圖所示:

怎么快速從深層嵌套JSON中找到特定的Key

可以看到,從最外層開始一路讀到cursor字段,需要經(jīng)過非常多的字段名,對應(yīng)到 JSON 中,如下圖所示:

怎么快速從深層嵌套JSON中找到特定的Key

由于entries 字段列表中一共有20個元素,所以這里的18、19實(shí)際上對應(yīng)了倒數(shù)第二條和倒數(shù)第一條數(shù)據(jù)。其中,倒數(shù)第二條的 cursor  對應(yīng)的是本頁第一條推文,而倒數(shù)第一條對應(yīng)的是本頁最后一條推文。所以當(dāng)我們要往后翻頁的時候,應(yīng)該用的是倒數(shù)第一條的 cursor。

我們試著來讀取一下結(jié)果:

怎么快速從深層嵌套JSON中找到特定的Key

非常輕松地獲取到了數(shù)據(jù)。不需要再肉眼在 JSON 中尋找字段了。

原理分析

JsonPathFinder 的原理并不復(fù)雜,全部代碼加上空行,一共只有32行,如下圖所示:

怎么快速從深層嵌套JSON中找到特定的Key

因?yàn)橐粋€字段在 JSON  中可能出現(xiàn)很多次,所以find_one方法返回從外層到目標(biāo)字段的第一條路徑。而find_all方法返回從外層到目標(biāo)字段的所有路徑。

而核心算法,就是iter_node方法。在把 JSON 字符串轉(zhuǎn)成 Python  的字典或者列表以后,這個方法使用深度優(yōu)先遍歷整個數(shù)據(jù),記錄它走過的每一個字段,如果遇到列表就把列表的索引作為  Key。直到遍歷到目標(biāo)字段,或者某個字段的值不是列表也不是字典時結(jié)束本條路徑,繼續(xù)遍歷下個節(jié)點(diǎn)。

代碼第10-15行,分別對列表和字典進(jìn)行處理。對于字典來說,我們分離 key 和 value,寫作:

for key, value in xxx.items():    ...

對于列表,我們分離索引和元素,寫作:

for index, element in enumerate(xxx):    ...

所以如在第11和第13行,使用生成器推導(dǎo)式分別處理字典和列表,這樣得到的key_value_iter生成器對象,就可以在第16行被相同的 for  循環(huán)迭代。

我們知道,在 Python  里面可以迭代的對象除了字典和列表以外,還有很多其他的對象,不過我這里只處理了字典和列表。大家也可以試一試修改10-15行的條件判斷,增加對其他可迭代對象的處理邏輯。

代碼第16-22行,對處理以后的 key-value  進(jìn)行迭代。首先記錄到當(dāng)前字段為止的迭代路徑到current_path列表中。然后判斷當(dāng)前字段是不是目標(biāo)字段。如果是,那么把當(dāng)前的路徑通過 yield  拋出來。如果當(dāng)前路徑的值是列表或者字典,那么把這個值遞歸傳入 iter_node  方法,進(jìn)一步檢查內(nèi)部還有沒有目標(biāo)字段。需要注意的是,無論當(dāng)前字段是不是目標(biāo)字段,只要它的值是列表或者字典,都需要繼續(xù)迭代。因?yàn)榧词巩?dāng)前字段的名字是目標(biāo)字段,但也許它內(nèi)部還有某個子孫字段的字段名也是目標(biāo)字段名。

對于普通函數(shù)來說,要遞歸調(diào)用,直接return 當(dāng)前函數(shù)(參數(shù))就可以了。但是對于生成器來說,要遞歸調(diào)用,就需要使用yield from  當(dāng)前函數(shù)名(參數(shù))。

由于iter_node方法返回的是一個生成器對象,在 find_one和find_all方法中,for  循環(huán)每一次迭代,都能拿到一條從20行拋出來的到目標(biāo)字段的路徑。而在find_one方法中,當(dāng)我們拿到第一條路徑時,不再繼續(xù)迭代,那么就可以節(jié)省大量的時間,減少迭代次數(shù)。

正確使用

有了這個工具以后,我們可以直接用它來解析數(shù)據(jù),也可以用來輔助分析數(shù)據(jù)。例如,Twitter 時間線的正文是在full_text中,我可以直接用  JsonPathFinder 獲取所有的正文:

怎么快速從深層嵌套JSON中找到特定的Key

但有時候,我們除了獲取正文外,還需要每一條推文的其他信息,如下圖所示:

怎么快速從深層嵌套JSON中找到特定的Key

可以看到, 這種情況下,我們可以先獲取從外層到full_text的路徑列表,然后再人工對列表進(jìn)行一些加工,輔助開發(fā):

怎么快速從深層嵌套JSON中找到特定的Key

從打印出來的路徑列表里面可以看到,我們只需要獲取globalObjects->tweets就可以了。它的值是20個字典,每個字典的 Key 是推文的  ID,Value 是推文的詳情。這個時候,我們再人工去修改一下代碼,也能方便地提取一條推文的全部字段。

“怎么快速從深層嵌套JSON中找到特定的Key”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI