• 模拟实现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=" 300px;margin: 0 auto;">
     9         <!-- 二维码图片路径 -->
    10         <img id="qcode"  style=" 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
  • 相关阅读:
    TCP通信丢包原因总结
    根据日志查看QPS
    mysql:备份、复制
    集群
    redis性能提升
    redis源码——多机数据库的实现
    redis源码——单机数据库的实现
    redis 设置过期Key 的 maxmemory-policy 六种方式
    字符处理
    贝塞尔曲线
  • 原文地址:https://www.cnblogs.com/yzls/p/9474969.html
Copyright © 2020-2023  润新知