模拟实现web版微信

1. 新建一个django项目 wechat

2. 在wechat项目下新建一个文件夹 static

3. 在wechat应用下的settings.py文件新增静态文件路径

STATICFILS_DIRS = (
    os.path.join(BASE_DIR,'static')   
)

4. 将jquery拷贝到static文件夹中

5. 新建一个应用 web

6. 在wechat应用下的urls.py文件中配置路由

from django.conf.urls import url
from django.contrib import admin
from web import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/$', views.login),
    url(r'^polling/$', views.long_polling),
    url(r'^index/$', views.index),
    url(r'^contact_list/$', views.contact_list),
    url(r'^send_msg/$', views.send_msg),
    url(r'^get_msg/$', views.get_msg),
]

7. 在web应用下的views.py文件中书写相关函数

  1 import re
  2 import time
  3 import json
  4 import requests
  5 from django.shortcuts import render
  6 from django.shortcuts import HttpResponse
  7 # 当前时间戳
  8 CURRENT_TIME = None
  9 QCODE = None
 10 
 11 LOGIN_COOKIE_DICT = {}
 12 TICKET_COOKIE_DICT = {}
 13 TICKET_DICT = {}
 14 TIPS = 1
 15 
 16 USER_INIT_DATA = {}
 17 BASE_URL = "http://wx.qq.com"
 18 BASE_SYNC_URL = "https://webpush.weixin.qq.com"
 19 
 20 def login(request):
 21     base_qcode_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&_={0}'
 22     global CURRENT_TIME
 23     CURRENT_TIME = str(time.time())
 24     q_code_url = base_qcode_url.format(CURRENT_TIME)
 25     response = requests.get(q_code_url)
 26     # 二维码后缀
 27     code = re.findall('uuid = "(.*)";',response.text)[0]
 28     global QCODE
 29     QCODE = code
 30     return render(request, 'login.html', {'code': code})
 31 
 32 def long_polling(request):
 33     print('polling....')
 34     ret = {'status': 408, 'data': None}
 35     # https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=IZpsHyzTNw==&tip=1&r=-897465901&_=1486956149964
 36     # 408,201,200
 37     try:
 38         global TIPS
 39         base_login_url = 'https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip={1}&r=-897465901&_={2}'
 40         login_url = base_login_url.format(QCODE,TIPS,CURRENT_TIME)
 41         response_login = requests.get(login_url)
 42         if "window.code=201" in response_login.text:
 43             TIPS = 0
 44             avatar = re.findall("userAvatar = '(.*)';",response_login.text)[0]
 45             ret['data'] = avatar
 46             ret['status'] = 201
 47         elif 'window.code=200' in response_login.text:
 48             # 扫码点击确认后,获取cookie
 49             LOGIN_COOKIE_DICT.update(response_login.cookies.get_dict())
 50             redirect_uri = re.findall('redirect_uri="(.*)";', response_login.text)[0]
 51             global BASE_URL
 52             global BASE_SYNC_URL
 53             if redirect_uri.startswith('https://wx2.qq.com'):
 54                 BASE_URL = 'https://wx2.qq.com'
 55                 BASE_SYNC_URL = 'https://webpush.wx2.qq.com'
 56             else:
 57                 BASE_URL = "http://wx.qq.com"
 58                 BASE_SYNC_URL = "https://webpush.weixin.qq.com"
 59 
 60             redirect_uri += '&fun=new&version=v2&lang=zh_CN'
 61 
 62             # 获取票据,Cookie,返回值
 63             response_ticket = requests.get(redirect_uri, cookies=LOGIN_COOKIE_DICT)
 64             TICKET_COOKIE_DICT.update(response_ticket.cookies.get_dict())
 65             print(response_ticket.text)
 66             from bs4 import BeautifulSoup
 67             soup = BeautifulSoup(response_ticket.text,'html.parser')
 68             for tag in soup.find():
 69                 TICKET_DICT[tag.name] = tag.string
 70 
 71             ret['status'] = 200
 72 
 73             # https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AZfYKn7CWTeZE_iMTHwv7GFB@qrticket_0&uuid=IeFZHVi6Jw==&lang=zh_CN&scan=1
 74             # https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?ticket=AepqqS0wvk1UN6bCGiaHHWXQ@qrticket_0&uuid=we1gq4TyyA==&lang=zh_CN&scan=1486957549"
 75     except Exception as e:
 76         print(e)
 77     return HttpResponse(json.dumps(ret))
 78 
 79 
 80 def index(request):
 81     # 初始化用户基本信息
 82     # https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-909239606&lang=zh_CN&pass_ticket=Tpc2XEec%252BJ0q2qNRw6nqWzGSsQ3jM2LZtBCVJZfjvMTDxjiyJ9mO5eRtCNOveeXO
 83 
 84 
 85     user_init_url = '%s/cgi-bin/mmwebwx-bin/webwxinit?pass_ticket=%s&r=%s' % (BASE_URL, TICKET_DICT['pass_ticket'], int(time.time()))
 86 
 87     form_data = {
 88         'BaseRequest': {
 89             'DeviceID': 'e531777446530354',
 90             'Sid': TICKET_DICT['wxsid'],
 91             'Skey': TICKET_DICT['skey'],
 92             'Uin': TICKET_DICT['wxuin']
 93         }
 94     }
 95     all_cookie_dict = {}
 96     all_cookie_dict.update(LOGIN_COOKIE_DICT)
 97     all_cookie_dict.update(TICKET_COOKIE_DICT)
 98 
 99     response_init = requests.post(user_init_url, json=form_data, cookies=all_cookie_dict)
100     response_init.encoding = 'utf-8'
101     user_init_data = json.loads(response_init.text)
102     # for k,v in user_init_data.items():
103     #     print(k,v)
104     USER_INIT_DATA.update(user_init_data)
105     """
106     form_data = {
107         'BaseRequest':{
108         'DeviceID': 'e531777446530354',
109         'Sid': TICKET_DICT['wxsid'],
110         'Skey': TICKET_DICT['skey'],
111         'Uin': TICKET_DICT['wxuin']
112         }
113     }
114     all_cookie_dict = {}
115     all_cookie_dict.update(LOGIN_COOKIE_DICT)
116     all_cookie_dict.update(TICKET_COOKIE_DICT)
117 
118     response_init = requests.post(user_init_url,json=form_data,)
119     response_init.encoding = 'utf-8'
120     print(response_init.text)
121     """
122 
123     return render(request, 'index.html',{'data': user_init_data})
124 
125 
126 def contact_list(request):
127     """
128     获取联系人列表
129     :param request:
130     :return:
131     """
132     # https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket={0}&r={1}&seq=0&skey={2}
133     base_url  = "{0}/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket={1}&r={2}&seq=0&skey={3}"
134     url = base_url.format(BASE_URL, TICKET_DICT['pass_ticket'], str(time.time()), TICKET_DICT['skey'])
135 
136     all_cookie_dict = {}
137     all_cookie_dict.update(LOGIN_COOKIE_DICT)
138     all_cookie_dict.update(TICKET_COOKIE_DICT)
139     response = requests.get(url,cookies=all_cookie_dict)
140     response.encoding = 'utf-8'
141     contact_list_dict = json.loads(response.text)
142     return render(request, 'contact_list.html',{'obj': contact_list_dict})
143 
144 
145 def send_msg(request):
146 
147     from_user_id = USER_INIT_DATA['User']['UserName']
148     to_user_id = request.POST.get('user_id')
149     msg = request.POST.get('user_msg')
150 
151     send_url = BASE_URL + "/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&pass_ticket=" + TICKET_DICT['pass_ticket']
152     form_data = {
153         'BaseRequest': {
154             'DeviceID': 'e531777446530354',
155             'Sid': TICKET_DICT['wxsid'],
156             'Skey': TICKET_DICT['skey'],
157             'Uin': TICKET_DICT['wxuin']
158         },
159         'Msg':{
160             "ClientMsgId": str(time.time()),
161             "Content": '%(content)s',
162             "FromUserName": from_user_id,
163             "LocalID": str(time.time()),
164             "ToUserName": to_user_id,
165             "Type": 1
166         },
167         'Scene':0
168     }
169     import json
170     # 字符串
171     form_data_str = json.dumps(form_data)
172     # 进行格式化
173     form_data_str = form_data_str %{'content':msg}
174 
175     # 转换成字节
176     form_data_bytes = bytes(form_data_str,encoding='utf-8')
177 
178     all_cookie_dict = {}
179     all_cookie_dict.update(LOGIN_COOKIE_DICT)
180     all_cookie_dict.update(TICKET_COOKIE_DICT)
181 
182     response = requests.post(send_url, data=form_data_bytes, cookies=all_cookie_dict, headers={
183         'Content-Type': 'application/json'})
184     print(response.text)
185 
186     return HttpResponse('ok')
187 
188 def get_msg(request):
189     sync_url = BASE_SYNC_URL + "/cgi-bin/mmwebwx-bin/synccheck"
190 
191     sync_data_list = []
192     for item in USER_INIT_DATA['SyncKey']['List']:
193         temp = "%s_%s" % (item['Key'], item['Val'])
194         sync_data_list.append(temp)
195     sync_data_str = "|".join(sync_data_list)
196     nid = int(time.time())
197     sync_dict = {
198         "r": nid,
199         "skey": TICKET_DICT['skey'],
200         "sid": TICKET_DICT['wxsid'],
201         "uin": TICKET_DICT['wxuin'],
202         "deviceid": "e531777446530354",
203         "synckey": sync_data_str
204     }
205     all_cookie = {}
206     all_cookie.update(LOGIN_COOKIE_DICT)
207     all_cookie.update(TICKET_COOKIE_DICT)
208     response_sync = requests.get(sync_url, params=sync_dict, cookies=all_cookie)
209     print(response_sync.text)
210     if 'selector:"2"' in response_sync.text:
211         fetch_msg_url = "%s/cgi-bin/mmwebwx-bin/webwxsync?sid=%s&skey=%s&lang=zh_CN&pass_ticket=%s" % (BASE_URL, TICKET_DICT['wxsid'], TICKET_DICT['skey'], TICKET_DICT['pass_ticket'])
212 
213         form_data = {
214             'BaseRequest': {
215                 'DeviceID': 'e531777446530354',
216                 'Sid': TICKET_DICT['wxsid'],
217                 'Skey': TICKET_DICT['skey'],
218                 'Uin': TICKET_DICT['wxuin']
219             },
220             'SyncKey': USER_INIT_DATA['SyncKey'],
221             'rr': str(time.time())
222         }
223         response_fetch_msg = requests.post(fetch_msg_url, json=form_data)
224         response_fetch_msg.encoding = 'utf-8'
225         res_fetch_msg_dict = json.loads(response_fetch_msg.text)
226         USER_INIT_DATA['SyncKey'] = res_fetch_msg_dict['SyncKey']
227         for item in res_fetch_msg_dict['AddMsgList']:
228             print(item['Content'], ":::::", item['FromUserName'], "---->", item['ToUserName'], )
229     return HttpResponse('ok')
views.py

8. 在templates文件夹下新建login.html、index.html、contact_list.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <div style="width: 300px;margin: 0 auto;">
 9         <!-- 二维码图片路径 -->
10         <img id="qcode"  style="width: 300px;height: 300px;" src="https://login.weixin.qq.com/qrcode/{{ code }}">
11     </div>
12     <script src="/static/jquery-1.12.4.js"></script>
13     <script>
14         $(function () {
15             polling();
16         });
17 
18         function polling(){
19             $.ajax({
20                 url: '/polling/',
21                 type: "GET",
22                 dataType: 'json',
23                 success: function(arg){
24                     if(arg.status == 408){
25                         polling();
26                     }else if(arg.status == 201){
27                         // 获取图片接着发
28                         $('#qcode').attr('src', arg.data);
29                         polling();
30                     }else {
31                         window.location.href = '/index/'
32                     }
33                 }
34             })
35         }
36     </script>
37 </body>
38 </html>
login.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <h1>个人信息</h1>
 9     <div>
10         <img src="https://wx.qq.com{{ data.User.HeadImgUrl }}">
11     </div>
12     <div>
13         {{ data.User.NickName }} - {{ data.User.UserName }}
14     </div>
15     <h1>联系人列表</h1>
16     <ul>
17     {% for row in data.ContactList%}
18         <li>{{ row.UserName }} - {{ row.NickName }}</li>
19     {% endfor %}
20     <li><a href="/contact_list/">获取更多联系人</a></li>
21     </ul>
22 
23     <h1>公众号</h1>
24     {% for row in data.MPSubscribeMsgList%}
25         <div style="font-weight: bolder">{{ row.NickName }}</div>
26         {% for i in row.MPArticleList %}
27             <div>
28                 <div><a href="{{ i.Url }}">{{ i.Title }}</a></div>
29                 <div style="color: #dddddd">{{ i.Digest }}</div>
30             </div>
31 
32         {% endfor %}
33 
34     {% endfor %}
35 
36 </body>
37 </html>
index.html
 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6 </head>
 7 <body>
 8     <h1>发送消息</h1>
 9     <div>
10         <p><input id="user_id" type="text" placeholder="请输入用户唯一ID" /></p>
11         <p><input id='user_msg' type="text" placeholder="请输入内容" /></p>
12         <input id="sendMsg" type="button" value="提交"  />
13     </div>
14     <ul>
15         {% for row in obj.MemberList %}
16             <li>{{ row.NickName }} - {{ row.UserName }} -{{ row.Province }}</li>
17         {% endfor %}
18     </ul>
19     <script src="/static/jquery-1.12.4.js"></script>
20     <script>
21         $(function () {
22             bindSendMessage();
23             fetchMessage();
24         });
25         function bindSendMessage() {
26             $('#sendMsg').click(function () {
27                 $.ajax({
28                     url: '/send_msg/',
29                     type: 'POST',
30                     data: {'user_id': $('#user_id').val(), 'user_msg': $('#user_msg').val()},
31                     success:function () {
32 
33                     }
34                 })
35             });
36         }
37     
38         function fetchMessage(){
39             $.ajax({
40                 url: '/get_msg/',
41                 type: 'GET',
42                 success:function (arg) {
43                     fetchMessage();
44                 }
45             })
46         }
47     </script>
48 </body>
49 </html>
contact_list.html

 

posted @ 2018-08-14 15:37  _E.t  阅读(529)  评论(0编辑  收藏  举报