python 网页微信_python---web微信开发

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

轮询:

在前端,设置时间内,一直向后端发送请求。

例如:使用setInterval方法设置定时器,一秒向后端发送一次请求,去主动获取数据,进行更新

由于前端一直请求,后端压力太大。而且当没有数据更新,前端一直去请求,太浪费了,没必要。

代码简单

长轮询:

在轮询的基础上,加以改造。Http请求到来,若是不主动close或者return,则连接会一直存在。但是不要让这个时间太长,会占用太多资源

例如:当前端发送请求,后端拿到后,不去关闭,而是等待一段时间,在这段时间内若是有数据到达,立刻返回,否则直到等待时间结束。

然后返回给前端,前端马上又发起一次请求......

消息是实时获取。

WebSocket:

http是单向请求,客户端去服务端获取数据。服务端不能主动推送消息。

而websocket类似于socket,可以实现双向发送,

实现当数据更新,可以主动推送

二:web微信流程介绍

三:微信登录开发

fromdjango.shortcuts import render,HttpResponsefrombs4 import BeautifulSoup

import requests

import time,re,json

CTIME=None  #用于保存全局时间戳

QCODE=None  #当我们访问二维码时,会产生一个UUID,我们将其存放为全局

TIP= 1  #url中的一个参数tip,当其为1:代表我们还没有扫描二维码,当其为0:扫描了二维码

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

def login(request):globalCTIMEglobalQCODE

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):globalTIP

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' inr1.text:

print("无人扫描")returnHttpResponse(json.dumps(ret))

elif'window.code=201' inr1.text:

ret['code'] = 201pat_ret= re.findall("window.userAvatar = '(.*)';",r1.text)[0]

ret['data'] =pat_ret

TIP= 0

returnHttpResponse(json.dumps(ret))

elif'window.code=200;' inr1.text:

ret['code'] = 200redirect_url= re.findall('window.redirect_uri="(.*)";',r1.text)[0]

reponse= requests.get(

url=redirect_url+"&fun=new&version=v2"#url不够完整,需要我们完善

)

# print(reponse.text) #0@crypt_7358fe11_af06754907ad9c216768337d80cf0ce7icUySQoySDi2OZFK2821071261IWScm1SE%2BGQ%2BNEaghUBCxbF3xPJSzqXUGTO6BYh3TBEGlw8Wa7qETkA9EEAUudYU1soup= 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-----------------------------------------------------------------

0

@crypt_7358fe11_ea821d506c39f7d75a3e83b4233caab4

qUJZlkBIWQ0130QI

2821071261

xNiKeCBgFkMBfEK8oOK3Gp9qj%2F1HfLpcfPrDwGv3A4nltKskVqoxkECrVYEN9eJJ

1

新请求:获取用户所有信息,最近联系人和公众号 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详细请求

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

Title

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();

}

}

})

}

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

user_dict ={}for item inuser_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})

相关数据打印(格式)

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

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

fromdjango.shortcuts import render,HttpResponse,redirectfrombs4 import BeautifulSoup

import requests

import time,re,json

CTIME=None

QCODE=None

TIP= 1TICKET_DICT={} #保存凭证信息

ALL_COOKIE_DICT={}

# Create your views here.

def login(request):globalCTIMEglobalQCODE

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):globalTIP

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' inr1.text:

print("无人扫描")returnHttpResponse(json.dumps(ret))

elif'window.code=201' inr1.text:

ret['code'] = 201pat_ret= re.findall("window.userAvatar = '(.*)';",r1.text)[0]

ret['data'] =pat_ret

TIP= 0

returnHttpResponse(json.dumps(ret))

elif'window.code=200;' inr1.text:

ret['code'] = 200redirect_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()globalTICKET_DICT

TICKET_DICT.update(info_dict)

ret['code']=200

returnHttpResponse(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})

前端代码

Title

最近联系人

  • {% for item in user_info_dict.ContactList %}
  • {{ item.NickName }}{% endfor %}

获取更多联系人

微信公众号

{% for item in user_info_dict.MPSubscribeMsgList %}
{{ item.NickName }}
{% endfor %}

五:显示所有联系人

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

fromdjango.shortcuts import render,HttpResponse,redirectfrombs4 import BeautifulSoup

import requests

import time,re,json

CTIME=None

QCODE=None

TIP= 1TICKET_DICT={} #保存凭证信息

ALL_COOKIE_DICT={}

# Create your views here.

def login(request):globalCTIMEglobalQCODE

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):globalTIP

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' inr1.text:

print("无人扫描")returnHttpResponse(json.dumps(ret))

elif'window.code=201' inr1.text:

ret['code'] = 201pat_ret= re.findall("window.userAvatar = '(.*)';",r1.text)[0]

ret['data'] =pat_ret

TIP= 0

returnHttpResponse(json.dumps(ret))

elif'window.code=200;' inr1.text:

ret['code'] = 200redirect_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()globalTICKET_DICT

TICKET_DICT.update(info_dict)

ret['code']=200

returnHttpResponse(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})

前端代码:

Title

全部联系人列表

  • {% for item in contact_info_list.MemberList %}
  • {{ item.NickName }}{% endfor %}

六:模拟发送信息

发送信息的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页面

$(".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);

})

})

}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 = newDate()var now_time =dt.toLocaleString();

console.log(callback);var li = '

Profile Picture
';

li+= '

'+callback.username+'';

li+= '

'+msg+'

';

li+= '

';

li+= ''+now_time;

li+= '

';

$(ths).parents(".widget-body").find(".list-unstyled").append(li);

$(ths).parents(".panel-footer").find(".chat-input").val("");

}

}

})

}

前端代码使用ajax向后端传送

后端代码send_msg

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

def send_msg(request):

ret={'code':200,'error':'Send Success','data':{}

}

recv_data=request.POSTifnot recv_data:

ret['code']=400ret['data']="Send failure"

returnHttpResponse(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']=0send_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']=401ret['data']=ret_errorreturnHttpResponse(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_6775403461 677540346#和上一个请求url中接收的数据一致%7C |2_6775404232 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:
@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'}globalSYNCKEY_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"}' inreponse.text:

ret['code'] = 200ret['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'] = 201ret['msg'] =[]for item in rep_dict['AddMsgList']:

ret['msg'].append(item)return HttpResponse(json.dumps(ret))

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

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();

}

})

}

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();

}

})

}

}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 = newDate()var now_time =dt.toLocaleString();

console.log(callback);var li = '

Profile Picture
';

li+= '

'+callback.username+'';

li+= '

'+msg+'

';

li+= '

';

li+= ''+now_time;

li+= '

';

$(ths).parents(".widget-body").find(".list-unstyled").append(li);

$(ths).parents(".panel-footer").find(".chat-input").val("");

}

}

})

}

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}

]

}

}

后端打印的数据

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

八:全部代码

后端:

fromdjango.shortcuts import render,HttpResponse,redirectfrombs4 import BeautifulSoup

import requests

import time,re,json

CTIME=None

QCODE=None

TIP= 1TICKET_DICT={} #保存凭证信息

ALL_COOKIE_DICT={} #保存所有COOKIE信息

USER_INIT_DICT={} #保存用户最近联系信息,和自己的信息

SYNCKEY_DICT={} #用于保存获取请求时需要的SyncKey

# Create your views here.

def login(request):globalCTIMEglobalQCODE

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):globalTIP

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' inr1.text:

print("无人扫描")returnHttpResponse(json.dumps(ret))

elif'window.code=201' inr1.text:

ret['code'] = 201pat_ret= re.findall("window.userAvatar = '(.*)';",r1.text)[0]

ret['data'] =pat_ret

TIP= 0

returnHttpResponse(json.dumps(ret))

elif'window.code=200;' inr1.text:

ret['code'] = 200redirect_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()globalTICKET_DICT

TICKET_DICT.update(info_dict)

ret['code']=200

returnHttpResponse(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.POSTifnot recv_data:

ret['code']=400ret['data']="Send failure"

returnHttpResponse(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']=0send_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']=401ret['data']=ret_errorreturnHttpResponse(json.dumps(ret))

ret['username'] = USER_INIT_DICT['User']['NickName']

ret['headImgUrl'] = 'https://wx.qq.com'+USER_INIT_DICT['User']['HeadImgUrl']returnHttpResponse(json.dumps(ret))

def get_msg(request):

ret={'code':400,'msg':'no message arrived'}globalSYNCKEY_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"}' inreponse.text:

ret['code'] = 200ret['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'] = 201ret['msg'] =[]for item in rep_dict['AddMsgList']:

ret['msg'].append(item)return HttpResponse(json.dumps(ret))

views.py

前端:

Title

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'}

}

})

}

login.html

Title

最近联系人

  • {% for item in user_info_dict.ContactList %}
  • {{ item.NickName }}{% endfor %}

获取更多联系人

微信公众号

{% for item in user_info_dict.MPSubscribeMsgList %}
{{ item.NickName }}
{% endfor %}

user.html

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();

}

})

}

}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 = newDate()var now_time =dt.toLocaleString();

console.log(callback);var li = '

Profile Picture
';

li+= '

'+callback.username+'';

li+= '

'+msg+'

';

li+= '

';

li+= ''+now_time;

li+= '

';

$(ths).parents(".widget-body").find(".list-unstyled").append(li);

$(ths).parents(".panel-footer").find(".chat-input").val("");

}

}

})

}

contact_info.html

需要:nifty插件可以联系我

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值