为了能够模拟登陆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简单的布置了下页面)发送接收消息的更多相关文章

  1. 微信开放平台开发——网页微信扫码登录(OAuth2.0)

    1.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提供 ...

  2. 第三方登录:微信扫码登录(OAuth2.0)

    1.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提供 ...

  3. php微信开放平台--第三方网页微信扫码登录(OAuth2.0)

    第一.OAuth2.0 OAuth(开放授权)是一个开放标准,允许用户让第三方应用访问该用户在某一网站上存储的私密的资源(如照片,视频,联系人列表),而无需将用户名和密码提供给第三方应用. 允许用户提 ...

  4. Web应用多账号系统设计及微信扫码登录实现

    Web应用多账号系统设计及微信扫码登录实现 1   前言概述 公司对功能测试,性能测试,安全测试等等都做了比较好的自动化后,急需要一个MIS系统来统一管理这些结果及报表. 此MIS系统特点如下: 仅内 ...

  5. C#开发微信门户及应用(45)--微信扫码登录

    在前面随笔<C#开发微信门户及应用(41)--基于微信开放平台的扫码登录处理>介绍了基于微信开放平台接口实现的微信扫码直接登录的过程.本篇介绍对扫码登录的一些改进和处理,以便更方便应用在实 ...

  6. C#开发微信门户及应用(41)--基于微信开放平台的扫码登录处理

    在现今很多网站里面,都使用了微信开放平台的扫码登录认证处理,这样做相当于把身份认证交给较为权威的第三方进行认证,在应用网站里面可以不需要存储用户的密码了.本篇介绍如何基于微信开放平台的扫码进行网站的登 ...

  7. 微信小程序使用场景延伸:扫码登录、扫码支付

    微信小程序使用场景延伸:扫码登录.扫码支付 小程序最适合的使用场景有哪些?相比大家能列举出来很多,但这个场景,大家可能多数没想到_^ 笔者团队近期接到了一个PC项目:转转游戏租号PC官网,该项目要求在 ...

  8. Vue+abp微信扫码登录

    最近系统中要使用微信扫码登录,根据微信官方文档和网络搜索相关文献实现了.分享给需要的人,也作为自己的一个笔记.后端系统是基于ABP的,所以部分代码直接使用了abp的接口,直接拷贝代码编译不通过. 注册 ...

  9. Java实现微信客户端扫码登录

    此篇文章记录自己开发中的微信客户端扫码登录的实例以及步骤,便于以后自行学习记起的关键,看到的网友有借鉴的地方就借鉴,看不懂的也请别吐槽,毕竟每个人的思维和思路以及记录东西的方式不一样: 1.首先需要一 ...

随机推荐

  1. GLSL 着色器程序

    除了使用Cg/HSL 着色器程序以外, OpenGL 着色器语言(GLSL)着色器可以直接书写shader. 然而,使用原生的GLSL只推荐作为测试使用,或者你清晰的知道你的目标平台是 Mac OS ...

  2. The Unique MST(最小生成树的唯一性判断)

    Given a connected undirected graph, tell if its minimum spanning tree is unique. Definition 1 (Spann ...

  3. webpack3.10.0(入门系列基本概念1)

    一.概念 webpack的核心是一个用于现代JavaScript应用程序的静态模块打包程序.当webpack处理您的应用程序时,它会递归地构建一个依赖图,其中包含应用程序所需的每个模块,然后将所有这些 ...

  4. 【阿里云训练营】python查漏补缺 1

    文章来自:微信公众号[机器学习炼丹术]. 有问题疑惑,或者想交流交朋友的可以加个人微信:cyx645016617 参考目录: 目录 1 注释 2 is 与 == 3 运算优先级 4 查找所有属性和方法 ...

  5. 机器学习,详解SVM软间隔与对偶问题

    今天是机器学习专题的第34篇文章,我们继续来聊聊SVM模型. 我们在上一篇文章当中推导了SVM模型在硬间隔的原理以及公式,最后我们消去了所有的变量,只剩下了\(\alpha\).在硬间隔模型当中,样本 ...

  6. Activiti7 组任务

    需求:在流程定义中在任务节点的assignee固定设置任务负责人,这种情况不是很好,如果有天任务负责人请假了,你想请假,等着吧..没人审批,针对这种情况,可以给任务设置多个候选人,可以从候选中选择参与 ...

  7. SpringBoot程序启动时在Oracle数据库中建表充值

    例子工程下载链接:https://files.cnblogs.com/files/xiandedanteng/gatling20200428-1.zip 需求:在工程启动时在Oracle数据库中建表. ...

  8. MyBatis的逆向工程、Example类

    public void testFindUserByName(){ //通过criteria构造查询条件 UserExample userExample = new UserExample(); us ...

  9. 业务级别MySQL

    业务级别MySQL 目录 业务级别MySQL 1. 权限管理和备份 1. 用户管理 1. SQLyog可视化操作 2. SQL命令操作 2. MySQL备份 3. 规范数据库设计 1. 为什么需要设计 ...

  10. python中的算数运算符+、-、*、/、//、%、**

    例如a=5,b=2 +    两个对象相加                              a+b=7 -    两个对象相减                              a- ...