21 JSONP

发布时间 2023-10-12 20:15:33作者: 生而自由爱而无畏

JSONP

为了解决浏览器跨域问题. jquery提供了jsonp请求.

在网页端如果见到了服务器返回的数据是:

​ xxxxxxxxxxdjsfkldasjfkldasjklfjadsklfjasdlkj({json数据})

​ 在Preview里面可以像看到json一样去调试

這就是jsonp。 这东西依然是ajax.

jsonp的逻辑是. 在发送请求的时候. 带上一个callback字符串. 该字符串自动发送给服务器. 服务器返回数据的时候. 会带上该callback字符串. 我们在抓包中看到的就是这样的效果:

image-20220609173715291

在Python中. 接下来, 我们还原一下该效果.

首先, 在flask中. 必须接收到前端返回的callback, 然后在返回数据的时候. 需要用前端返回的callback字符串. 将数据包裹

@app.route("/process_jsonp", methods=["GET"])
def process_jsonp():
    # 获取回调字符串
    cb = request.args.get("cb")
    print(cb)
    data = {
        "name": "alex",
        "age": 18
    }
    import json
    #      用回调字符串将真实要返回的数据包裹起来
    #      如果不包裹起來。前端ajax中的success将无法获取到数据
    return cb + "("+json.dumps(data)+")"

在发送ajax的时候. 需要指定dataType为jsonp, 以及自由配置回调函数的参数名

$(function(){
    $.ajax({
        url: "/process_jsonp",
        method:"get",
        // 典型, 京东.
        dataType: "jsonp", // 它的执行逻辑是. 请求服务上的一个js. 然后会自动执行该js.将js函数内的东西. 丢给success
        jsonp:"cb", // 传递给服务器的时候. 自动带上cb=xxxxxx  服务器端接收cb即可
        success: function(data){ // 此时data可以直接收取到数据
            console.log(data);
        }
    });
});

抓包效果:

image-20220609174324528

服务器处理cb时的效果:

image-20220609174352852

抓包中. 看到的服务器返回的数据

image-20220609174419304

success中接收到的数据效果

image-20220609174441431

我们以后见到这种网站. 如何处理?

首先, 固定好callback的值. 如上述案例. 我们就可以直接给出一个固定的cb值. 如果原网站就是固定的值. 此步骤可以忽略

http://127.0.0.1:5000/process_jsonp?cb=haha&_=1654767783595

然后, 得到返回值后. 用正则. 或者字符串操作. 即可处理.

import requests
import re

url = "http://127.0.0.1:5000/abc"
params = {
    "callback": "jQuery36002530792718956838_1681908950457",
    "_": "1681908950461"  # 它是为了防止浏览器缓存的. 实际上和服务器无关
}

resp = requests.get(url, params=params)
# 自己的服务器随便搞

print(resp.text)
# 如何提取jsonp中有用的数据
obj = re.compile(r'\((?P<code>.*)\)')  # 1
code = obj.search(resp.text).group("code")
print(code)
# 后续处理用, json或者execjs来处理成python的dict.