一:轮询,长轮询,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详细请求
前端代码:显示二维码和头像
TitlecheckLogin();
})
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微信公众号
{{ item.NickName }}
- {% for item2 in item.MPArticleList %}
- {% 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);
})
})
Chat
}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 = '
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();
}
})
}
Chat
}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 = '
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
前端:
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
微信公众号
{{ item.NickName }}
- {% for item2 in item.MPArticleList %}
- {% 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();
}
})
}
Chat
}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 = '
li+= '
$(ths).parents(".widget-body").find(".list-unstyled").append(li);
$(ths).parents(".panel-footer").find(".chat-input").val("");
}
}
})
}
contact_info.html
需要:nifty插件可以联系我