JSONP

目录

同源策略介绍

验证同源策略

解决同源策略

网上实例

同源策略介绍

基于安全的原因,浏览器是存在同源策略机制的,同源策略阻止从一个源加载的文档或脚本获取或设置另一个源加载的文档的属性。

 

验证同源策略

from django.shortcuts import render,HttpResponse
from django.views import View
import json


class Index(View):
    def get(self,request):
        data = {"a":1,"b":2,"c":"中国"}
        return HttpResponse(json.dumps(data))
python模拟服务器端
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">

    <script src="jquery.js"></script>
    <script>

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
</body>

</html>
在本地新建一个html文件,调用远程资源

 

解决同源策略

服务器端直接添加Access-Control-Allow-Origin字段

from django.shortcuts import render,HttpResponse
from django.views import View
import json


class Index(View):
    def get(self,request):
        data = {"a":1,"b":2,"c":"中国"}
        ret = HttpResponse(json.dumps(data))

        # 在头部添加Access-Control-Allow-Origin字段为*,在源头允许跨域,测试有效
        print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
        ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
        print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}

        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">

    <script src="jquery.js"></script>
    <script>

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
</body>

</html>
test.html

使用script的src字段绕过同源策略

简单使用script的src字段

from django.shortcuts import render,HttpResponse
from django.views import View
import json


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中国"}
#         ret = HttpResponse(json.dumps(data))
#
#         # 在头部添加Access-Control-Allow-Origin字段为*,在源头允许跨域,测试有效
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
#         ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}
#
#         return ret


class Index(View):
    def get(self,request):
        data = {"a":1,"b":2,"c":"中国"}

        ret = HttpResponse(json.dumps(data))
        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">
    <input type="button" id="btn2" value="btn2">


    <script src="jquery.js"></script>
    <script>
    

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
    
        <script>

        function CreateScript(src) {
            var Scrip=document.createElement('script');  // 创建script标签
            Scrip.src=src;  // 设置script的src属性
            document.body.appendChild(Scrip);
        }

        $('#btn2').click(function(){
            console.log("btn2");
            CreateScript("http://127.0.0.1:8000/jsonp/index/")
        })
    </script>
</body>

</html>
test.html

原因分析

  • 添加标签:<script src="http://127.0.0.1:8000/jsonp/index/"></script>
  • 经过服务端返回数据{"a": 1, "b": 2, "c": "\u4e2d\u56fd"},浏览器将其解析为html语言出现错误,非数据,比如返回的是字符串“abc”,但浏览器会解析为abc对象。
  • 浏览器不知道怎么处理这些返回来的html代码

解决方法

  • 如果返回的数据是"func("abc")",那么浏览器就会找到func函数对字符串“abc”进行处理

自定义方法,使用script的src字段,返回带有callback方法的数据

from django.shortcuts import render,HttpResponse
from django.views import View
import json


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中国"}
#         ret = HttpResponse(json.dumps(data))
#
#         # 在头部添加Access-Control-Allow-Origin字段为*,在源头允许跨域,测试有效
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
#         ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}
#
#         return ret


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中国"}
#
#         ret = HttpResponse(json.dumps(data))
#         return ret


class Index(View):
    def get(self,request):
        callback= request.GET.get("callback")
        data = {"a":1,"b":2,"c":"中国"}

        data = '{func}({data})'.format(func=callback,data=data)
        # data = '{func}("{data}")'.format(func=callback,data=data)  # 如果是字符串,则需要加双引号

        ret = HttpResponse(data)
        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">
    <input type="button" id="btn2" value="btn2">


    <script src="jquery.js"></script>
    <script>
    

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
    
        <script>

        function CreateScript(src) {
            var Scrip=document.createElement('script');  // 创建script标签
            Scrip.src=src;  // 设置script的src属性
            document.body.appendChild(Scrip);
        }
        function myjsonpcallback(data) {
            console.log("==================jsonpcallback==================")
            console.log(data)
        }

        $('#btn2').click(function(){
            console.log("btn2");
            // CreateScript("http://127.0.0.1:8000/jsonp/index/")
            CreateScript("http://127.0.0.1:8000/jsonp/index/?callback=myjsonpcallback")
        })
    </script>
</body>

</html>
test.html

直接使用ajax自带的jsonp,返回带有callback方法的数据

from django.shortcuts import render,HttpResponse
from django.views import View
import json


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中国"}
#         ret = HttpResponse(json.dumps(data))
#
#         # 在头部添加Access-Control-Allow-Origin字段为*,在源头允许跨域,测试有效
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
#         ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}
#
#         return ret


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中国"}
#
#         ret = HttpResponse(json.dumps(data))
#         return ret


class Index(View):
    def get(self,request):
        callback= request.GET.get("callback")
        data = {"a":1,"b":2,"c":"中国"}

        data = '{func}({data})'.format(func=callback,data=data)
        # data = '{func}("{data}")'.format(func=callback,data=data)  # 如果是字符串,则需要加双引号

        ret = HttpResponse(data)
        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">
    <input type="button" id="btn2" value="btn2">
    <input type="button" id="btn3" value="btn3">


    <script src="jquery.js"></script>
    <script>
    

        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
    
    <script>

        function CreateScript(src) {
            var Scrip=document.createElement('script');  // 创建script标签
            Scrip.src=src;  // 设置script的src属性
            document.body.appendChild(Scrip);
        }
        function myjsonpcallback(data) {
            console.log("==================jsonpcallback==================")
            console.log(data)
        }

        $('#btn2').click(function(){
            console.log("btn2");
            // CreateScript("http://127.0.0.1:8000/jsonp/index/")
            CreateScript("http://127.0.0.1:8000/jsonp/index/?callback=myjsonpcallback")
        })
    </script>
    <script>
        function myjsonpcallback(data) {
            console.log("==================jsonpcallback==================")
            console.log(data)
        }
    
        $(document).ready(function(){
                $("#btn3").click(function(){
                    console.log("btn3");
                    $.ajax({
                        type:"GET",
                        url:"http://127.0.0.1:8000/jsonp/index/",
                        dataType:"jsonp",
                        jsonp:"callback",  //此为URL上的参数,url?callback=myjsonpcallback,可修改,比如jsonp:cb,则变为url?cb=myjsonpcallback
                        jsonpCallback:"myjsonpcallback",  // 回调函数名称
                        success:function(data){
                            console.log("==================success==================")
                            console.log(data)
                        }
                    })
                })
            }
        )

    </script>

    
    
</body>

</html>
test.html

完整版

from django.shortcuts import render,HttpResponse
from django.views import View
import json


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中国"}
#         ret = HttpResponse(json.dumps(data))
#
#         # 在头部添加Access-Control-Allow-Origin字段为*,在源头允许跨域,测试有效
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8')}
#         ret._headers["Access-Control-Allow-Origin"] = ("Access-Control-Allow-Origin","*")
#         print(ret._headers)  # {'content-type': ('Content-Type', 'text/html; charset=utf-8'), 'Access-Control-Allow-Origin': ('Access-Control-Allow-Origin', '*')}
#
#         return ret


# class Index(View):
#     def get(self,request):
#         data = {"a":1,"b":2,"c":"中国"}
#
#         ret = HttpResponse(json.dumps(data))
#         return ret


# class Index(View):
#     def get(self,request):
#         callback= request.GET.get("callback")
#         data = {"a":1,"b":2,"c":"中国"}
#
#         data = '{func}({data})'.format(func=callback,data=data)
#         # data = '{func}("{data}")'.format(func=callback,data=data)  # 如果是字符串,则需要加双引号
#
#         ret = HttpResponse(data)
#         return ret


class Index(View):
    def get(self,request):
        callback= request.GET.get("callback")
        # data = "abcd"
        data = {"a":1,"b":2,"c":"中国"}
        # data = [1,2,"中国","a"]

        if isinstance(data,str):
            data = '{func}("{data}")'.format(func=callback,data=data)
        else:
            data = '{func}({data})'.format(func=callback,data=data)

        ret = HttpResponse(data)
        return ret
python views.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>


</head>
<body>
    <h1>haha</h1>

    <input type="button" id="btn1" value="btn1">
    <input type="button" id="btn2" value="btn2">
    <input type="button" id="btn3" value="btn3">

    <hr>
    <textarea id="text" style="width: 400px; height: 100px;"></textarea>

    
    
    <script src="jquery.js"></script>
    
    <script>
        function myjsonpcallback(data) {
            console.log("==================jsonpcallback==================")
            console.log(data)
            $("#text").val(data)
        }
    </script>
    
    <script>
        $("#btn1").click(function () {
            console.log("btn1");
            $.ajax({
                type:"GET",
                url:"http://127.0.0.1:8000/jsonp/index/",
                success:function(msg){
                    console.log(msg)
                }
            })
        });
    </script>
    
    <script>
        // 自定义方法,使用script的src字段,返回带有callback方法的数据
        
        function CreateScript(src) {
            var Scrip=document.createElement('script');  // 创建script标签
            Scrip.src=src;  // 设置script的src属性
            document.body.appendChild(Scrip);
        }

        $('#btn2').click(function(){
            console.log("btn2");
            // CreateScript("http://127.0.0.1:8000/jsonp/index/")
            CreateScript("http://127.0.0.1:8000/jsonp/index/?callback=myjsonpcallback")
        })
    </script>
    
    <script>
        // 直接使用ajax自带的jsonp,返回带有callback方法的数据
    
        $(document).ready(function(){
                $("#btn3").click(function(){
                    console.log("btn3");
                    $.ajax({
                        type:"GET",
                        url:"http://127.0.0.1:8000/jsonp/index/",
                        dataType:"jsonp",
                        jsonp:"callback",  //此为URL上的参数,url?callback=myjsonpcallback,可修改,比如jsonp:cb,则变为url?cb=myjsonpcallback
                        jsonpCallback:"myjsonpcallback",  // 回调函数名称
                        success:function(data){
                            console.log("==================success==================")
                            console.log(data)
                        }
                    })
                })
            }
        )

    </script>

    
    
</body>

</html>
test.html

网上实例

百度搜索框

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    *{margin: 0px;padding: 0px;}
    #sch{width:200px;margin: 50px auto;}
    #tex{width: 200px;height: 20px;}
    ul{border: 1px solid #eee;width: 202px;display: inline-block;}
    ul li{list-style: none;border: 1px solid #ddd;width:200px;height: 20px;text-align: left;line-height: 20px;}
    ul li:hover{background: orange;}
    </style>
</head>
<body>
    <div id = 'sch'>
        <input type="text" placeholder='请输入关键字' id = 'tex'>
        <ul id="test_ul">
            <!-- <li>1</li>
            <li>2</li>
            <li>3</li>
            <li>4</li> -->
        </ul>
    </div>

    <script src="../../static/jquery.js"></script>



    <script>
        // 定义回调函数
        function testcb(data){
            var result = data["s"]
            $.each(result,function(index,item){
                $("<li>").html(item).appendTo("#test_ul")
            });
        }
    </script>

    <script>
        // jsonp获取数据
        function getData(keyword){
            var params = {'wd': keyword,
                'p': '3',
                //'cb': 'testcb',
                "req":2,
                "sid":"1426_21116_22074",
                "json":1,
                "csor":1,};
            $.ajax({
                async: false,
                //url: "http://suggestion.baidu.com/su",
                url: "https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su",
                type: "GET",
                dataType: 'jsonp',
                jsonp: 'cb',
                jsonpCallback:"testcb",
                data: params,
                timeout: 5000,
                success: function (json) {
                    console.log(json)
                },
                error: function (xhr) {
                }
            });

        }
    </script>

    <script>
        /* 使用input,keyup等都行
        $("#tex").input(function(){
            var mykeyword = $("#tex").val()
            if(mykeyword.length > 0){
                getData(mykeyword)
            }
        })
        */
        $("#tex").on("input",function(){
            $("#test_ul").empty()
            var mykeyword = $("#tex").val();
            if (mykeyword.length>0){
                getData(mykeyword)
            }
        })
    </script>


    <script>
        // 网上其他人的做法
        /*
        var oTex = document.getElementById('tex');
        var oUl = document.getElementsByTagName('ul')[0];
        function baiduSU(data){
            var d = data.s
            if(d.length){
                oUl.style.display = 'block';
                var str = '';
                for(var i =0;i<d.length;i++)
            {
                str += '<li>'+d[i]+'</li>'
            }
            oUl.innerHTML = str;
            }else{
                oUl.style.display = 'none';
            }
        }



        oTex.onkeyup = function()
        {
            if(oTex.value != '')
            {
                var oScript = document.createElement('script');
                oScript.src = 'http://unionsug.baidu.com/su?wd='+oTex.value+'&cb=baiduSU';
                document.body.appendChild(oScript);
            }else{
                oUl.style.display = 'none';
            }
        }
        */
    </script>

</body>
</html>
baidu.html

过程

图中的url应该是会变的,后面使用python爬取该url

结果

爬取url

import requests
import re

url = "https://www.baidu.com"
method = "GET"
headers = {
    "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0",
}
params = {}

req = requests.request(method=method,url=url,params=params,headers=headers)

target = re.search("sugHost : (.+?),",req.text)
print(target.group(1)[1:-1])  # https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su
爬取url.py

 

参考or转发

http://www.cnblogs.com/oppoic/p/baidu_auto_complete.html

posted @ 2018-09-27 18:28  fat39  阅读(521)  评论(0编辑  收藏  举报