十一、模拟扫码登录微信(用Django简单的布置了下页面)发送接收消息
为了能够模拟登陆QQ,并获取信息。对扫码登录微信进行了分析。简单的用了一下Django将获取的信息映射到页面上。(python3+pycharm)
主要过程就是:
1、获取二维码
2、扫码登录(有三种状态)
3、获取联系人信息(index页面获取的是个人信息、最近联系人信息、公众号)
4、获取所有的联系人
5、发送和接收消息(接收消息打印到了后台)
创建Django项目、导入JQuery(发送AJax请求)、创建APP、创建模板(简单的弄一下,能合理显示得到的数据就好)
url.py
from django.contrib import admin
# from django.urls import path
from django.conf.urls import url
from app01 import views
urlpatterns = [
url('admin/', admin.site.urls),
url(r'^$', 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), # 接收消息
]
templates
login.html(对应的是views中函数login和long_polling)
扫码前

扫码后、没有点击登录按钮,显示的你的头像

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <div style="margin: 0 auto;width: 300px">
<img id="qcode" style="width: 300px;height: 300px" src="https://login.weixin.qq.com/qrcode/{{ code }}" alt="扫码登录">
</div> <script src="/static/jquery-1.12.4.js"></script>
<script>
$(function () { polling();
});
function polling(){
$.ajax({
url: '/polling/',
type: 'GET',
dataType: 'json',
success: function (arg) {
if(arg.status==408){
console.log(1); polling();
}else if(arg.status==201){
$('#qcode').attr('src',arg.data);
polling(); }else if(arg.status==200) {
window.location.href ='/index/';
} } })
}
</script>
</body>
</html>
index.html(个人信息、最近联系人、公众号页面)
点击登录后的页面:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>个人信息</h1>
<div>
{# <img src="https://wx.qq.com{{ data.User.HeadImgUrl }}">#}
<img style="width: 40px;height: 40px" src={{ code }}>
</div>
<div>
{{ data.User.NickName }} - {{ data.User.UserName }}
</div>
<h1>最近联系人列表</h1>
<ul>
{% for row in data.ContactList%}
<li>{{ row.UserName }} - {{ row.NickName }}</li>
{% endfor %}
<li><a href="/contact_list/">获取更多联系人</a></li>
</ul> <h1>公众号</h1>
{% for row in data.MPSubscribeMsgList%}
<div style="font-weight: bolder">{{ row.NickName }}</div>
{% for i in row.MPArticleList %}
<div>
<div><a href="{{ i.Url }}">{{ i.Title }}</a></div>
<div style="color: #dddddd">{{ i.Digest }}</div>
</div> {% endfor %} {% endfor %} </body>
</html>
contac_list(全部联系人、发送接收页面)
页面:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>发送消息</h1>
<div> <p><input id="user_id" type="text" placeholder="请输入用户唯一ID" /></p>
<p><input id='user_msg' type="text" placeholder="请输入内容" /></p>
<input id="sendMsg" type="button" value="提交" />
</div>
<ul>
{% for row in obj.MemberList %}
<li>{{ row.NickName }} - {{ row.UserName }} -{{ row.Province }}</li>
{% endfor %}
</ul>
<script src="/static/jquery-1.12.4.js"></script>
<script>
$(function () {
bindSendMessage();
fetchMessage();
});
function bindSendMessage() {
$('#sendMsg').click(function () {
$.ajax({
url: '/send_msg/',
type: 'POST',
data: {'user_id': $('#user_id').val(), 'user_msg': $('#user_msg').val()},
success:function () { }
})
});
} function fetchMessage(){
$.ajax({
url: '/get_msg/',
type: 'GET',
success:function (arg) {
fetchMessage();
}
})
}
</script>
</body>
</html>

views.py(逻辑层)
import re
import time
import json
import requests
from bs4 import BeautifulSoup
from django.shortcuts import render, HttpResponse
# Create your views here. # 一些全局变量
# 当前时间戳
CURRENT_TIME = None
# 验证码
QCODE = None
#图片
PICTURE = None
# tip
TIP = 1
# LOGININ cookies
# all_cookie_dict = {}
# 保存cookies
LOGIN_COOLIES_DICT = {}
TICKET_COOKIES_DICT = {}
TICKET_DICT = {}
# 用户信息
USER_INIT_DATA = {} def login(request):
'''
获取登录二维码
:param request:
:return:
'''
global QCODE
global CURRENT_TIME 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}'
CURRENT_TIME = str(time.time())
q_code_url = url.format(CURRENT_TIME)
response = requests.get(q_code_url)
# 打印返回值
# window.QRLogin.code = 200; window.QRLogin.uuid = "4c5VeLH00g==";
# print(response.text)
code = re.findall('uuid = "(.*)";', response.text)[0]
QCODE = code
# print(code)
return render(request, 'login.html', {'code': code}) def long_polling(request):
'''
长轮询,有408、201、200三种状态
:param request:
:return:
''' global TIP
global PICTURE
print('polling') # 默认返回Ajax状态为408
ret = {'status': 408, 'data': None}
base_login_url = 'https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip={1}&r=970980966&_={1}'
login_url = base_login_url.format(QCODE, TIP, CURRENT_TIME)
response = requests.get(login_url)
# print(response.text) # 判断
if 'window.code=201' in response.text:
TIP = 0
# 图片地址
avatar = re.findall("userAvatar = '(.*)';", response.text)[0]
# print(avatar)
ret['data'] = avatar
ret['status'] = 201
# 获得个人信息头像使用(index函数中,直接在函数返回值中提取链接获取不到图片)
PICTURE = avatar elif 'window.code=200' in response.text:
# 获取登录时的cookie值,存到全局变量中
LOGIN_COOLIES_DICT.update(response.cookies.get_dict())
# 提取返回值中的url地址
redirect_uri = re.findall('redirect_uri="(.*)";', response.text)[0]
redirect_uri += '&fun=new&version=v2' # 获取以后要用到的ticket等数据
response_ticket = requests.get(redirect_uri, cookies=LOGIN_COOLIES_DICT)
TICKET_COOKIES_DICT.update(response_ticket.cookies.get_dict())
# print(response_ticket.text)
# soup1 = BeautifulSoup(response_ticket.text, 'lxml')
soup2 = BeautifulSoup(response_ticket.text, 'html.parser')
# print(soup1)
# print(soup2)
for tag in soup2.find():
TICKET_DICT[tag.name] = tag.string
# print(TICKET_DICT)
ret['status'] = 200
return HttpResponse(json.dumps(ret)) def index(request):
'''
获取个人信息、最近联系人、公众号
:param request:
:return:
'''
# 用户初始化
user_init_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=855409185&pass_ticket=%s' % TICKET_DICT['pass_ticket']
form_data = {
'BaseRequest': {
'DeviceID': 'e531777446530354',
'Sid': TICKET_DICT['wxsid'],
'Skey': TICKET_DICT['skey'],
'Uin': TICKET_DICT['wxuin']
}
} # 带上所有的coolkie
all_cookie_dict = {}
all_cookie_dict.update(LOGIN_COOLIES_DICT)
all_cookie_dict.update(TICKET_COOKIES_DICT)
# json= 发送过去会自动带一个请求头,用json解析
response_init = requests.post(user_init_url, json=form_data, cookies=all_cookie_dict)
# print(response_init.text)
response_init.encoding = 'utf-8'
# print(response_init.text)
user_init_data = json.loads(response_init.text)
USER_INIT_DATA.update(user_init_data) return render(request, 'index.html', {'data': user_init_data, 'code':PICTURE}) def contact_list(request):
'''
获取所有联系人列表
:param request:
:return:
'''
# print(all_cookie_dict)
# print(TICKET_DICT)
# print(LOGIN_COOLIES_DICT)
# print(TICKET_COOKIES_DICT) 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'], str(time.time()), TICKET_DICT['skey']))
# base_url = '{0} {1} {2}'
# url = base_url.format(TICKET_DICT['pass_ticket'], str(time.time()), TICKET_DICT['skey'])
# print(base_url)
all_cookie_dict = {}
all_cookie_dict.update(LOGIN_COOLIES_DICT)
all_cookie_dict.update(TICKET_COOKIES_DICT)
response = requests.get(url, cookies=all_cookie_dict)
response.encoding = 'utf-8'
contact_list_dict = json.loads(response.text)
# print(contact_list_dict)
return render(request, 'contact_list.html', {'obj': contact_list_dict})
# return HttpResponse("ok") def send_msg(request):
'''
发送消息
:param request:
:return:
'''
# print(USER_INIT_DATA)
# print(TICKET_DICT)
# print(LOGIN_COOLIES_DICT)
# print(TICKET_COOKIES_DICT)
from_user_id = USER_INIT_DATA['User']['UserName']
to_user_id = request.POST.get('user_id')
msg = request.POST.get('user_msg')
send_url = 'https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg'
form_data = {
'BaseRequest': {
'DeviceID': 'e531777446530354',
'Sid': TICKET_DICT['wxsid'],
'Skey': TICKET_DICT['skey'],
'Uin': TICKET_DICT['wxuin']
},
'Msg': {
"ClientMsgId": str(time.time()),
#"Content": msg,
"Content": '%(content)s',
"FromUserName": from_user_id,
"LocalID": str(time.time()),
"ToUserName": to_user_id,
"Type": 1
},
'Scene': 0
}
import json
# 字符串
form_data_str = json.dumps(form_data)
# 进行格式化
form_data_str = form_data_str % {'content': msg} # 转换成字节
form_data_bytes = bytes(form_data_str, encoding='utf-8') all_cookie_dict = {}
all_cookie_dict.update(LOGIN_COOLIES_DICT)
all_cookie_dict.update(TICKET_COOKIES_DICT) # response = requests.post(send_url, json=form_data, cookies=all_cookie_dict)
response = requests.post(send_url, data=form_data_bytes, cookies=all_cookie_dict, headers={
'Content-Type': 'application/json'})
print(response.text)
return HttpResponse('OK') def get_msg(request):
sync_url = 'https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck' sync_data_list = []
for item in USER_INIT_DATA['SyncKey']['List']:
temp = "%s_%s" % (item['Key'], item['Val'])
sync_data_list.append(temp)
sync_data_str = "|".join(sync_data_list)
nid = int(time.time())
sync_dict = {
"r": nid,
"skey": TICKET_DICT['skey'],
"sid": TICKET_DICT['wxsid'],
"uin": TICKET_DICT['wxuin'],
"deviceid": "e531777446530354",
"synckey": sync_data_str
}
all_cookie = {}
all_cookie.update(LOGIN_COOLIES_DICT)
all_cookie.update(TICKET_COOKIES_DICT)
response_sync = requests.get(sync_url, params=sync_dict, cookies=all_cookie)
print(response_sync.text)
if 'selector:"2"' in response_sync.text:
fetch_msg_url = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid=%s&skey=%s&lang=zh_CN&pass_ticket=%s" % (
TICKET_DICT['wxsid'], TICKET_DICT['skey'], TICKET_DICT['pass_ticket']) form_data = {
'BaseRequest': {
'DeviceID': 'e531777446530354',
'Sid': TICKET_DICT['wxsid'],
'Skey': TICKET_DICT['skey'],
'Uin': TICKET_DICT['wxuin']
},
'SyncKey': USER_INIT_DATA['SyncKey'],
'rr': str(time.time())
}
response_fetch_msg = requests.post(fetch_msg_url, json=form_data)
response_fetch_msg.encoding = 'utf-8'
res_fetch_msg_dict = json.loads(response_fetch_msg.text)
USER_INIT_DATA['SyncKey'] = res_fetch_msg_dict['SyncKey']
for item in res_fetch_msg_dict['AddMsgList']:
print(item['Content'], ":::::", item['FromUserName'], "---->", item['ToUserName'],)
return HttpResponse('ok')
爬虫入门简单,想要深入果然很难。继续努力,加油!
十一、模拟扫码登录微信(用Django简单的布置了下页面)发送接收消息的更多相关文章
- 微信开放平台开发——网页微信扫码登录(OAuth2.0)
1.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提供 ...
- 第三方登录:微信扫码登录(OAuth2.0)
1.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提供 ...
- php微信开放平台--第三方网页微信扫码登录(OAuth2.0)
第一.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提 ...
- Web应用多账号系统设计及微信扫码登录实现
Web应用多账号系统设计及微信扫码登录实现 1 前言概述 公司对功能测试,性能测试,安全测试等等都做了比较好的自动化后,急需要一个MIS系统来统一管理这些结果及报表. 此MIS系统特点如下: 仅内 ...
- C#开发微信门户及应用(45)--微信扫码登录
在前面随笔<C#开发微信门户及应用(41)--基于微信开放平台的扫码登录处理>介绍了基于微信开放平台接口实现的微信扫码直接登录的过程.本篇介绍对扫码登录的一些改进和处理,以便更方便应用在实 ...
- C#开发微信门户及应用(41)--基于微信开放平台的扫码登录处理
在现今很多网站里面,都使用了微信开放平台的扫码登录认证处理,这样做相当于把身份认证交给较为权威的第三方进行认证,在应用网站里面可以不需要存储用户的密码了.本篇介绍如何基于微信开放平台的扫码进行网站的登 ...
- 微信小程序使用场景延伸:扫码登录、扫码支付
微信小程序使用场景延伸:扫码登录.扫码支付 小程序最适合的使用场景有哪些?相比大家能列举出来很多,但这个场景,大家可能多数没想到_^ 笔者团队近期接到了一个PC项目:转转游戏租号PC官网,该项目要求在 ...
- Vue+abp微信扫码登录
最近系统中要使用微信扫码登录,根据微信官方文档和网络搜索相关文献实现了.分享给需要的人,也作为自己的一个笔记.后端系统是基于ABP的,所以部分代码直接使用了abp的接口,直接拷贝代码编译不通过. 注册 ...
- Java实现微信客户端扫码登录
此篇文章记录自己开发中的微信客户端扫码登录的实例以及步骤,便于以后自行学习记起的关键,看到的网友有借鉴的地方就借鉴,看不懂的也请别吐槽,毕竟每个人的思维和思路以及记录东西的方式不一样: 1.首先需要一 ...
随机推荐
- 沈阳做假证z
沈阳做假证[电/薇:187ヘ1184ヘ0909同号]办各类证件-办毕业证-办离婚证,办学位证书,办硕士毕业证,办理文凭学历,办资格证,办房产证不. 这是一个简单的取最大值程序,可以用于处理 i32 数 ...
- unity2D物理引擎之-Rigidbody 2D
虽然Rigidbody 2D大致上可以看成是Rigidbody的2D化,大部分功能也是一致的,但是还是有一些细节问题. 一些事项: 1.任何添加到同一个 GameObject身上或者其子物体身上的 2 ...
- 用navicat进行身份验证连接出现cannot connect to Mongodb authentication failed
用navicat进行身份验证连接出现cannot connect to Mongodb authentication failed. 解决办法: 1.打开mongoDB连接 win+r --cmd-- ...
- 1dialog 表单最基本的封装
<!-- --> <template> <el-dialog :visible.sync="defaultConfigDialogAdd.dialogVisib ...
- 转载:把你的精力专注在java,jvm原理,spring原理,mysql锁,事务,多线程,大并发,分布式架构,微服务,以及相关的项目管理等等,这样你的核心竞争力才会越来越高
https://developer.51cto.com/art/202001/608984.htm 把你的精力专注在java,jvm原理,spring原理,mysql锁,事务,多线程,大并发,分布式架 ...
- MySQL通过实体经纬度字段插入数据库point类型的经纬度字段
说明:数据库:表中没有经度跟纬度字段,只有location字段(point类型) POINT(经度 纬度)实体类:只有经度 lng 字段.纬度 lat 字段 没有location字段 <!--添 ...
- pwnable.kr之leg
查看原题代码: #include <stdio.h> #include <fcntl.h> int key1(){ asm("mov r3, pc\n"); ...
- poi自动生成Ecxel表格和Chart图表
最近因为业务需求,需要做poi自动导出Ecxel表格和Chart折线图的功能. 所以我在网上找到了一篇关于poi生成Chart图表的博客,代码很详细,但是缺少相关注释说明. 想要将它改造成自己需要的样 ...
- 3896. 【NOIP2014模拟10.26】战争游戏
鉴于如此一道恶心的题,作者还花了一个晚上草草学了tarjan. 于是乎,这道题就是道tarjan 具体怎么实现呢?正解上有个什么树形DP,看的我一脸懵逼. 这道题可以运用到tarjan一个高科技的算法 ...
- css常用属性:居中展示、内边距、外边距
1.横向居中.纵向居中 2.纵向展示3个块级(div标签即可纵向展示) 3.横向展示3个块级 4.在横向块级上加上边框的两种方法 法一:在父级div上加上和样式一样高的height 法二:在父级div ...