• python---web微信开发


    一:轮询,长轮询,WebSocket了解

    轮询:

    在前端,设置时间内,一直向后端发送请求。
    例如:使用setInterval方法设置定时器,一秒向后端发送一次请求,去主动获取数据,进行更新
    由于前端一直请求,后端压力太大。而且当没有数据更新,前端一直去请求,太浪费了,没必要。
    代码简单

    长轮询:

    在轮询的基础上,加以改造。Http请求到来,若是不主动close或者return,则连接会一直存在。但是不要让这个时间太长,会占用太多资源
    例如:当前端发送请求,后端拿到后,不去关闭,而是等待一段时间,在这段时间内若是有数据到达,立刻返回,否则直到等待时间结束。
    然后返回给前端,前端马上又发起一次请求......
    消息是实时获取。

    WebSocket:

    http是单向请求,客户端去服务端获取数据。服务端不能主动推送消息。
    而websocket类似于socket,可以实现双向发送,
    实现当数据更新,可以主动推送

    二:web微信流程介绍

     三:微信登录开发

    from django.shortcuts import render,HttpResponse
    from bs4 import BeautifulSoup
    import requests
    import time,re,json
    
    CTIME = None  #用于保存全局时间戳
    QCODE = None  #当我们访问二维码时,会产生一个UUID,我们将其存放为全局
    TIP = 1  #url中的一个参数tip,当其为1:代表我们还没有扫描二维码,当其为0:扫描了二维码

    登录视图login,用于显示二维码

    def login(request):
        global CTIME
        global QCODE
        CTIME = int(time.time())
    
        data = {
            'appid':'wx782c26e4c19acffb',
            'fun':'new',
            'lang':'zh_CN',
            '_':CTIME
        }
    
        response = requests.get(
            url="https://login.wx.qq.com/jslogin",
            params=data
        )
    
        pat_res = re.findall('uuid = "(.*)";',response.text)  #正则匹配UUID
        QCODE = pat_res[0]
    
        return render(request,"login.html",{'qcode':QCODE})

    check_login用于检测登录状态:408未扫描,201扫描二维码但是未登录,200点击登录

    def check_login(request):
        global TIP
        ret = {'code':408,'data':None}
        data = {
            'loginicon':"true",
            'uuid':QCODE,
            'tip':TIP,
            'r':'-577317906',
            '_':int(time.time())
        }
        r1 = requests.get(
            url='https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login',
            params=data
        )
    
        if 'window.code=408' in r1.text:
            print("无人扫描")
            return HttpResponse(json.dumps(ret))
        elif 'window.code=201' in r1.text:
            ret['code'] = 201
            pat_ret = re.findall("window.userAvatar = '(.*)';",r1.text)[0]
            ret['data'] = pat_ret
            TIP = 0
            return HttpResponse(json.dumps(ret))
        elif 'window.code=200;' in r1.text:
            ret['code'] = 200
            redirect_url = re.findall('window.redirect_uri="(.*)";',r1.text)[0]
            reponse = requests.get(
                url=redirect_url+"&fun=new&version=v2"  #url不够完整,需要我们完善
            )
            # print(reponse.text) #<error><ret>0</ret><message></message><skey>@crypt_7358fe11_af06754907ad9c216768337d80cf0ce7</skey><wxsid>icUySQoySDi2OZFK</wxsid><wxuin>2821071261</wxuin><pass_ticket>IWScm1SE%2BGQ%2BNEaghUBCxbF3xPJSzqXUGTO6BYh3TBEGlw8Wa7qETkA9EEAUudYU</pass_ticket><isgrayscale>1</isgrayscale></error>
            soup = BeautifulSoup(reponse.text,"lxml")
            info_dict = {}
            for tag in soup.find("error").children:
                info_dict[tag.name]=tag.get_text()
    
    
            get_user_info_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-613135321&pass_ticket='+info_dict['pass_ticket']
            get_user_info_form = {
                'BaseRequest':
                {
                    'DeviceID':"e055319847811019",
                    'Sid':info_dict['wxsid'],
                    'Skey':info_dict['skey'],
                    'Uin':info_dict['wxuin']
                }
            }
    
    
            reponse2 = requests.post(   #获取的是用户信息,最近联系人,公众号,自己信息
                url=get_user_info_url,
                json=get_user_info_form,    #注意这里使用的是json,post不允许传送字典
            )
    
            reponse2.encoding = "utf-8"
            print(reponse2.text)
    
            return HttpResponse("OK")
            '''
            新请求 GET 获取跳转地址redirect_uri
            https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?
            loginicon=true
            &uuid=QfsKELYXow==
            &tip=0
            &r=-613406501
            &_=1529621492415
            ---------------------------------------------------------
                window.code=200;
                window.redirect_uri="
                    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?
                        ticket=ASWg1dxC1oWVbJtZH8V-HhlB@qrticket_0
                        &uuid=QfsKELYXow==
                        &lang=zh_CN
                        &scan=1529621533";
                        
            新请求   GET    获取凭证pass_ticket    服务端开始设置了cookie,说明在后面的请求中需要携带cookie
            https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?
            ticket=ASWg1dxC1oWVbJtZH8V-HhlB@qrticket_0
            &uuid=QfsKELYXow==
            &lang=zh_CN
            &scan=1529621533
            &fun=new
            &version=v2
            -----------------------------------------------------------------
                <error>
                    <ret>0</ret>
                    <message></message>
                    <skey>@crypt_7358fe11_ea821d506c39f7d75a3e83b4233caab4</skey>
                    <wxsid>qUJZlkBIWQ0130QI</wxsid>
                    <wxuin>2821071261</wxuin>
                    <pass_ticket>xNiKeCBgFkMBfEK8oOK3Gp9qj%2F1HfLpcfPrDwGv3A4nltKskVqoxkECrVYEN9eJJ</pass_ticket>
                    <isgrayscale>1</isgrayscale>
                </error>
            
            新请求:获取用户所有信息,最近联系人和公众号    POST    需要携带数据,数据来自于上面凭证中
            https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?
            r=-613135321
            &pass_ticket=xNiKeCBgFkMBfEK8oOK3Gp9qj%252F1HfLpcfPrDwGv3A4nltKskVqoxkECrVYEN9eJJ
            
            数据
            {
                BaseRequest:
                {
                    DeviceID:"e055319847811019"
                    Sid:"pY7nfHplUAsBOINz"
                    Skey:"@crypt_7358fe11_e0ae163bd19650bea336df66837e9f7a"
                    Uin:"2821071261"
                }
            }
            --------------------------------------------------------------------
            {
                "BaseResponse": {
                "Ret": 0,
                "ErrMsg": ""
                }
                ,
                "Count": 9,
                "ContactList": [{
                "Uin": 0,
                "UserName": "filehelper",
                "NickName": "文件传输助手",
                "HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=660872310&username=filehelper&skey=@crypt_7358fe11_ea821d506c39f7d75a3e83b4233caab4",
                "ContactFlag": 2,
                "MemberCount": 0,
                "MemberList": [],
                "RemarkName": "",
                "HideInputBarFlag": 0,
                "Sex": 0,
                "Signature": "",
                "VerifyFlag": 0,
                "OwnerUin": 0,
                "PYInitial": "WJCSZS",
                "PYQuanPin": "wenjianchuanshuzhushou",
                "RemarkPYInitial": "",
                "RemarkPYQuanPin": "",
                "StarFriend": 0,
                "AppAccountFlag": 0,
                "Statues": 0,
                "AttrStatus": 0,
                "Province": "",
                "City": "",
                "Alias": "",
                "SnsFlag": 0,
                "UniFriend": 0,
                "DisplayName": "",
                "ChatRoomId": 0,
                "KeyWord": "fil",
                "EncryChatRoomId": "",
                "IsOwner": 0
                },还有其他的]
            }
    
            新请求
            https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?
            r=-613135321
            &pass_ticket=xNiKeCBgFkMBfEK8oOK3Gp9qj%252F1HfLpcfPrDwGv3A4nltKskVqoxkECrVYEN9eJJ
            
            
            新请求 GET 获取所有联系人和公众号
            https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?
            lang=zh_CN
            &pass_ticket=gWbCT8vTjFeFKXDvfJZ6DtMtHo5d8zzhtLgLoybILn7eeTNSMI4BErA7e9otuPXQ
            &r=1529642330650
            &seq=0
            &skey=@crypt_7358fe11_9dc260b8cffb962a3e475ca50e7813c9
            -----------------------------------------------------------------------------
            {
            "BaseResponse": {
            "Ret": 0,
            "ErrMsg": ""
            }
            ,
            "MemberCount": 162,
            "MemberList": [{
                "Uin": 0,
                "UserName": "@39ef4d4197e9a7388e41fc9de150b3e28bf125082f1e442822814dec4803c6a0",
                "NickName": "宁静致远",
                "HeadImgUrl": "/cgi-bin/mmwebwx-bin/webwxgeticon?seq=0&username=@39ef4d4197e9a7388e41fc9de150b3e28bf125082f1e442822814dec4803c6a0&skey=@crypt_7358fe11_9dc260b8cffb962a3e475ca50e7813c9",
                "ContactFlag": 1,
                "MemberCount": 0,
                "MemberList": [],
                "RemarkName": "",
                "HideInputBarFlag": 0,
                "Sex": 1,
                "Signature": "凶巴巴呛贝贝",
                "VerifyFlag": 0,
                "OwnerUin": 0,
                "PYInitial": "NJZY",
                "PYQuanPin": "ningjingzhiyuan",
                "RemarkPYInitial": "",
                "RemarkPYQuanPin": "",
                "StarFriend": 0,
                "AppAccountFlag": 0,
                "Statues": 0,
                "AttrStatus": 4197,
                "Province": "河南",
                "City": "郑州",
                "Alias": "",
                "SnsFlag": 17,
                "UniFriend": 0,
                "DisplayName": "",
                "ChatRoomId": 0,
                "KeyWord": "",
                "EncryChatRoomId": "",
                "IsOwner": 0
                },
                还有其他
            ]
            '''
    各个url详细请求

    前端代码:显示二维码和头像

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <img id="qrcode" style=" 340px;height: 340px;" src="https://login.weixin.qq.com/qrcode/{{ qcode }}" alt="">
    </body>
    </html>
    <script src="/static/jquery.js"></script>
    <script>
        $(function(){
            checkLogin();
        })
    
        function checkLogin() {
            $.ajax({
                url:'/check-login.html',
                type:'GET',
                dataType:"json",
                success:function(data){
                    console.log(data.code);
                    if (data.code==408){
                        checkLogin();
                    }
                    else if(data.code==201){
                        $("#qrcode").attr('src',data.data)
                        checkLogin();
                    }
                }
            })
        }
    </script>

    测试返回的最近联系人和公众号信息

    user_dict = {}
    
    
    for item in user_dict.items():
        print(item)
    
    for item in user_dict['ContactList']:   #最近联系人
        print(item['PYQuanPin'],item['NickName'])
    
    
    for item in user_dict['MPSubscribeMsgList']:    #公众号和推送消息
        print(item['UserName'],item['NickName'])
        for item2 in item['MPArticleList']:
            print(item2['Title'],item2['Cover'],item2['Digest'],item2['Url'])
    最近联系人和公众号
    ('ClientVersion', 637929271)
    ('GrayScale', 1)
    ('Count', 10)
    ('SystemTime', 1529661118)
    ('MPSubscribeMsgList:公众号列表,含有文章推送等信息', [{'UserName': '@393d71e59f81ac2feca148e8e269c0df', 'MPArticleList': [{'Title': '', 'Digest': '', 'Url': '', 'Cover': '图片'}, ], 'MPArticleCount': 2, 'Time': 1529651105, 'NickName': '人工智能头条'},])
    ('ChatSet', 'filehelper,@@7c7137978e7349eac97453fa2adc290df295eaba3e7981e07ff85111f94a403c,weixin,@0fdf14d27dc0b2d34d013329ec498aae6284dbc340bdfbd8741227a72b1b3fa4,@393d71e59f81ac2feca148e8e269c0df,@@4d7d0c68e8445a6d69a5e3a2415c57c8f46858724cfdef8618b5790094e5de37,@@6b45638d8a8394a5bea103bd55ef49ce69dad73b8eda94dd5f63a126ec0e6ee4,@@d6c45082c0686e0cef729f3cb20db704b381b2aef67fe0a8a82151869220c8ef,@@03e7d8c59c30bb81dc0f2dc683b8e7a6f4a707f2aac6655c6e5036c349a96fe3,@02bf3be3c826bc38d4461d3ee52704e8,')
    ('MPSubscribeMsgCount:最近推送的公众号数目', 2)
    ('BaseResponse', {'ErrMsg': '', 'Ret': 0})
    ('SKey', '@crypt_7358fe11_08012eadffc70f5c3189f802236830be')
    ('ClickReportInterval', 600000)
    ('InviteStartCount', 40)
    ('User:用户自己的信息', {'VerifyFlag': 0, 'HeadImgFlag': 1, 'Uin': 2821071261, 'NickName': '宁静致远', 'AppAccountFlag': 0, 'UserName': '@c959c389ab390d9f71d3f528f5a4ee1e81d6c8cd4aaf48d8b1f0077073660c5c', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1753775271&username=@c959c389ab390d9f71d3f528f5a4ee1e81d6c8cd4aaf48d8b1f0077073660c5c&skey=@crypt_7358fe11_08012eadffc70f5c3189f802236830be', 'ContactFlag': 0, 'RemarkPYInitial': '', 'SnsFlag': 17, 'PYQuanPin': '', 'WebWxPluginSwitch': 0, 'HideInputBarFlag': 0, 'RemarkPYQuanPin': '', 'Signature': '凶巴巴呛贝贝', 'Sex': 1, 'StarFriend': 0, 'PYInitial': '', 'RemarkName': ''})
    ('ContactList:最近联系人信息', [
     {'VerifyFlag': 0, 'Uin': 0, 'Signature': '', 'AppAccountFlag': 0, 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=660872310&username=filehelper&skey=@crypt_7358fe11_08012eadffc70f5c3189f802236830be', 'PYInitial': 'WJCSZS', 'Province': '', 'PYQuanPin': 'wenjianchuanshuzhushou', 'DisplayName': '', 'RemarkName': '', 'IsOwner': 0, 'Sex': 0, 'EncryChatRoomId': '', 'KeyWord': 'fil', 'City': '', 'ChatRoomId': 0, 'RemarkPYQuanPin': '', 'Alias': '', 'UniFriend': 0, 'UserName': 'filehelper', 'MemberCount': 0, 'ContactFlag': 2, 'RemarkPYInitial': '', 'Statues': 0, 'AttrStatus': 0, 'SnsFlag': 0, 'HideInputBarFlag': 0, 'NickName': '文件传输助手', 'OwnerUin': 0, 'StarFriend': 0, 'MemberList': []},])
    ('SyncKey', {'List': [{'Key': 1, 'Val': 677540039}, {'Key': 2, 'Val': 677540219}, {'Key': 3, 'Val': 677540036}, {'Key': 1000, 'Val': 1529658962}], 'Count': 4})
    相关数据打印(格式)

     四:显示最近联系人和公众号

    视图所有代码:对于上面是有所修改的

    from django.shortcuts import render,HttpResponse,redirect
    from bs4 import BeautifulSoup
    import requests
    import time,re,json
    
    CTIME = None
    QCODE = None
    TIP = 1
    TICKET_DICT = {}    #保存凭证信息
    ALL_COOKIE_DICT = {}
    
    
    # Create your views here.
    def login(request):
        global CTIME
        global QCODE
        CTIME = int(time.time()*1000)
    
        data = {
            'appid':'wx782c26e4c19acffb',
            'fun':'new',
            'lang':'zh_CN',
            '_':CTIME
        }
    
        response = requests.get(
            url="https://login.wx.qq.com/jslogin",
            params=data
        )
    
        pat_res = re.findall('uuid = "(.*)";',response.text)
        QCODE = pat_res[0]
    
        return render(request,"login.html",{'qcode':QCODE})
    
    def check_login(request):
        global TIP
        ret = {'code':408,'data':None}
        data = {
            'loginicon':"true",
            'uuid':QCODE,
            'tip':TIP,
            'r':'-577317906',
            '_':int(time.time())
        }
        r1 = requests.get(
            url='https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login',
            params=data
        )
    
        if 'window.code=408' in r1.text:
            print("无人扫描")
            return HttpResponse(json.dumps(ret))
        elif 'window.code=201' in r1.text:
            ret['code'] = 201
            pat_ret = re.findall("window.userAvatar = '(.*)';",r1.text)[0]
            ret['data'] = pat_ret
            TIP = 0
            return HttpResponse(json.dumps(ret))
        elif 'window.code=200;' in r1.text:
            ret['code'] = 200
            redirect_url = re.findall('window.redirect_uri="(.*)";', r1.text)[0]
            reponse = requests.get(     #获取凭证,这里也开始设置cookie了,所以我们在这里向后需要记录cookie
                url=redirect_url + "&fun=new&version=v2"  # url不够完整,需要我们完善
            )
            ALL_COOKIE_DICT.update(reponse.cookies)
    
            soup = BeautifulSoup(reponse.text, "lxml")
            info_dict = {}
            for tag in soup.find("error").children:
                info_dict[tag.name] = tag.get_text()
    
            global TICKET_DICT
            TICKET_DICT.update(info_dict)
    
            ret['code']=200
    
            return HttpResponse(json.dumps(ret))
    
    
    def user(request):
        get_user_info_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-613135321&pass_ticket=' + TICKET_DICT[
            'pass_ticket']
        get_user_info_form = {
            'BaseRequest':
                {
                    'DeviceID': "e055319847811019",
                    'Sid': TICKET_DICT['wxsid'],
                    'Skey': TICKET_DICT['skey'],
                    'Uin': TICKET_DICT['wxuin']
                }
        }
    
        reponse2 = requests.post(  # 获取的是用户信息,几个联系人,公众号,自己信息
            url=get_user_info_url,
            json=get_user_info_form,  # 注意这里使用的是json,post不允许传送字典
        )
        ALL_COOKIE_DICT.update(reponse2.cookies)
    
        reponse2.encoding = "utf-8"
    
        user_info_dict = json.loads(reponse2.text)  # 获取的是用户信息,几个联系人,公众号,自己信息
    
        return render(request, "user.html", {'user_info_dict': user_info_dict})
    views修改后的代码,主要是将凭证放入全局字典

    视图方法user去获取最近联系人

    注意:我们将上面的凭证保存到了全局变量中TICKET_DICT方便查询使用

    def user(request): get_user_info_url
    = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-613135321&pass_ticket=' + TICKET_DICT[ 'pass_ticket'] get_user_info_form = { 'BaseRequest': { 'DeviceID': "e055319847811019", 'Sid': TICKET_DICT['wxsid'], 'Skey': TICKET_DICT['skey'], 'Uin': TICKET_DICT['wxuin'] } } reponse2 = requests.post( # 获取的是用户信息,几个联系人,公众号,自己信息 url=get_user_info_url, json=get_user_info_form, # 注意这里使用的是json,post不允许传送字典 ) ALL_COOKIE_DICT.update(reponse2.cookies) reponse2.encoding = "utf-8" user_info_dict = json.loads(reponse2.text) # 获取的是用户信息,几个联系人,公众号,自己信息 return render(request, "user.html", {'user_info_dict': user_info_dict})

    前端代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div>
            <h3>最近联系人</h3>
            <ul>
                {% for item in user_info_dict.ContactList %}
                    <li>{{ item.NickName }}</li>
                {% endfor %}
            </ul>
            <a href="/contact-list.html">获取更多联系人</a>
        </div>
        <div>
            <h3>微信公众号</h3>
            <div>
                {% for item in user_info_dict.MPSubscribeMsgList %}
                    <h4>{{ item.NickName }}</h4>
                    <ul>
                        {% for item2 in item.MPArticleList %}
                            <li>
                                <a href="{{ item2.Url }}">
                                    {{ item2.Title }}
                                </a>
                            </li>
                        {% endfor %}
                    </ul>
                {% endfor %}
            </div>
        </div>
    </body>
    </html>

    五:显示所有联系人

    视图所有的修改:主要在设置一个全局字典存放网站cookie,注意这里是需要携带cookie的,而cookie是在我们点击登录后,服务器开始设置的,我们需要去获取自那时以后的所有cookie

    from django.shortcuts import render,HttpResponse,redirect
    from bs4 import BeautifulSoup
    import requests
    import time,re,json
    
    CTIME = None
    QCODE = None
    TIP = 1
    TICKET_DICT = {}    #保存凭证信息
    ALL_COOKIE_DICT = {}
    
    
    # Create your views here.
    def login(request):
        global CTIME
        global QCODE
        CTIME = int(time.time()*1000)
    
        data = {
            'appid':'wx782c26e4c19acffb',
            'fun':'new',
            'lang':'zh_CN',
            '_':CTIME
        }
    
        response = requests.get(
            url="https://login.wx.qq.com/jslogin",
            params=data
        )
    
        pat_res = re.findall('uuid = "(.*)";',response.text)
        QCODE = pat_res[0]
    
        return render(request,"login.html",{'qcode':QCODE})
    
    def check_login(request):
        global TIP
        ret = {'code':408,'data':None}
        data = {
            'loginicon':"true",
            'uuid':QCODE,
            'tip':TIP,
            'r':'-577317906',
            '_':int(time.time())
        }
        r1 = requests.get(
            url='https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login',
            params=data
        )
    
        if 'window.code=408' in r1.text:
            print("无人扫描")
            return HttpResponse(json.dumps(ret))
        elif 'window.code=201' in r1.text:
            ret['code'] = 201
            pat_ret = re.findall("window.userAvatar = '(.*)';",r1.text)[0]
            ret['data'] = pat_ret
            TIP = 0
            return HttpResponse(json.dumps(ret))
        elif 'window.code=200;' in r1.text:
            ret['code'] = 200
            redirect_url = re.findall('window.redirect_uri="(.*)";', r1.text)[0]
            reponse = requests.get(     #获取凭证,这里也开始设置cookie了,所以我们在这里向后需要记录cookie
                url=redirect_url + "&fun=new&version=v2"  # url不够完整,需要我们完善
            )
            ALL_COOKIE_DICT.update(reponse.cookies)
    
            soup = BeautifulSoup(reponse.text, "lxml")
            info_dict = {}
            for tag in soup.find("error").children:
                info_dict[tag.name] = tag.get_text()
    
            global TICKET_DICT
            TICKET_DICT.update(info_dict)
    
            ret['code']=200
    
            return HttpResponse(json.dumps(ret))
    
    
    def user(request):
        get_user_info_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-613135321&pass_ticket=' + TICKET_DICT[
            'pass_ticket']
        get_user_info_form = {
            'BaseRequest':
                {
                    'DeviceID': "e055319847811019",
                    'Sid': TICKET_DICT['wxsid'],
                    'Skey': TICKET_DICT['skey'],
                    'Uin': TICKET_DICT['wxuin']
                }
        }
    
        reponse2 = requests.post(  # 获取的是用户信息,几个联系人,公众号,自己信息
            url=get_user_info_url,
            json=get_user_info_form,  # 注意这里使用的是json,post不允许传送字典
        )
        ALL_COOKIE_DICT.update(reponse2.cookies)
    
        reponse2.encoding = "utf-8"
    
        user_info_dict = json.loads(reponse2.text)  # 获取的是用户信息,几个联系人,公众号,自己信息
    
        return render(request, "user.html", {'user_info_dict': user_info_dict})
    
    
    def contact_list(request):
        get_all_user_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=%s&r=%s&seq=0&skey=%s' % (TICKET_DICT['pass_ticket'],int(time.time()*1000),TICKET_DICT['skey'])
    
        reponse = requests.get(
            url=get_all_user_url,   #这里需要用到cookie
            cookies=ALL_COOKIE_DICT
        )
    
        reponse.encoding = "utf-8"
        contact_info_list = json.loads(reponse.text)
    
    
        return render(request,"contact_info.html",{'contact_info_list':contact_info_list})
    所有视图代码,主要修改在ALL_COOKIE_DICT 存放cookie

    不携带cookie情况:

    视图方法:contact_list

    def contact_list(request):
        get_all_user_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=%s&r=%s&seq=0&skey=%s' % (TICKET_DICT['pass_ticket'],int(time.time()*1000),TICKET_DICT['skey'])
    
        reponse = requests.get(
            url=get_all_user_url,   #这里需要用到cookie
            cookies=ALL_COOKIE_DICT
        )
    
        reponse.encoding = "utf-8"
        contact_info_list = json.loads(reponse.text)
    
    
        return render(request,"contact_info.html",{'contact_info_list':contact_info_list})

     前端代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div>
            <h3>全部联系人列表</h3>
            <ul>
                {% for item in contact_info_list.MemberList %}
                <li>{{ item.NickName }}</li>
                {% endfor %}
            </ul>
        </div>
    </body>
    </html>

     六:模拟发送信息

    发送信息的url:

    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&pass_ticket=l8yQcPtEelgrNY6fSnMf72i%252BoP10LCLTdmjnFgEQOCK9n7401krRfKnc0xMbNweJ

    POST传递数据内容:

    {
    "BaseRequest":  #这里数据存放在全局凭证中 {"Uin":2821071261, "Sid":"xU10r+19IxmPU8Fb", "Skey":"@crypt_7358fe11_5fc69b570e562f35f5e96aa1039d83aa", "DeviceID":"e308142734343946" }, "Msg":  #发送的数据信息 {"Type":1,  #文本信息 "Content":"参数",  #发送的数据 "FromUserName":"@c63e475396e438ef81d9825832217c06e4cc302269db05b7eae7e2980de2d56d",  #我的username "ToUserName":"@94bcc0a92c726c0e2639ffa59618549d222bee0107150515cf247dc8d45f8144",  #发给谁username "LocalID":"15296541823070630",  #和时间戳一致 "ClientMsgId":"15296541823070630"  #时间戳 }, "Scene":0 }
    {"BaseRequest":
         {"Uin":2821071261,
          "Sid":"xU10r+19IxmPU8Fb",
          "Skey":"@crypt_7358fe11_5fc69b570e562f35f5e96aa1039d83aa",
          "DeviceID":"e149192355196085"  #可变的设备ID
          },
     "Msg":
         {"Type":1,  
          "Content":"哈哈哈",  #发送内容改变了
          "FromUserName":"@c63e475396e438ef81d9825832217c06e4cc302269db05b7eae7e2980de2d56d",
          "ToUserName":"@94bcc0a92c726c0e2639ffa59618549d222bee0107150515cf247dc8d45f8144",
          "LocalID":"15296546798310239",  #同时间戳一致
          "ClientMsgId":"15296546798310239"  #时间戳改变了
          },
    "Scene":0
     }

     修改前端contact_info.html页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link href="/static/css/bootstrap.min.css" rel="stylesheet">
        <link href="/static/css/nifty.min.css" rel="stylesheet">
        <link href="/static/css/demo/nifty-demo-icons.min.css" rel="stylesheet">
        <link href="/static/css/demo/nifty-demo.min.css" rel="stylesheet">
        <link href="/static/plugins/pace/pace.min.css" rel="stylesheet">
        <script src="/static/js/jquery-2.2.4.min.js"></script>
        <script>
        $(function(){
            $(".list-group-item").click(function(){
                $(".list-unstyled").empty();
                $(this).siblings().removeClass("active");
                $(this).addClass("active");
                var NickName = $(this).first().text().trim();
                $(".panel-title").text(NickName);
            })
        })
        </script>
        <script src="/static/plugins/pace/pace.min.js"></script>
        <script src="/static/js/bootstrap.min.js"></script>
        <script src="/static/js/nifty.min.js"></script>
        <script src="/static/js/demo/nifty-demo.min.js"></script>
        <script src="/static/plugins/flot-charts/jquery.flot.min.js"></script>
        <script src="/static/plugins/flot-charts/jquery.flot.resize.min.js"></script>
        <script src="/static/plugins/gauge-js/gauge.min.js"></script>
        <script src="/static/plugins/skycons/skycons.min.js"></script>
        <script src="/static/plugins/easy-pie-chart/jquery.easypiechart.min.js"></script>
        <script src="/static/js/demo/widgets.js"></script>
    </head>
    <body>
    <div id="container" class="effect  aside-bright mainnav-sm aside-right aside-in">
        <div class="boxed">
            <div id="content-container">
                <div class="row">
                    <div class="col-md-8 col-lg-8 col-sm-8">
    
                <!--Chat widget-->
                <!--===================================================-->
                <div class="panel" style="height: 640px">
                    <!--Heading-->
                    <div class="panel-heading">
                        <h3 class="panel-title">Chat</h3>
                    </div>
    
                    <!--Widget body-->
                    <div style="height:510px;padding-top:0px;" class="widget-body">
                        <div class="nano">
                            <div class="nano-content pad-all">
                                <ul class="list-unstyled media-block">
                                    <li class="mar-btm">
                                        <div class="media-left">
                                            <img src="img/profile-photos/1.png" class="img-circle img-sm" alt="Profile Picture">
                                        </div>
                                        <div class="media-body pad-hor">
                                            <div class="speech">
                                                <a href="#" class="media-heading">Aaron Chavez</a>
                                                <p>Hello Lucy, how can I help you today ?</p>
                                                <p class="speech-time">
                                                <i class="demo-pli-clock icon-fw"></i>09:23AM
                                                </p>
                                            </div>
                                        </div>
                                    </li>
                                    <li class="mar-btm">
                                        <div class="media-right">
                                            <img src="img/profile-photos/8.png" class="img-circle img-sm" alt="Profile Picture">
                                        </div>
                                        <div class="media-body pad-hor speech-right">
                                            <div class="speech">
                                                <a href="#" class="media-heading">Lucy Doe</a>
                                                <p>Hi, I want to buy a new shoes.</p>
                                                <p class="speech-time">
                                                    <i class="demo-pli-clock icon-fw"></i> 09:23AM
                                                </p>
                                            </div>
                                        </div>
                                    </li>
                                </ul>
                            </div>
                        </div>
    
                        <!--Widget footer-->
                        <div class="panel-footer" style="height: 90px;">
                            <div class="row">
                                <div class="col-xs-9">
                                    <input type="text" placeholder="Enter your text" class="form-control chat-input">
                                </div>
                                <div class="col-xs-3">
                                    <button class="btn btn-primary btn-block" onclick="sendMsg(this);" type="submit">Send</button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <!--===================================================-->
                <!--Chat widget-->
    
            </div>
                    <div class="col-md-4 col-lg-4 col-sm-4">
                        <aside id="aside-container">
                    <div id="aside">
                        <div class="nano has-scrollbar">
                            <div class="nano-content" tabindex="0" style="right: -17px;">
    
                                <!--Nav tabs-->
                                <!--================================-->
                                <ul class="nav nav-tabs nav-justified">
                                    <li class="active">
                                        <a href="#demo-asd-tab-1" data-toggle="tab">
                                            <i class="demo-pli-speech-bubble-7"></i>
                                        </a>
                                    </li>
                                </ul>
                                <!--================================-->
                                <!--End nav tabs-->
    
                                <!-- Tabs Content -->
                                <!--================================-->
                                <div class="tab-content">
                                    <div class="tab-pane fade in active" id="demo-asd-tab-1">
                                        <p class="pad-hor text-semibold text-main">
                                            <span class="pull-right badge badge-success">{{ contact_info_list.MemberCount }}</span> Friends
                                        </p>
    
                                        <!--Works-->
                                        <div class="list-group bg-trans">
                                            {% for item in contact_info_list.MemberList %}
                                                <a href="#" for="{{ item.UserName }}" class="list-group-item">
                                                    <span class="badge badge-purple badge-icon badge-fw pull-left"></span> {{ item.NickName }}
                                                </a>
                                            {% endfor %}
                                        </div>
                                    </div>
                                </div>
                            </div>
                        <div class="nano-pane" style="display: none;"><div class="nano-slider" style="height: 4059px; transform: translate(0px, 0px);"></div></div></div>
                    </div>
                </aside>
                    </div>
                </div>
            </div>
        </div>
    </div>
    </body>
    </html>
    
    <script>
        function sendMsg(ths){
            var sel_tag = $(".list-group").find(".active")
            if(sel_tag.length==0){
                return false;
            }
            var msg = $(ths).parents(".panel-footer").find(".chat-input").val();
            var sendMsg={
                'ToUserName':sel_tag.attr("for"),
                'Type':1,
                'Content':msg,
                'csrfmiddlewaretoken':'{{ csrf_token }}'
            }
    
            $.ajax({
                url:"send-msg.html",
                data:sendMsg,
                type:"POST",
                dataType:"json",
                success:function(callback){
                    if (callback.code==200){
                        var dt = new Date()
                        var now_time = dt.toLocaleString();
    
                        console.log(callback);
                        var li = '<li class="mar-btm"><div class="media-right"><img src="'+callback.headImgUrl+'" class="img-circle img-sm" alt="Profile Picture"></div>';
                        li += '<div class="media-body pad-hor speech-right"><div class="speech"><a href="#" class="media-heading">'+callback.username+'</a>';
                        li += '<p>'+msg+'</p>';
                        li += '<p class="speech-time">';
                        li += '<i class="demo-pli-clock icon-fw"></i>'+now_time;
                        li += '</p></div></div></li>';
                        $(ths).parents(".widget-body").find(".list-unstyled").append(li);
                        $(ths).parents(".panel-footer").find(".chat-input").val("");
                    }
                }
            })
        }
    </script>
    前端代码使用ajax向后端传送

    后端代码send_msg

    注意:处理传送中文时,在requests模块有点麻烦,下面代码有写解决方法

    def send_msg(request):
        ret = {
            'code':200,
            'error':'Send Success',
            'data':{}
        }
    
        recv_data = request.POST
    
        if not recv_data:
            ret['code']=400
            ret['data']="Send failure"
            return HttpResponse(json.dumps(ret))
    
        #数据整合
        Send_data={}
        Send_data['BaseRequest'] = {
            'DeviceID': "e055319847811019",
            'Sid': TICKET_DICT['wxsid'],
            'Skey': TICKET_DICT['skey'],
            'Uin': TICKET_DICT['wxuin']
        }
    
        Send_data['Msg'] = {
            'Type':recv_data.get("Type",1),
            'Content':recv_data.get("Content"),
            'FromUserName':USER_INIT_DICT['User']['UserName'],
            'ToUserName':recv_data.get("ToUserName"),
            'LocalID':int(time.time()*1000),
            'ClientMsgId':int(time.time()*1000),
        }
        Send_data['Scene']=0
    
        send_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&pass_ticket=%s'%TICKET_DICT['pass_ticket']
        # reponse = requests.post(
        #     url=send_url,
        #     json=Send_data, #注意这里如果使用json,会将中文转换为Unicode
        #     cookies=ALL_COOKIE_DICT
        # )
        reponse = requests.post(
            url=send_url,
            #若是有中文,需要加上ensure_ascii=False,若是字符串中含有中文,request传递数据时,将中文转换为字节,无法为我们转换。需要我们提前使用encoding编码,直接传递字节,不让requests为我们转换
            #data可以是字典,字符串,字节,既然对于字典,字符串直接含有中文不正确,直接转字节传送,py3默认是utf-8,所以我们直接传送字节就可以
            data=bytes(json.dumps(Send_data,ensure_ascii=False),encoding="utf-8"), #注意这里如果使用json,会将中文转换为Unicode
            cookies=ALL_COOKIE_DICT  #携带cookie
        )
    
        reponse.encoding = "utf-8"
    
        ret_status = re.findall('"Ret": (.*),', reponse.text)[0]
        ret_error = re.findall('"ErrMsg": "(.*)"', reponse.text)[0]
    
        if int(ret_status) != 0:
            ret['code']=401
            ret['data']=ret_error
            return HttpResponse(json.dumps(ret))
    
        ret['username'] = USER_INIT_DICT['User']['NickName']
        ret['headImgUrl'] = 'https://wx.qq.com'+USER_INIT_DICT['User']['HeadImgUrl']
    
        return HttpResponse(json.dumps(ret))

     七:实现长轮询接收消息

    先参考微信的实例:微信依靠两个url实现去后端获取数据

    1.webwxsync:ajax使用POST,长轮询去获取发送的消息,和获取一个SyncCheckKey,下面检测是否有消息到了需要携带这个SyncCheckKey
    
    https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=NOWucA2Et3xw0l8a&skey=@crypt_7358fe11_181eea60999ab937ed1ff13e1d1f7853&pass_ticket=9ZK9OoNzaLxkdRqVWghy7uGzWFvsIzXNWDjgeJqTskg3Bl08tQxAZ9t0hcEYOzmO

    要传递的POST数据
    {  
    "BaseRequest":{  #都是已经获取的数据
    "Uin":2821071261,
    "Sid":"NOWucA2Et3xw0l8a",
    "Skey":"@crypt_7358fe11_181eea60999ab937ed1ff13e1d1f7853",
    "DeviceID":"e937865997050874"
    },
    "SyncKey":{  #我们上一次的SyncKey值
    "Count":9,"List":[{"Key":1,"Val":677540346},{"Key":2,"Val":677540435},{"Key":3,"Val":677540036},{"Key":11,"Val":677540181},{"Key":201,"Val":1529672373},{"Key":203,"Val":1529658601},{"Key":1000,"Val":1529658962},{"Key":1001,"Val":1529659033},{"Key":2001,"Val":1529480143}]
    },
    "rr":-664997335  #未知
    }
    {
    "BaseResponse": {
    "Ret": 0,
    "ErrMsg": ""
    }
    ,
    "AddMsgCount": 0,
    "AddMsgList": [],
    "ModContactCount": 0,
    "ModContactList": [],
    "DelContactCount": 0,
    "DelContactList": [],
    "ModChatRoomMemberCount": 0,
    "ModChatRoomMemberList": [],
    "Profile": {
    "BitFlag": 0,
    "UserName": {
    "Buff": ""
    }
    ,
    "NickName": {
    "Buff": ""
    }
    ,
    "BindUin": 0,
    "BindEmail": {
    "Buff": ""
    }
    ,
    "BindMobile": {
    "Buff": ""
    }
    ,
    "Status": 0,
    "Sex": 0,
    "PersonalCard": 0,
    "Alias": "",
    "HeadImgUpdateFlag": 0,
    "HeadImgUrl": "",
    "Signature": ""
    }
    ,
    "ContinueFlag": 0,
    "SyncKey": {
    "Count": 9,
    "List": [
        {
        "Key": 1,
        "Val": 677540346
        }
        ,{
        "Key": 2,
        "Val": 677540423
        }
        ,{
        "Key": 3,
        "Val": 677540036
        }
        ,{
        "Key": 11,
        "Val": 677540181
        }
        ,{
        "Key": 201,
        "Val": 1529671726
        }
        ,{
        "Key": 203,
        "Val": 1529658601
        }
        ,{
        "Key": 1000,
        "Val": 1529658962
        }
        ,{
        "Key": 1001,
        "Val": 1529659033
        }
        ,{
        "Key": 2001,
        "Val": 1529480143
        }
    ]
    }
    ,
    "SKey": "",
    "SyncCheckKey": {
    "Count": 9,
    "List": [
        {
        "Key": 1,
        "Val": 677540346
        }
        ,{
        "Key": 2,
        "Val": 677540423
        }
        ,{
        "Key": 3,
        "Val": 677540036
        }
        ,{
        "Key": 11,
        "Val": 677540181
        }
        ,{
        "Key": 201,
        "Val": 1529671726
        }
        ,{
        "Key": 203,
        "Val": 1529658601
        }
        ,{
        "Key": 1000,
        "Val": 1529658962
        }
        ,{
        "Key": 1001,
        "Val": 1529659033
        }
        ,{
        "Key": 2001,
        "Val": 1529480143
        }
    ]
    }
    }
    获取的数据:SyncKey
    2.synccheck:轮询请求,用于检测是否有人发消息过来。注意:当我们刚刚登陆时,是有一个初始的synckey的,可以在《相关数据打印(格式)》那里看到
    
    https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck?r=1529672369137&skey=%40crypt_7358fe11_181eea60999ab937ed1ff13e1d1f7853&sid=NOWucA2Et3xw0l8a&uin=2821071261&deviceid=e539832593408529&synckey=1_677540346%7C2_677540434%7C3_677540036%7C11_677540181%7C201_1529672366%7C203_1529658601%7C1000_1529658962%7C1001_1529659033%7C2001_1529480143&_=1529671539738
    https:
    //webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck? r=1529671730362 #时间戳 &skey=%40crypt_7358fe11_181eea60999ab937ed1ff13e1d1f7853&sid=NOWucA2Et3xw0l8a &uin=2821071261 #和其他数据一起放在TICKET_DICT中 &deviceid=e065841963151848 #设备id &synckey= 1_677540346 1 677540346 #和上一个请求url中接收的数据一致 %7C | 2_677540423 2 677540423 %7C | 3_677540036 %7C 11_677540181%7C201_1529671726%7C203_1529658601%7C1000_1529658962%7C1001_1529659033%7C2001_1529480143 &_=1529671539706 #时间戳 r=1529672904066&skey=%40crypt_7358fe11_181eea60999ab937ed1ff13e1d1f7853&sid=NOWucA2Et3xw0l8a&uin=2821071261&deviceid=e647845000558861&synckey=1_677540346%7C2_677540435%7C3_677540036%7C11_677540181%7C201_1529672373%7C203_1529658601%7C1000_1529658962%7C1001_1529659033%7C2001_1529480143&_=1529671539759

    返回值
    window.synccheck
    ={retcode:"0",selector:"2"}  #有消息到来
    window.synccheck={retcode:"0",selector:"0"}  #没有消息到来

    当有消息到来:我们将从webwxsync中获取到数据

    {
    "BaseResponse": {
    "Ret": 0,
    "ErrMsg": ""
    }
    ,
    "AddMsgCount": 1,  #到来的消息数目
    "AddMsgList": [{
    "MsgId": "3138475736544982077",
    "FromUserName": "@@e780498496215d2077ef72216ce629bfd570595c2d1b99192aa32fae78a3e489",  #来自谁的微信
    "ToUserName": "@9419ce13e311ec0469803ba1667703ca16fd3e9ec13d5998c52f42dba33f4c3d",  #这是我们的微信
    "MsgType": 1,
    "Content": "@0e722870282c2e079ec9ddc7304ef501bb99d45465501efac52f8b050498d8a4:<br/>@A~筱嵩灬 10分钟吧",    #发过来的信息,我们未编码
    "Status": 3,  #状态
    "ImgStatus": 1,
    "CreateTime": 1529673345,
    "VoiceLength": 0,
    "PlayLength": 0,
    "FileName": "",
    "FileSize": "",
    "MediaId": "",
    "Url": "",
    "AppMsgType": 0,
    "StatusNotifyCode": 0,
    "StatusNotifyUserName": "",
    "RecommendInfo": {
    "UserName": "",
    "NickName": "",
    "QQNum": 0,
    "Province": "",
    "City": "",
    "Content": "",
    "Signature": "",
    "Alias": "",
    "Scene": 0,
    "VerifyFlag": 0,
    "AttrStatus": 0,
    "Sex": 0,
    "Ticket": "",
    "OpCode": 0
    }
    ,
    "ForwardFlag": 0,
    "AppInfo": {
    "AppID": "",
    "Type": 0
    }
    ,
    "HasProductId": 0,
    "Ticket": "",
    "ImgHeight": 0,
    "ImgWidth": 0,
    "SubMsgType": 0,
    "NewMsgId": 3138475736544982077,
    "OriContent": "",
    "EncryFileName": ""
    }
    ],
    "ModContactCount": 0,
    "ModContactList": [],
    "DelContactCount": 0,
    "DelContactList": [],
    "ModChatRoomMemberCount": 0,
    "ModChatRoomMemberList": [],
    "Profile": {
    "BitFlag": 0,
    "UserName": {
    "Buff": ""
    }
    ,
    "NickName": {
    "Buff": ""
    }
    ,
    "BindUin": 0,
    "BindEmail": {
    "Buff": ""
    }
    ,
    "BindMobile": {
    "Buff": ""
    }
    ,
    "Status": 0,
    "Sex": 0,
    "PersonalCard": 0,
    "Alias": "",
    "HeadImgUpdateFlag": 0,
    "HeadImgUrl": "",
    "Signature": ""
    }
    ,
    "ContinueFlag": 0,
    "SyncKey": {  #下一次去检测需要的SyncKey,每当我们接受一次真正的消息或者长轮询结束,原来的就失效,需要一个新的SyncKey值
    "Count": 9,
    "List": [{
    "Key": 1,
    "Val": 677540346
    }
    ,{
    "Key": 2,
    "Val": 677540437
    }
    ,{
    "Key": 3,
    "Val": 677540036
    }
    ,{
    "Key": 11,
    "Val": 677540181
    }
    ,{
    "Key": 201,
    "Val": 1529673345
    }
    ,{
    "Key": 203,
    "Val": 1529658601
    }
    ,{
    "Key": 1000,
    "Val": 1529658962
    }
    ,{
    "Key": 1001,
    "Val": 1529659033
    }
    ,{
    "Key": 2001,
    "Val": 1529480143
    }
    ]
    }
    ,
    "SKey": "",
    "SyncCheckKey": {
    "Count": 9,
    "List": [{
    "Key": 1,
    "Val": 677540346
    }
    ,{
    "Key": 2,
    "Val": 677540437
    }
    ,{
    "Key": 3,
    "Val": 677540036
    }
    ,{
    "Key": 11,
    "Val": 677540181
    }
    ,{
    "Key": 201,
    "Val": 1529673345
    }
    ,{
    "Key": 203,
    "Val": 1529658601
    }
    ,{
    "Key": 1000,
    "Val": 1529658962
    }
    ,{
    "Key": 1001,
    "Val": 1529659033
    }
    ,{
    "Key": 2001,
    "Val": 1529480143
    }
    ]
    }
    
    }

     后台视图方法获取接收的信息

    def get_msg(request):
        ret = {
            'code':400,
            'msg':'no message arrived'
        }
        global SYNCKEY_DICT  #设置为全局
        #1.先去查询是否有消息到达
        req_url = 'https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck'
        sync_key = []
        for item in SYNCKEY_DICT['List']:
            sync_key.append("%s_%s"%(item['Key'],item['Val']))
    
        reponse = requests.get(
            url=req_url,
            params={
                'r':int(time.time()*1000),
                'skey':TICKET_DICT['skey'],
                'sid':TICKET_DICT['wxsid'],
                'uin':TICKET_DICT['wxuin'],
                'deviceid':'e055319847811019',
                'synckey':'|'.join(sync_key)  #参数重组
            },
            cookies = ALL_COOKIE_DICT
        )
    
        if 'window.synccheck={retcode:"0",selector:"2"}' in reponse.text:
            ret['code'] = 200
            ret['msg'] = "message arrived"
            #有消息到来,这时我们需要去获取信息,并且更新SYNCKEY_DICT
            req_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync'
    
            post_dict = {
                'BaseRequest':
                    {
                        'DeviceID': "e055319847811019",
                        'Sid': TICKET_DICT['wxsid'],
                        'Skey': TICKET_DICT['skey'],
                        'Uin': TICKET_DICT['wxuin']
                    },
                'SyncKey':SYNCKEY_DICT
            }
    
            reponse2 = requests.post(
                url=req_url,
                params={
                    'sid':TICKET_DICT['wxsid'],
                    'pass_ticket':TICKET_DICT['pass_ticket'],
                    'skey':TICKET_DICT['skey'],
                    'lang': 'zh_CN'
                },
                json = post_dict
            )
    
            reponse2.encoding = "utf-8"
            rep_dict = json.loads(reponse2.text)
            SYNCKEY_DICT = rep_dict.get("SyncKey")
            if rep_dict['AddMsgCount'] != 0:
                ret['code'] = 201
                ret['msg'] = []
                for item in rep_dict['AddMsgList']:
                    ret['msg'].append(item)
    
        return HttpResponse(json.dumps(ret))

    前端修改:首先是有get_msg方法去长轮询获取接收消息和检测数据是否接收。然后针对谁发送的,谁就高亮

        <script>
        $(function(){
            bind_event();
            get_msg();
        })
    
        function bind_event() {
            $(".list-group-item").click(function(){
                $(".list-unstyled").empty();
                $(this).siblings().removeClass("active");
                $(this).addClass("active");
                var NickName = $(this).first().text().trim();
                $(".panel-title").text(NickName);
            })
        }
    
        function get_msg(){
            $.ajax({
                url:"/get-msg.html",
                type:"GET",
                dataType:"json",
                success:function(callback){
                    if (callback.code==201){
                        //这里只去看一个人的信息
                        var info = callback['msg'][0]
                        $(".list-group-item").each(function(){
                            if($(this).attr("for")==info['FromUserName']){
                                $(this).addClass("active")
                                return false;
                            }
                        })
                    }
                    get_msg();
                }
            })
        }
        </script>
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link href="/static/css/bootstrap.min.css" rel="stylesheet">
        <link href="/static/css/nifty.min.css" rel="stylesheet">
        <link href="/static/css/demo/nifty-demo-icons.min.css" rel="stylesheet">
        <link href="/static/css/demo/nifty-demo.min.css" rel="stylesheet">
        <link href="/static/plugins/pace/pace.min.css" rel="stylesheet">
        <script src="/static/js/jquery-2.2.4.min.js"></script>
        <script>
        $(function(){
            bind_event();
            get_msg();
        })
    
        function bind_event() {
            $(".list-group-item").click(function(){
                $(".list-unstyled").empty();
                $(this).siblings().removeClass("active");
                $(this).addClass("active");
                var NickName = $(this).first().text().trim();
                $(".panel-title").text(NickName);
            })
        }
    
        function get_msg(){
            $.ajax({
                url:"/get-msg.html",
                type:"GET",
                dataType:"json",
                success:function(callback){
                    if (callback.code==201){
                        //这里只去看一个人的信息
                        var info = callback['msg'][0]
                        $(".list-group-item").each(function(){
                            if($(this).attr("for")==info['FromUserName']){
                                $(this).addClass("active")
                                return false;
                            }
                        })
                    }
                    get_msg();
                }
            })
        }
        </script>
        <script src="/static/plugins/pace/pace.min.js"></script>
        <script src="/static/js/bootstrap.min.js"></script>
        <script src="/static/js/nifty.min.js"></script>
        <script src="/static/js/demo/nifty-demo.min.js"></script>
        <script src="/static/plugins/flot-charts/jquery.flot.min.js"></script>
        <script src="/static/plugins/flot-charts/jquery.flot.resize.min.js"></script>
        <script src="/static/plugins/gauge-js/gauge.min.js"></script>
        <script src="/static/plugins/skycons/skycons.min.js"></script>
        <script src="/static/plugins/easy-pie-chart/jquery.easypiechart.min.js"></script>
        <script src="/static/js/demo/widgets.js"></script>
    </head>
    <body>
    <div id="container" class="effect  aside-bright mainnav-sm aside-right aside-in">
        <div class="boxed">
            <div id="content-container">
                <div class="row">
                    <div class="col-md-8 col-lg-8 col-sm-8">
    
                <!--Chat widget-->
                <!--===================================================-->
                <div class="panel" style="height: 640px">
                    <!--Heading-->
                    <div class="panel-heading">
                        <h3 class="panel-title">Chat</h3>
                    </div>
    
                    <!--Widget body-->
                    <div style="height:510px;padding-top:0px;" class="widget-body">
                        <div class="nano">
                            <div class="nano-content pad-all">
                                <ul class="list-unstyled media-block">
                                    <li class="mar-btm">
                                        <div class="media-left">
                                            <img src="img/profile-photos/1.png" class="img-circle img-sm" alt="Profile Picture">
                                        </div>
                                        <div class="media-body pad-hor">
                                            <div class="speech">
                                                <a href="#" class="media-heading">Aaron Chavez</a>
                                                <p>Hello Lucy, how can I help you today ?</p>
                                                <p class="speech-time">
                                                <i class="demo-pli-clock icon-fw"></i>09:23AM
                                                </p>
                                            </div>
                                        </div>
                                    </li>
                                    <li class="mar-btm">
                                        <div class="media-right">
                                            <img src="img/profile-photos/8.png" class="img-circle img-sm" alt="Profile Picture">
                                        </div>
                                        <div class="media-body pad-hor speech-right">
                                            <div class="speech">
                                                <a href="#" class="media-heading">Lucy Doe</a>
                                                <p>Hi, I want to buy a new shoes.</p>
                                                <p class="speech-time">
                                                    <i class="demo-pli-clock icon-fw"></i> 09:23AM
                                                </p>
                                            </div>
                                        </div>
                                    </li>
                                </ul>
                            </div>
                        </div>
    
                        <!--Widget footer-->
                        <div class="panel-footer" style="height: 90px;">
                            <div class="row">
                                <div class="col-xs-9">
                                    <input type="text" placeholder="Enter your text" class="form-control chat-input">
                                </div>
                                <div class="col-xs-3">
                                    <button class="btn btn-primary btn-block" onclick="sendMsg(this);" type="submit">Send</button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <!--===================================================-->
                <!--Chat widget-->
    
            </div>
                    <div class="col-md-4 col-lg-4 col-sm-4">
                        <aside id="aside-container">
                    <div id="aside">
                        <div class="nano has-scrollbar">
                            <div class="nano-content" tabindex="0" style="right: -17px;">
    
                                <!--Nav tabs-->
                                <!--================================-->
                                <ul class="nav nav-tabs nav-justified">
                                    <li class="active">
                                        <a href="#demo-asd-tab-1" data-toggle="tab">
                                            <i class="demo-pli-speech-bubble-7"></i>
                                        </a>
                                    </li>
                                </ul>
                                <!--================================-->
                                <!--End nav tabs-->
    
                                <!-- Tabs Content -->
                                <!--================================-->
                                <div class="tab-content">
                                    <div class="tab-pane fade in active" id="demo-asd-tab-1">
                                        <p class="pad-hor text-semibold text-main">
                                            <span class="pull-right badge badge-success">{{ contact_info_list.MemberCount }}</span> Friends
                                        </p>
    
                                        <!--Works-->
                                        <div class="list-group bg-trans">
                                            {% for item in contact_info_list.MemberList %}
                                                <a href="#" for="{{ item.UserName }}" class="list-group-item">
                                                    <span class="badge badge-purple badge-icon badge-fw pull-left"></span> {{ item.NickName }}
                                                </a>
                                            {% endfor %}
                                        </div>
                                    </div>
                                </div>
                            </div>
                        <div class="nano-pane" style="display: none;"><div class="nano-slider" style="height: 4059px; transform: translate(0px, 0px);"></div></div></div>
                    </div>
                </aside>
                    </div>
                </div>
            </div>
        </div>
    </div>
    </body>
    </html>
    
    <script>
        function sendMsg(ths){
            var sel_tag = $(".list-group").find(".active")
            if(sel_tag.length==0){
                return false;
            }
            var msg = $(ths).parents(".panel-footer").find(".chat-input").val();
            var sendMsg={
                'ToUserName':sel_tag.attr("for"),
                'Type':1,
                'Content':msg,
                'csrfmiddlewaretoken':'{{ csrf_token }}'
            }
    
            $.ajax({
                url:"send-msg.html",
                data:sendMsg,
                type:"POST",
                dataType:"json",
                success:function(callback){
                    if (callback.code==200){
                        var dt = new Date()
                        var now_time = dt.toLocaleString();
    
                        console.log(callback);
                        var li = '<li class="mar-btm"><div class="media-right"><img src="'+callback.headImgUrl+'" class="img-circle img-sm" alt="Profile Picture"></div>';
                        li += '<div class="media-body pad-hor speech-right"><div class="speech"><a href="#" class="media-heading">'+callback.username+'</a>';
                        li += '<p>'+msg+'</p>';
                        li += '<p class="speech-time">';
                        li += '<i class="demo-pli-clock icon-fw"></i>'+now_time;
                        li += '</p></div></div></li>';
                        $(ths).parents(".widget-body").find(".list-unstyled").append(li);
                        $(ths).parents(".panel-footer").find(".chat-input").val("");
                    }
                }
            })
        }
    </script>
    contact_info前端代码

    window.synccheck={retcode:"0",selector:"2"}
    {
    "BaseResponse": {
    "Ret": 0,
    "ErrMsg": ""
    }
    ,
    "AddMsgCount": 1,
    "AddMsgList": [{
    "MsgId": "8087080836430146290",
    "FromUserName": "@7ef22458145d7446b96c0c1612549c00991cab433640c86b9c7d5f9d17dc8a43",
    "ToUserName": "@fb5a4e79e7d71ec3f11d3351fdec8a1cb5c4df7979041ed9315833e427323198",
    "MsgType": 1,
    "Content": "",
    "Status": 3,
    "ImgStatus": 1,
    "CreateTime": 1529679858,
    "VoiceLength": 0,
    "PlayLength": 0,
    "FileName": "",
    "FileSize": "",
    "MediaId": "",
    "Url": "",
    "AppMsgType": 0,
    "StatusNotifyCode": 0,
    "StatusNotifyUserName": "",
    "RecommendInfo": {
    "UserName": "",
    "NickName": "",
    "QQNum": 0,
    "Province": "",
    "City": "",
    "Content": "",
    "Signature": "",
    "Alias": "",
    "Scene": 0,
    "VerifyFlag": 0,
    "AttrStatus": 0,
    "Sex": 0,
    "Ticket": "",
    "OpCode": 0
    }
    ,
    "ForwardFlag": 0,
    "AppInfo": {
    "AppID": "",
    "Type": 0
    }
    ,
    "HasProductId": 0,
    "Ticket": "",
    "ImgHeight": 0,
    "ImgWidth": 0,
    "SubMsgType": 0,
    "NewMsgId": 8087080836430146290,
    "OriContent": "",
    "EncryFileName": ""
    }
    ],
    "ModContactCount": 0,
    "ModContactList": [],
    "DelContactCount": 0,
    "DelContactList": [],
    "ModChatRoomMemberCount": 0,
    "ModChatRoomMemberList": [],
    "Profile": {
    "BitFlag": 0,
    "UserName": {
    "Buff": ""
    }
    ,
    "NickName": {
    "Buff": ""
    }
    ,
    "BindUin": 0,
    "BindEmail": {
    "Buff": ""
    }
    ,
    "BindMobile": {
    "Buff": ""
    }
    ,
    "Status": 0,
    "Sex": 0,
    "PersonalCard": 0,
    "Alias": "",
    "HeadImgUpdateFlag": 0,
    "HeadImgUrl": "",
    "Signature": ""
    }
    ,
    "ContinueFlag": 0,
    "SyncKey": {
    "Count": 8,
    "List": [{
    "Key": 1,
    "Val": 677540346
    }
    ,{
    "Key": 2,
    "Val": 677540469
    }
    ,{
    "Key": 3,
    "Val": 677540464
    }
    ,{
    "Key": 11,
    "Val": 677540440
    }
    ,{
    "Key": 201,
    "Val": 1529679858
    }
    ,{
    "Key": 1000,
    "Val": 1529658962
    }
    ,{
    "Key": 1001,
    "Val": 1529659033
    }
    ,{
    "Key": 2001,
    "Val": 1529480143
    }
    ]
    }
    ,
    "SKey": "",
    "SyncCheckKey": {
    "Count": 8,
    "List": [{
    "Key": 1,
    "Val": 677540346
    }
    ,{
    "Key": 2,
    "Val": 677540469
    }
    ,{
    "Key": 3,
    "Val": 677540464
    }
    ,{
    "Key": 11,
    "Val": 677540440
    }
    ,{
    "Key": 201,
    "Val": 1529679858
    }
    ,{
    "Key": 1000,
    "Val": 1529658962
    }
    ,{
    "Key": 1001,
    "Val": 1529659033
    }
    ,{
    "Key": 2001,
    "Val": 1529480143
    }
    ]
    }
    
    }
    后端打印的数据

    其实应该更进一步,显示出来我们接受的数据,但是明天考试..不再继续了

    八:全部代码

    后端:

    from django.shortcuts import render,HttpResponse,redirect
    from bs4 import BeautifulSoup
    import requests
    import time,re,json
    
    CTIME = None
    QCODE = None
    TIP = 1
    TICKET_DICT = {}    #保存凭证信息
    ALL_COOKIE_DICT = {}    #保存所有COOKIE信息
    USER_INIT_DICT = {} #保存用户最近联系信息,和自己的信息
    SYNCKEY_DICT = {}    #用于保存获取请求时需要的SyncKey
    
    
    # Create your views here.
    def login(request):
        global CTIME
        global QCODE
        CTIME = int(time.time()*1000)
    
        data = {
            'appid':'wx782c26e4c19acffb',
            'fun':'new',
            'lang':'zh_CN',
            '_':CTIME
        }
    
        response = requests.get(
            url="https://login.wx.qq.com/jslogin",
            params=data
        )
    
        pat_res = re.findall('uuid = "(.*)";',response.text)
        QCODE = pat_res[0]
    
        return render(request,"login.html",{'qcode':QCODE})
    
    def check_login(request):
        global TIP
        ret = {'code':408,'data':None}
        data = {
            'loginicon':"true",
            'uuid':QCODE,
            'tip':TIP,
            'r':'-577317906',
            '_':int(time.time())
        }
        r1 = requests.get(
            url='https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login',
            params=data
        )
    
        if 'window.code=408' in r1.text:
            print("无人扫描")
            return HttpResponse(json.dumps(ret))
        elif 'window.code=201' in r1.text:
            ret['code'] = 201
            pat_ret = re.findall("window.userAvatar = '(.*)';",r1.text)[0]
            ret['data'] = pat_ret
            TIP = 0
            return HttpResponse(json.dumps(ret))
        elif 'window.code=200;' in r1.text:
            ret['code'] = 200
            redirect_url = re.findall('window.redirect_uri="(.*)";', r1.text)[0]
            reponse = requests.get(     #获取凭证,这里也开始设置cookie了,所以我们在这里向后需要记录cookie
                url=redirect_url + "&fun=new&version=v2"  # url不够完整,需要我们完善
            )
            ALL_COOKIE_DICT.update(reponse.cookies)
    
            soup = BeautifulSoup(reponse.text, "lxml")
            info_dict = {}
            for tag in soup.find("error").children:
                info_dict[tag.name] = tag.get_text()
    
            global TICKET_DICT
            TICKET_DICT.update(info_dict)
    
            ret['code']=200
    
            return HttpResponse(json.dumps(ret))
    
    
    def user(request):
        get_user_info_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-613135321&pass_ticket=' + TICKET_DICT[
            'pass_ticket']
        get_user_info_form = {
            'BaseRequest':
                {
                    'DeviceID': "e055319847811019",
                    'Sid': TICKET_DICT['wxsid'],
                    'Skey': TICKET_DICT['skey'],
                    'Uin': TICKET_DICT['wxuin']
                }
        }
    
        reponse2 = requests.post(  # 获取的是用户信息,几个联系人,公众号,自己信息
            url=get_user_info_url,
            json=get_user_info_form,  # 注意这里使用的是json,post不允许传送字典
        )
        ALL_COOKIE_DICT.update(reponse2.cookies)
    
        reponse2.encoding = "utf-8"
    
        user_info_dict = json.loads(reponse2.text)  # 获取的是用户信息,几个联系人,公众号,自己信息
        USER_INIT_DICT.update(user_info_dict)
        SYNCKEY_DICT.update(user_info_dict['SyncKey'])
    
        return render(request, "user.html", {'user_info_dict': user_info_dict})
    
    
    def contact_list(request):
        get_all_user_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket=%s&r=%s&seq=0&skey=%s' % (TICKET_DICT['pass_ticket'],int(time.time()*1000),TICKET_DICT['skey'])
    
        reponse = requests.get(
            url=get_all_user_url,   #这里需要用到cookie
            cookies=ALL_COOKIE_DICT
        )
    
        reponse.encoding = "utf-8"
        contact_info_list = json.loads(reponse.text)
    
        return render(request,"contact_info.html",{'contact_info_list':contact_info_list})
    
    def send_msg(request):
        ret = {
            'code':200,
            'error':'Send Success',
            'data':{}
        }
    
        recv_data = request.POST
    
        if not recv_data:
            ret['code']=400
            ret['data']="Send failure"
            return HttpResponse(json.dumps(ret))
    
        #数据整合
        Send_data={}
        Send_data['BaseRequest'] = {
            'DeviceID': "e055319847811019",
            'Sid': TICKET_DICT['wxsid'],
            'Skey': TICKET_DICT['skey'],
            'Uin': TICKET_DICT['wxuin']
        }
    
        Send_data['Msg'] = {
            'Type':recv_data.get("Type",1),
            'Content':recv_data.get("Content"),
            'FromUserName':USER_INIT_DICT['User']['UserName'],
            'ToUserName':recv_data.get("ToUserName"),
            'LocalID':int(time.time()*1000),
            'ClientMsgId':int(time.time()*1000),
        }
        Send_data['Scene']=0
    
        send_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&pass_ticket=%s'%TICKET_DICT['pass_ticket']
        # reponse = requests.post(
        #     url=send_url,
        #     json=Send_data, #注意这里如果使用json,会将中文转换为Unicode
        #     cookies=ALL_COOKIE_DICT
        # )
        reponse = requests.post(
            url=send_url,
            #若是有中文,需要加上ensure_ascii=False,若是字符串中含有中文,request传递数据时,将中文转换为字节,无法为我们转换。需要我们提前使用encoding编码,直接传递字节,不让requests为我们转换
            #data可以是字典,字符串,字节,既然对于字典,字符串直接含有中文不正确,直接转字节传送,py3默认是utf-8,所以我们直接传送字节就可以
            data=bytes(json.dumps(Send_data,ensure_ascii=False),encoding="utf-8"), #注意这里如果使用json,会将中文转换为Unicode
            cookies=ALL_COOKIE_DICT
        )
    
        reponse.encoding = "utf-8"
    
        ret_status = re.findall('"Ret": (.*),', reponse.text)[0]
        ret_error = re.findall('"ErrMsg": "(.*)"', reponse.text)[0]
    
        if int(ret_status) != 0:
            ret['code']=401
            ret['data']=ret_error
            return HttpResponse(json.dumps(ret))
    
        ret['username'] = USER_INIT_DICT['User']['NickName']
        ret['headImgUrl'] = 'https://wx.qq.com'+USER_INIT_DICT['User']['HeadImgUrl']
    
        return HttpResponse(json.dumps(ret))
    
    def get_msg(request):
        ret = {
            'code':400,
            'msg':'no message arrived'
        }
        global SYNCKEY_DICT
        #1.先去查询是否有消息到达
        req_url = 'https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck'
        sync_key = []
        for item in SYNCKEY_DICT['List']:
            sync_key.append("%s_%s"%(item['Key'],item['Val']))
    
        reponse = requests.get(
            url=req_url,
            params={
                'r':int(time.time()*1000),
                'skey':TICKET_DICT['skey'],
                'sid':TICKET_DICT['wxsid'],
                'uin':TICKET_DICT['wxuin'],
                'deviceid':'e055319847811019',
                'synckey':'|'.join(sync_key)
            },
            cookies = ALL_COOKIE_DICT
        )
    
        if 'window.synccheck={retcode:"0",selector:"2"}' in reponse.text:
            ret['code'] = 200
            ret['msg'] = "message arrived"
            #有消息到来,这时我们需要去获取信息,并且更新SYNCKEY_DICT
            req_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync'
    
            post_dict = {
                'BaseRequest':
                    {
                        'DeviceID': "e055319847811019",
                        'Sid': TICKET_DICT['wxsid'],
                        'Skey': TICKET_DICT['skey'],
                        'Uin': TICKET_DICT['wxuin']
                    },
                'SyncKey':SYNCKEY_DICT
            }
    
            reponse2 = requests.post(
                url=req_url,
                params={
                    'sid':TICKET_DICT['wxsid'],
                    'pass_ticket':TICKET_DICT['pass_ticket'],
                    'skey':TICKET_DICT['skey'],
                    'lang': 'zh_CN'
                },
                json = post_dict
            )
    
            reponse2.encoding = "utf-8"
            rep_dict = json.loads(reponse2.text)
            SYNCKEY_DICT = rep_dict.get("SyncKey")
            if rep_dict['AddMsgCount'] != 0:
                ret['code'] = 201
                ret['msg'] = []
                for item in rep_dict['AddMsgList']:
                    ret['msg'].append(item)
    
        return HttpResponse(json.dumps(ret))
    views.py

    前端:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <img id="qrcode" style=" 340px;height: 340px;" src="https://login.weixin.qq.com/qrcode/{{ qcode }}" alt="">
    </body>
    </html>
    <script src="/static/jquery.js"></script>
    <script>
        $(function(){
            checkLogin();
        })
    
        function checkLogin() {
            $.ajax({
                url:'/check-login.html',
                type:'GET',
                dataType:"json",
                success:function(data){
                    console.log(data.code);
                    if (data.code==408){
                        checkLogin();
                    }
                    else if(data.code==201){
                        $("#qrcode").attr('src',data.data)
                        checkLogin();
                    }
                    else if(data.code==200){
                        location.href='/user.html'
                    }
                }
            })
        }
    </script>
    login.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div>
            <h3>最近联系人</h3>
            <ul>
                {% for item in user_info_dict.ContactList %}
                    <li>{{ item.NickName }}</li>
                {% endfor %}
            </ul>
            <a href="/contact-list.html">获取更多联系人</a>
        </div>
        <div>
            <h3>微信公众号</h3>
            <div>
                {% for item in user_info_dict.MPSubscribeMsgList %}
                    <h4>{{ item.NickName }}</h4>
                    <ul>
                        {% for item2 in item.MPArticleList %}
                            <li>
                                <a href="{{ item2.Url }}">
                                    {{ item2.Title }}
                                </a>
                            </li>
                        {% endfor %}
                    </ul>
                {% endfor %}
            </div>
        </div>
    </body>
    </html>
    user.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link href="/static/css/bootstrap.min.css" rel="stylesheet">
        <link href="/static/css/nifty.min.css" rel="stylesheet">
        <link href="/static/css/demo/nifty-demo-icons.min.css" rel="stylesheet">
        <link href="/static/css/demo/nifty-demo.min.css" rel="stylesheet">
        <link href="/static/plugins/pace/pace.min.css" rel="stylesheet">
        <script src="/static/js/jquery-2.2.4.min.js"></script>
        <script>
        $(function(){
            bind_event();
            get_msg();
        })
    
        function bind_event() {
            $(".list-group-item").click(function(){
                $(".list-unstyled").empty();
                $(this).siblings().removeClass("active");
                $(this).addClass("active");
                var NickName = $(this).first().text().trim();
                $(".panel-title").text(NickName);
            })
        }
    
        function get_msg(){
            $.ajax({
                url:"/get-msg.html",
                type:"GET",
                dataType:"json",
                success:function(callback){
                    if (callback.code==201){
                        //这里只去看一个人的信息
                        var info = callback['msg'][0]
                        $(".list-group-item").each(function(){
                            if($(this).attr("for")==info['FromUserName']){
                                $(this).addClass("active")
                                return false;
                            }
                        })
                    }
                    get_msg();
                }
            })
        }
        </script>
        <script src="/static/plugins/pace/pace.min.js"></script>
        <script src="/static/js/bootstrap.min.js"></script>
        <script src="/static/js/nifty.min.js"></script>
        <script src="/static/js/demo/nifty-demo.min.js"></script>
        <script src="/static/plugins/flot-charts/jquery.flot.min.js"></script>
        <script src="/static/plugins/flot-charts/jquery.flot.resize.min.js"></script>
        <script src="/static/plugins/gauge-js/gauge.min.js"></script>
        <script src="/static/plugins/skycons/skycons.min.js"></script>
        <script src="/static/plugins/easy-pie-chart/jquery.easypiechart.min.js"></script>
        <script src="/static/js/demo/widgets.js"></script>
    </head>
    <body>
    <div id="container" class="effect  aside-bright mainnav-sm aside-right aside-in">
        <div class="boxed">
            <div id="content-container">
                <div class="row">
                    <div class="col-md-8 col-lg-8 col-sm-8">
    
                <!--Chat widget-->
                <!--===================================================-->
                <div class="panel" style="height: 640px">
                    <!--Heading-->
                    <div class="panel-heading">
                        <h3 class="panel-title">Chat</h3>
                    </div>
    
                    <!--Widget body-->
                    <div style="height:510px;padding-top:0px;" class="widget-body">
                        <div class="nano">
                            <div class="nano-content pad-all">
                                <ul class="list-unstyled media-block">
                                    <li class="mar-btm">
                                        <div class="media-left">
                                            <img src="img/profile-photos/1.png" class="img-circle img-sm" alt="Profile Picture">
                                        </div>
                                        <div class="media-body pad-hor">
                                            <div class="speech">
                                                <a href="#" class="media-heading">Aaron Chavez</a>
                                                <p>Hello Lucy, how can I help you today ?</p>
                                                <p class="speech-time">
                                                <i class="demo-pli-clock icon-fw"></i>09:23AM
                                                </p>
                                            </div>
                                        </div>
                                    </li>
                                    <li class="mar-btm">
                                        <div class="media-right">
                                            <img src="img/profile-photos/8.png" class="img-circle img-sm" alt="Profile Picture">
                                        </div>
                                        <div class="media-body pad-hor speech-right">
                                            <div class="speech">
                                                <a href="#" class="media-heading">Lucy Doe</a>
                                                <p>Hi, I want to buy a new shoes.</p>
                                                <p class="speech-time">
                                                    <i class="demo-pli-clock icon-fw"></i> 09:23AM
                                                </p>
                                            </div>
                                        </div>
                                    </li>
                                </ul>
                            </div>
                        </div>
    
                        <!--Widget footer-->
                        <div class="panel-footer" style="height: 90px;">
                            <div class="row">
                                <div class="col-xs-9">
                                    <input type="text" placeholder="Enter your text" class="form-control chat-input">
                                </div>
                                <div class="col-xs-3">
                                    <button class="btn btn-primary btn-block" onclick="sendMsg(this);" type="submit">Send</button>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
                <!--===================================================-->
                <!--Chat widget-->
    
            </div>
                    <div class="col-md-4 col-lg-4 col-sm-4">
                        <aside id="aside-container">
                    <div id="aside">
                        <div class="nano has-scrollbar">
                            <div class="nano-content" tabindex="0" style="right: -17px;">
    
                                <!--Nav tabs-->
                                <!--================================-->
                                <ul class="nav nav-tabs nav-justified">
                                    <li class="active">
                                        <a href="#demo-asd-tab-1" data-toggle="tab">
                                            <i class="demo-pli-speech-bubble-7"></i>
                                        </a>
                                    </li>
                                </ul>
                                <!--================================-->
                                <!--End nav tabs-->
    
                                <!-- Tabs Content -->
                                <!--================================-->
                                <div class="tab-content">
                                    <div class="tab-pane fade in active" id="demo-asd-tab-1">
                                        <p class="pad-hor text-semibold text-main">
                                            <span class="pull-right badge badge-success">{{ contact_info_list.MemberCount }}</span> Friends
                                        </p>
    
                                        <!--Works-->
                                        <div class="list-group bg-trans">
                                            {% for item in contact_info_list.MemberList %}
                                                <a href="#" for="{{ item.UserName }}" class="list-group-item">
                                                    <span class="badge badge-purple badge-icon badge-fw pull-left"></span> {{ item.NickName }}
                                                </a>
                                            {% endfor %}
                                        </div>
                                    </div>
                                </div>
                            </div>
                        <div class="nano-pane" style="display: none;"><div class="nano-slider" style="height: 4059px; transform: translate(0px, 0px);"></div></div></div>
                    </div>
                </aside>
                    </div>
                </div>
            </div>
        </div>
    </div>
    </body>
    </html>
    
    <script>
        function sendMsg(ths){
            var sel_tag = $(".list-group").find(".active")
            if(sel_tag.length==0){
                return false;
            }
            var msg = $(ths).parents(".panel-footer").find(".chat-input").val();
            var sendMsg={
                'ToUserName':sel_tag.attr("for"),
                'Type':1,
                'Content':msg,
                'csrfmiddlewaretoken':'{{ csrf_token }}'
            }
    
            $.ajax({
                url:"send-msg.html",
                data:sendMsg,
                type:"POST",
                dataType:"json",
                success:function(callback){
                    if (callback.code==200){
                        var dt = new Date()
                        var now_time = dt.toLocaleString();
    
                        console.log(callback);
                        var li = '<li class="mar-btm"><div class="media-right"><img src="'+callback.headImgUrl+'" class="img-circle img-sm" alt="Profile Picture"></div>';
                        li += '<div class="media-body pad-hor speech-right"><div class="speech"><a href="#" class="media-heading">'+callback.username+'</a>';
                        li += '<p>'+msg+'</p>';
                        li += '<p class="speech-time">';
                        li += '<i class="demo-pli-clock icon-fw"></i>'+now_time;
                        li += '</p></div></div></li>';
                        $(ths).parents(".widget-body").find(".list-unstyled").append(li);
                        $(ths).parents(".panel-footer").find(".chat-input").val("");
                    }
                }
            })
        }
    </script>
    contact_info.html

    需要:nifty插件可以联系我

  • 相关阅读:
    linux下安装jmeter
    Jmeter 跨线程组传递参数 之两种方法
    Jmeter之Json Path Extractor 接受上一个请求的响应参数
    Jmeter之添加响应断言,bean shell post processor
    Jmeter 分布式压力测试
    Jmeter之一个请求获取上一个请求的参数
    selenium自动化测试实例
    SqlBulkCopy类进行大数据(一万条以上)插入测试
    SqlServer存储过程传入Table参数
    Asp.Net EF Code First 简单入门
  • 原文地址:https://www.cnblogs.com/ssyfj/p/9210725.html
Copyright © 2020-2023  润新知