Python獲取jsonp資料

'Radio'發表於2023-05-09

使用python爬取資料時,有時候會遇到jsonp的資料格式,由於不是json的,所以不能直接使用json.loads()方法來解析,需要先將其轉換為json格式,再進行解析。在前面講了jsonp的原理 ,這裡就略過一部分。

jsonp的格式

jsonp的內容一般是這樣的:

callback({
    "name":"zhangsan",
    "age":18
})

也有有可能是這樣的:

callback(
    'name',
    (function(a,b,c){
        return {
            name:a,
            age:b,
            gender:c
        }
    })('孫悟空',18,'男')
)

這裡的callback就是一個函式名,這個函式名是由後端返回的,我們需要將這個函式名提取出來,然後將其替換為一個我們自己定義的函式名,然後再將其轉換為json格式,再進行解析。

這個函式名一般會包含在get請求的引數中,例如:

<script src="xxx.xxx?callback=cb"></script>

在這個url中,callback=cb是我們傳給伺服器的引數,我們可以理解為告訴伺服器我們需要將資料傳入cb這個函式中,然後伺服器返回的資料就會以cb(data)的形式返回,例如:

cb({
    "name":"zhangsan",
    "age":18
})
獲取資料
方法一

通常情況下伺服器返回的資料呼叫哪個函式由傳遞的callback引數決定,如果我們將callback的引數改為我們自己定義的函式名,那麼伺服器就會返回這個函式名。
因此,我們也可以嘗試將callback引數填寫為空,例如:

import requests
requests.get('xxx.xxx?callback=')

這樣伺服器就會直接返回資料而不是用函式包裹

方法二

透過字串切片或者正規表示式來提取資料,例如:


import requests
import re
res = requests.get('xxx.xxx?callback=cb')
# 正規表示式提取
data = re.search('cb\((.*?)\)',res).group(1)
# 字串切片提取
data = res[3:-1] 
方法三

使用subprocess庫執行js程式碼,但是jsonp返回的資料中只有一個呼叫函式的程式碼,因此我們需要提前定義一個函式,並將內容寫入js檔案後執行,例如:

import requests
import subprocess

cb_data = requests.get('xxx.xxx?callback=cb').text
# 定義一個函式
js = '''   
function cb(data) {
    console.log(data);
}
'''
# 將函式寫入js檔案
with open('jsonp.js','w',encoding='utf-8') as f:
    f.write(js+cb_data)

# 執行js檔案的同時捕獲列印資訊
result = subprocess.run('node jsonp.js',shell=True,stout=subprocess.PIPE)
# 將結果轉換為json
json = json.loads(res.stdout.decode())
""" json轉換時可能會出錯,因此可以在定義的函式中將console.log(data) 修改為 console.log( JSON.stringify(data)) """
# 列印轉換後的內容
print(json)

以上,簡單的介紹了三種獲取jsonp資料的方式,如果有錯誤或不足之處歡迎指正

相關文章