使用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資料的方式,如果有錯誤或不足之處歡迎指正