1 D:\soft\work\Python_17\day23\weixin>tree /F 2 卷 NewDisk 的文件夹 PATH 列表 3 卷序列号为 2E8B-8205 4 D:. 5 │ db.sqlite3 6 │ manage.py 7 │ 8 ├─.idea 9 │ │ misc.xml 10 │ │ modules.xml 11 │ │ weixin.iml 12 │ │ workspace.xml 13 │ │ 14 │ └─inspectionProfiles 15 │ profiles_settings.xml 16 │ 17 ├─statics 18 │ ├─css 19 │ │ bbs.css 20 │ │ bootstrap-select.min.css 21 │ │ bootstrap-theme.css 22 │ │ bootstrap-theme.css.map 23 │ │ bootstrap-theme.min.css 24 │ │ bootstrap-theme.min.css.map 25 │ │ bootstrap.css 26 │ │ bootstrap.css.map 27 │ │ bootstrap.min.css 28 │ │ bootstrap.min.css.map 29 │ │ bootstrapValidator.min.css 30 │ │ 31 │ ├─fonts 32 │ │ glyphicons-halflings-regular.eot 33 │ │ glyphicons-halflings-regular.svg 34 │ │ glyphicons-halflings-regular.ttf 35 │ │ glyphicons-halflings-regular.woff 36 │ │ glyphicons-halflings-regular.woff2 37 │ │ 38 │ └─js 39 │ bootstrap-select.js.map 40 │ bootstrap-select.min.js 41 │ bootstrap.js 42 │ bootstrap.min.js 43 │ bootstrapValidator.min.js 44 │ city_info.js 45 │ jquery-3.2.1.js 46 │ jquery-3.2.1.min.js 47 │ jquery.cookie.js 48 │ npm.js 49 │ 50 ├─templates 51 │ contactList.html 52 │ index.html 53 │ login.html 54 │ 55 ├─utils 56 │ │ get_sync_key.py 57 │ │ myResponse.py 58 │ │ 59 │ └─__pycache__ 60 │ get_sync_key.cpython-35.pyc 61 │ myResponse.cpython-35.pyc 62 │ 63 ├─wechat 64 │ │ admin.py 65 │ │ apps.py 66 │ │ demo.py 67 │ │ models.py 68 │ │ tests.py 69 │ │ views.py 70 │ │ __init__.py 71 │ │ 72 │ ├─migrations 73 │ │ │ __init__.py 74 │ │ │ 75 │ │ └─__pycache__ 76 │ │ __init__.cpython-35.pyc 77 │ │ 78 │ └─__pycache__ 79 │ admin.cpython-35.pyc 80 │ apps.cpython-35.pyc 81 │ models.cpython-35.pyc 82 │ views.cpython-35.pyc 83 │ __init__.cpython-35.pyc 84 │ 85 └─weixin 86 │ settings.py 87 │ urls.py 88 │ wsgi.py 89 │ __init__.py 90 │ 91 └─__pycache__ 92 settings.cpython-35.pyc 93 urls.cpython-35.pyc 94 wsgi.cpython-35.pyc 95 __init__.cpython-35.pyc 96 97 98 D:\soft\work\Python_17\day23\weixin>
# login.html
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<img id="wx_pic" src="{{ img_url }}" style="height: 200px; width: 200px">
</div>
<script src="{% static "js/jquery-3.2.1.js" %}"></script>
<script>
$(function () {
checkLogin();
});
function checkLogin() {
TIP = 0;
console.log("checkLogin ... ");
$.ajax({
url: ‘/loginCheck.htm‘,
type: ‘GET‘,
data: {‘tip‘:TIP},
success:function (data) {
var data=JSON.parse(data);
if(‘201‘ == data.code){
$("#wx_pic").attr(‘src‘,data.data);
checkLogin();
{# tip=0;#}
}
else if(‘200‘ == data.code){
location.href = ‘/index.htm‘;
}
else {
console.log(">>> "+data.code);
checkLogin();
}
console.log(typeof data);
console.log(data);
}
})
}
</script>
</body>
</html>
# index.html
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>个人信息</h3>
<img src="/showAvatar.htm?img={{ init_dict.User.HeadImgUrl }}" >
<ul>
<li>{{ init_dict.User.NickName }}</li>
<li>{{ init_dict.User.UserName }}</li>
<li>{{ init_dict.User.Signature }}</li>
</ul>
<h3>最近联系人列表</h3>
<ul>
{% for item in init_dict.ContactList %}
<img src="/showAvatar.htm?img={{ item.HeadImgUrl }}" >
<li>{{ item.NickName }}</li>
<li>{{ item.UserName }}</li>
<li>{{ item.Signature }}</li>
{% endfor %}
<li><a href="/contactList.htm">查看所有联系人</a></li>
</ul>
<script src="{% static "js/jquery-3.2.1.js" %}"></script>
<script>
</script>
</body>
</html>
# contactList.html
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{% static "css/bootstrap.css" %}">
<script src="{% static "js/bootstrap.js" %}"></script>
</head>
<body>
<h3>发送消息...</h3>
{% csrf_token %}
<div class="input-group">
<span class="input-group-addon" id="sizing-addon2">发送给谁</span>
<input type="text" class="form-control" placeholder="请输入对方的id" aria-describedby="sizing-addon2" id="to_user">
</div>
<div class="input-group">
<span class="input-group-addon" id="sizing-addon2">消息内容</span>
<input type="text" class="form-control" placeholder="请输入要发送的内容" aria-describedby="sizing-addon2" id="msg">
</div>
<button id="btn" type="button" class="btn btn-success">发送</button>
<button id="logout" type="button" class="btn btn-info">退出登录</button>
<div class="private">
<h3>个人信息</h3>
<img src="/showAvatar.htm?img={{ init_dict.User.HeadImgUrl }}" >
<ul>
<li>{{ init_dict.User.NickName }}</li>
<li>{{ init_dict.User.UserName }}</li>
<li>{{ init_dict.User.Signature }}</li>
</ul>
</div>
<div class="contactList">
<h3>联系人列表</h3>
<ul>
{% for user in contact_list_dict.MemberList %}
<li>{{ user.UserName }}</li>
<li>{{ user.NickName }}</li>
<li>{{ user.RemarkName }}</li>
<li>{{ user.Signature }}</li>
<ul>
<li>{{ user.Province }}</li>
<li>{{ user.City }}</li>
</ul>
{% endfor %}
</ul>
</div>
<script src="{% static "js/jquery-3.2.1.js" %}"></script>
<script src="{% static "js/jquery.cookie.js" %}"></script>
<script>
$(function () {
getMsg();
bindBtnEvent();
bindLogoutEvent();
});
function bindBtnEvent() {
$("#btn").click(function () {
$.ajax({
url:‘/sendMsg.htm‘,
type:‘POST‘,
data:{‘to_user‘:$("#to_user").val(),‘msg‘:$("#msg").val()},
headers:{‘X-CSRFToken‘: $.cookie(‘csrftoken‘)},
success:function (res) {
var data=JSON.parse(res);
if(0 == data.BaseResponse.Ret){
alert("消息发送成功!");
}else {
alert("消息发送失败:" + data.BaseResponse.ErrMsg);
}
},
error:function (res) {
console.log("[[ bindBtnEvent ]] raise err..." + res)
}
})
})
}
function getMsg() {
$.ajax({
url:‘/syncCheck.htm‘,
type:‘GET‘,
success:function (res) {
var data=JSON.parse(res);
if(data.AddMsgCount > 0){
alert(data.AddMsgList);
for(var i=0; i<data.AddMsgCount; i++) {
alert("收到 " + data.AddMsgList[i].FromUserName + " 的新消息:" + data.AddMsgList[i].Content);
}
}
getMsg();
},
error:function (res) {
console.log("[[ getMsg ]] raise err..." + res);
getMsg();
}
})
}
function bindLogoutEvent() {
$("#logout").click(function () {
$.ajax({
url:‘/logout.htm‘,
type:‘GET‘,
success:function (arg) {
}
})
})
}
</script>
</body>
</html>
# urls.py
from django.conf.urls import url
from django.contrib import admin
from wechat import views
urlpatterns = [
url(r‘^admin/‘, admin.site.urls),
url(r‘^login.htm$‘, views.login),
url(r‘^loginCheck.htm$‘, views.loginCheck),
url(r‘^index.htm$‘, views.index),
url(r‘^showAvatar.htm$‘, views.showAvatar),
url(r‘^contactList.htm$‘, views.contactList),
url(r‘^sendMsg.htm$‘, views.sendMsg),
url(r‘^syncCheck.htm$‘, views.syncCheck),
url(r‘^logout.htm$‘, views.logout),
]
# views.py
from django.shortcuts import render,HttpResponse,redirect
import re
import time
import json
import requests
from bs4 import BeautifulSoup
from utils.myResponse import BaseResponse
from utils.get_sync_key import get_sync_key
"""
微信网页版登录示例
GET https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_=1508052025433
得到响应: window.QRLogin.code = 200; window.QRLogin.uuid = "IapQqsoqcA==";
二维码src https://login.weixin.qq.com/qrcode/IapQqsoqcA==
长轮询: https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=IapQqsoqcA==&tip=0&r=-518626217&_=1508052025438
"""
def login(req):
ctime = time.time() * 1000
qrcode_url = "https://login.wx.qq.com/jslogin?appid=wx782c26e4c19acffb&redirect_uri=https%3A%2F%2Fwx.qq.com%2Fcgi-bin%2Fmmwebwx-bin%2Fwebwxnewloginpage&fun=new&lang=zh_CN&_={}".format(ctime)
rsp1 = requests.get(url=qrcode_url)
qrcode = re.findall(‘.uuid = "(.*)";‘, rsp1.text)[0]
img_url = "https://login.weixin.qq.com/qrcode/{}".format(qrcode)
req.session[‘qrcode‘] = qrcode
req.session[‘ctime‘] = ctime
return render(req,‘login.html‘,{‘img_url‘:img_url})
def get_pass_ticket(html):
soup = BeautifulSoup(html, ‘html.parser‘)
ret = {}
for tag in soup.find(name=‘error‘).find_all():
ret[tag.name] = tag.text
return ret
def loginCheck(req):
"""
判断是否扫码;扫码之后立即进入下一次长轮询,等待用户点击确认登录
window.code=408; 未扫码
window.code=201; 已扫码
window.userAvatar = ‘data:img/jpg;base64,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‘;
window.code=200; 已确认登录
window.redirect_uri="https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AZ3EYrgZt_xzrpgpevpgZdnN@qrticket_0&uuid=ochHx1cRew==&lang=zh_CN&scan=1508341438";
:param req:
:return:
"""
res = BaseResponse()
qrcode = req.session.get(‘qrcode‘)
ctime = time.time()*1000
tip = req.GET.get("tip")
tip = tip if tip else 0
print(qrcode, tip, ctime)
url = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip={1}&r=-716232763&_={2}".format(qrcode,tip,ctime)
rsp2 = requests.get(url=url)
res.status = rsp2.status_code
res.code = re.findall(".code=(\d+).",rsp2.text)[0]
if ‘201‘ == res.code:
avatar_str = re.findall("userAvatar = ‘(.*)‘.",rsp2.text)[0]
res.data = avatar_str if avatar_str else ""
elif ‘200‘ == res.code:
# 记录用户点击登录时候获得的cookies
req.session[‘LOGIN_COOKIES‘] = rsp2.cookies.get_dict()
# 获取 redirect_uri
redirect_uri = re.findall(‘redirect_uri="(.*)";‘, rsp2.text)[0]
redirect_uri = redirect_uri + "&fun=new&version=v2"
# 获取凭证
rsp3 = requests.get(url=redirect_uri)
ticket_dict = get_pass_ticket(rsp3.text)
# 记录请求redirect_uri之后获取的 TICKET_DITC 以及 相应cookies
req.session[‘TICKET_DITC‘] = ticket_dict
req.session[‘TICKET_COOKIES‘] = rsp3.cookies.get_dict()
res.data = rsp3.text
else:
res.data = rsp2.text
print(res.dict_info)
return HttpResponse(json.dumps(res.dict_info))
def index(req):
if not req.session.get(‘TICKET_DITC‘):
return redirect(‘/login.htm‘)
ticket_dict = req.session.get(‘TICKET_DITC‘)
# 获取完TICKET_DITC之后开始获取最近联系人列表并初始化
init_params_dict = {
‘BaseRequest‘: {
‘DeviceID‘: "e553172362037361",
‘Sid‘: ticket_dict[‘wxsid‘],
‘Skey‘: ticket_dict[‘skey‘],
‘Uin‘: ticket_dict[‘wxuin‘]
}
}
url_post = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-809803709&pass_ticket={}".format(ticket_dict.get(‘pass_ticket‘))
rsp4 = requests.post(url=url_post, json=init_params_dict)
rsp4.encoding=‘utf-8‘ # 避免出现中文乱码
print(">>>>>>>> ", rsp4.text)
# 记录初始化之后获取的cookies
req.session[‘INIT_COOKIES‘] = rsp4.cookies.get_dict()
init_dict = json.loads(rsp4.text)
sync_key = init_dict.pop(‘SyncKey‘) # sync_key 用于在后面发送消息
# 记录拿到的初始化信息,后面需要展示在页面上,所以先存储在session里
req.session[‘init_dict‘] = init_dict
req.session[‘sync_key‘] = sync_key
return render(req,‘index.html‘,{‘init_dict‘:init_dict})
def showAvatar(req):
# 整合cookies
all_cookies = {}
LOGIN_COOKIES = req.session.get(‘LOGIN_COOKIES‘)
TICKET_COOKIES = req.session.get(‘TICKET_COOKIES‘)
INIT_COOKIES = req.session.get(‘INIT_COOKIES‘)
all_cookies.update(LOGIN_COOKIES)
all_cookies.update(TICKET_COOKIES)
all_cookies.update(INIT_COOKIES)
# 获取前端传过来的头像参数并拼接头像url
img_prefix = req.GET.get(‘img‘) # /cgi-bin/mmwebwx-bin/webwxgeticon?seq=1576406163
username = req.GET.get(‘username‘) # @c1c38ffccbf118f6f62a023364f624c1bf683d3dc4432ad0203520b5f63f2742
skey = req.GET.get(‘skey‘) # @crypt_af096eac_6563c98d6143e21bcd2911bfdb3c2c50
avatar_url = "https://wx.qq.com{0}&username={1}&skey={2}".format(img_prefix,username,skey)
rsp = requests.get(url=avatar_url,cookies=all_cookies)
return HttpResponse(rsp.content)
def contactList(req):
# 整合cookies
all_cookies = {}
LOGIN_COOKIES = req.session.get(‘LOGIN_COOKIES‘)
TICKET_COOKIES = req.session.get(‘TICKET_COOKIES‘)
INIT_COOKIES = req.session.get(‘INIT_COOKIES‘)
all_cookies.update(LOGIN_COOKIES)
all_cookies.update(TICKET_COOKIES)
all_cookies.update(INIT_COOKIES)
ctime = time.time()
TICKET_DITC = req.session.get(‘TICKET_DITC‘)
pass_ticket = TICKET_DITC.get(‘pass_ticket‘)
skey = TICKET_DITC.get(‘skey‘)
url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket={0}&r={1}&seq=0&skey={2}".format(pass_ticket,ctime,skey)
rsp = requests.get(url=url,cookies=all_cookies)
rsp.encoding = ‘utf-8‘ # 避免出现中文乱码
contact_list_dict = json.loads(rsp.text)
print(">>>>>>>>>>>>>>>>>\n", contact_list_dict)
# 把所有联系人信息存储到session里
req.session[‘contact_list_dict‘] = contact_list_dict
init_dict = req.session.get(‘init_dict‘)
return render(req,‘contactList.html‘,{‘contact_list_dict‘:contact_list_dict,‘init_dict‘:init_dict})
def sendMsg(req):
ctime = time.time() * 1000
to_user = req.POST.get(‘to_user‘)
msg = req.POST.get(‘msg‘)
from_user = req.session.get(‘init_dict‘).get(‘User‘).get(‘UserName‘)
print("++++++++++++++++++++++++++++++++++")
print(to_user,msg)
ticket_dict = req.session.get(‘TICKET_DITC‘)
pass_ticket = ticket_dict.get(‘pass_ticket‘)
send_msg_url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?pass_ticket={0}".format(pass_ticket)
msg_dict = {
‘BaseRequest‘:{
‘DeviceID‘: "e553172362037361",
‘Sid‘: ticket_dict[‘wxsid‘],
‘Skey‘: ticket_dict[‘skey‘],
‘Uin‘: ticket_dict[‘wxuin‘]
},
‘Msg‘:{
‘ClientMsgId‘:ctime,
‘Content‘:msg,
‘FromUserName‘:from_user,
‘LocalID‘:ctime,
‘ToUserName‘:to_user,
‘Type‘:1
},
‘Scene‘:0
}
# 整合cookies
all_cookies = {}
LOGIN_COOKIES = req.session.get(‘LOGIN_COOKIES‘)
TICKET_COOKIES = req.session.get(‘TICKET_COOKIES‘)
INIT_COOKIES = req.session.get(‘INIT_COOKIES‘)
all_cookies.update(LOGIN_COOKIES)
all_cookies.update(TICKET_COOKIES)
all_cookies.update(INIT_COOKIES)
# 下面这种方式发送会出现中文乱码:
# rsp = requests.post(url=send_msg_url, json=msg_dict, cookies=all_cookies)
"""
json序列化的时候是可以加参数的:
data = {
‘name‘:‘alex‘,
‘msg‘:‘中文asa‘
}
import json
print(json.dumps(data))
按Unicode显示: {"msg": "\u4e2d\u6587asa", "name": "alex"}
print(json.dumps(data,ensure_ascii=False))
按中文显示: {"msg": "中文asa", "name": "alex"}
json.dumps() 之后是字符串
requests.post() 默认是按照 latin-1 编码,不支持中文
所以改成直接发bytes:
requests.post(data=json.dumps(data,ensure_ascii=False).encode(‘utf-8‘))
"""
rsp = requests.post(
url=send_msg_url,
data=json.dumps(msg_dict,ensure_ascii=False).encode(‘utf-8‘),
headers={‘Content-Type‘:‘application/json; charset=utf-8‘},
cookies=all_cookies
)
rsp.encoding = ‘utf-8‘ # 避免出现中文乱码
ret_dict = json.loads(rsp.text) # 将字符串转换成字典对象,这样前端接收的时候就能使用 xx.xx 形式进行取值了
return HttpResponse(json.dumps(ret_dict))
def syncCheck(req):
# 整合cookies
all_cookies = {}
LOGIN_COOKIES = req.session.get(‘LOGIN_COOKIES‘)
TICKET_COOKIES = req.session.get(‘TICKET_COOKIES‘)
INIT_COOKIES = req.session.get(‘INIT_COOKIES‘)
all_cookies.update(LOGIN_COOKIES)
all_cookies.update(TICKET_COOKIES)
all_cookies.update(INIT_COOKIES)
ctime = time.time() * 1000
ticket_dict = req.session.get(‘TICKET_DITC‘)
pass_ticket = ticket_dict.get(‘pass_ticket‘)
sync_key = req.session.get(‘sync_key‘)
sync_check_url = "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck"
params = {
‘r‘:ctime,
‘skey‘:ticket_dict.get(‘skey‘),
‘sid‘:ticket_dict.get(‘wxsid‘),
‘uin‘:ticket_dict.get(‘wxuin‘),
‘deviceid‘:‘e553172362037361‘,
‘synckey‘:get_sync_key(sync_key)
}
# 检测是否有新消息到来
rsp = requests.get(url=sync_check_url,params=params,cookies=all_cookies)
print(rsp.text)
# 去服务器端取回新消息
if ‘window.synccheck={retcode:"0",selector:"2"}‘ in rsp.text:
data = {
‘BaseRequest‘:{
‘DeviceID‘: "e553172362037361",
‘Sid‘: ticket_dict[‘wxsid‘],
‘Skey‘: ticket_dict[‘wxsid‘],
‘Uin‘: ticket_dict[‘wxuin‘]
},
‘SyncKey‘:sync_key,
‘rr‘:‘-1324973514‘
}
sync_msg_url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid={0}&skey={1}&pass_ticket={2}".format(ticket_dict[‘wxsid‘],ticket_dict[‘wxsid‘],pass_ticket)
msg_res = requests.post(url=sync_msg_url,json=data,cookies=all_cookies)
msg_res.encoding = ‘utf-8‘
msg_res_dict = json.loads(msg_res.text) # 将字符串转换成字典对象,这样前端接收的时候就能使用 xx.xx 形式进行取值了
new_sync_key = msg_res_dict.get(‘SyncKey‘) # 每次同步完新消息后,sync_key都会更新,所以每次记得重新获取并存储到session里
req.session[‘sync_key‘] = new_sync_key
for msg in msg_res_dict.get(‘AddMsgList‘):
print(msg.get(‘FromUserName‘),msg.get(‘CreateTime‘),msg.get(‘Content‘))
return HttpResponse(json.dumps(msg_res_dict))
else:
return HttpResponse(json.dumps({‘AddMsgCount‘:0,‘AddMsgList‘:None}))
def logout(req):
print("ByeBye...")
req.session.clear()
return redirect(‘/login.htm‘)
# get_sync_key.py
def get_sync_key(sync_key):
sync_key_list = []
for item in sync_key.get(‘List‘):
tmp = "%s_%s" % (item.get(‘Key‘),item.get(‘Val‘))
sync_key_list.append(tmp)
return "|".join(sync_key_list)
# myResponse.py
class BaseResponse(object):
def __init__(self):
self.status = None
self.code = None
self.data = None
@property
def dict_info(self):
return self.__dict__
class LikeResponse(BaseResponse):
def __init__(self):
self.msg = None
super(LikeResponse, self).__init__()
if __name__ == ‘__main__‘:
like = LikeResponse()
print(like.dict_info)
原文:http://www.cnblogs.com/standby/p/7739797.html