web微信

1.扫码获取头像

当你打开web微信的时候,因为http是无状态的,web微信如何实时的获取用户的扫码动作?

那么这里用到的是长轮询的方式。

from flask import Flask,request,redirect,render_template,session,jsonify
import time
import requests
import re
from bs4 import BeautifulSoup
import json app =Flask(__name__)
app.secret_key='adfa12da' @app.route('/login',methods=['GET',"POST"])
def login():
'''
扫码获取头像
:return:
'''
if request.method=='GET':
ctime = str(int(time.time()*1000))
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}'.format(ctime)
ret = requests.get(qcode_url)
qcode = re.findall('uuid = "(.*)";',ret.text)[0]
session['qcode'] = qcode
session['login_cookies'] = ret.cookies.get_dict()
return render_template('login.html',qcode=qcode) else:
pass ####Html#########
<img id="img" src="https://login.weixin.qq.com/qrcode/{{qcode}}">

获取web微信头像

2.点击登录

a.当扫码成功后获取到了web头像,依旧要执行长轮询,我们需要做的是获取发起长轮询的url,

b.将登录成功的cookies保存在session里。

c.模仿浏览器自动访问并且挂起。当登录成功后,状态码为200,跳转到主页面

@app.route('/check_login',methods=['GET','POST'])
def check_login():
'''
检测是否已经登录.
url:https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid=AcjVHfghyA==&tip=0&r=-557419402&_=1529565723654
:return:
'''
if request.method=='GET':
response= {'code':408}
qcode = session.get('qcode')
ctime = str(int(time.time()*1000))
check_url = 'https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login?loginicon=true&uuid={0}&tip=0&r=-557419402&_={1}'.format(qcode,ctime)
ret = requests.get(url=check_url)
print(ret.text)
if 'code=201' in ret.text:
src = re.findall("userAvatar = '(.*)';",ret.text)[0]
response['code']=201
response['src'] = src elif 'code=200' in ret.text:
src = re.findall('redirect_uri="(.*);',ret.text)[0]
response['code']=200
response['src']=src
ret = requests.get(url=src+'&fun=new&version=v2&lang=zh_CN')
xml_dic = xml_parser(ret.text)
session['xml_dic']=xml_dic
session['pass_cookies'] = ret.cookies.get_dict()
print(xml_dic)
return jsonify(response) ####js代码####
#不断的发送长轮询 当返回的状态码为200的时候跳转页面
$(function () {
check_login();
}); function check_login() {
$.ajax({
url:'/check_login',
type:'GET',
datatype:'JSON',
success:function (arg) {
if (arg.code == 201){
$('#img').attr('src',arg.src);
check_login();
}
else if (arg.code == 200){
location.href='/index'
}else {
check_login();
} } })
}

登录成功

3.获取个人信息和联系人列表

a.当登录成功后,进行获取个人的信息,存放在session里方便后面的使用。

b.获取联系人列表在前端展示.

@app.route('/index',methods=['GET',"POST"])
def index(): pass_ticket =session['xml_dic'].get('pass_ticket')
inni_dic={
'BaseRequest':{
'DeviceID':"e901523268059245",
'Sid':session['xml_dic'].get('wxsid'),
'Skey':session['xml_dic'].get('skey'),
'Uin':session['xml_dic'].get('wxuin'),
}
}
inni_msg = requests.post(
url ='https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit?r=-581032482&lang=zh_CN&pass_ticket={0}'.format(pass_ticket),
json=inni_dic
)
inni_msg.encoding='utf-8'
user_dict = inni_msg.json()
session['user_info'] = user_dict['User']
session['SyncKey'] = user_dict['SyncKey'] ctime= str(int(time.time()*1000))
contact_url= 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact?lang=zh_CN&pass_ticket={0}&r={1}&seq=0&skey={2}'
contact_url = contact_url.format(pass_ticket,ctime,session['xml_dic'].get('skey'))
pass_cookies = session.get('pass_cookies')
contact_list = requests.get(
url=contact_url,
cookies = pass_cookies,
)
contact_list.encoding = 'utf-8'
result_list = contact_list.json() return render_template('index.html',user_dict=user_dict,result_list=result_list) ####前端代码#### <body>
<h1>Welcome {{user_dict.User.NickName}}!!</h1>
<img src="/get_img" alt="">
<ul>
{%for row in user_dict.ContactList%}
<li>{{row.NickName}}</li>
{%endfor%}
</ul> <div>
<h1>全部联系人</h1>
<ul>
{% for item in result_list.MemberList%}
<li>{{item.UserName}}===={{item.NickName}}</li>
{%endfor%}
</ul>
</div>
</body>

4.登录成功后获取头像

#<img src="/get_img" alt="">

@app.route('/get_img',methods=['GET','POST'])
def get_img(): # 需要不断的试cookies
# 登录以后的操作一般都需要cookies, 一般cookies是拿登录成功后的 # 特殊的需要将cookies成功之后才能进行登录,访问的时候就记录cookies # headers的重要参数: Referer host User_Agent user_info = session.get('user_info')
pass_cookies = session.get('pass_cookies')
header_url = "https://wx2.qq.com"+user_info['HeadImgUrl']
ret = requests.get(
url = header_url,
cookies = pass_cookies,
headers= {
'Content-Type': 'image/jpeg',
}
)
return ret.content

5.发送信息

登录成功后,拿到了联系人列表,其中返回的信息里面的MemberList有每个人的NickName.

用Ajax给他人发送消息

@app.route('/send_msg',methods=['GET','POST'])
def send_msg():
if request.method=='GET':
return 'what are you 弄啥呢'
else:
data =request.form
to = data.get('to')
content = data.get('content')
print(to,content)
user = session['user_info']['UserName']
pass_ticket =session['xml_dic'].get('pass_ticket')
ctime= str(int(time.time()*1000))
send_url ='https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg?lang=zh_CN&pass_ticket={0}'.format(pass_ticket) send_dict = {
'BaseRequest':{
'DeviceID': "e901523268059245",
'Sid': session['xml_dic'].get('wxsid'),
'Skey': session['xml_dic'].get('skey'),
'Uin': session['xml_dic'].get('wxuin'),
},
'Msg':{'ClientMsgId':ctime,
'LocalID':ctime,
'FromUserName':user,
'ToUserName':to,
'Type':1,
'Content':content,
},
'Scene':0,} ret = requests.post(
url=send_url,
data=bytes(json.dumps(send_dict,ensure_ascii=False),encoding='utf-8'),
) return ret.text
###前端代码#### <body>
<form id="fm">
<input type="text" name="to" placeholder="联系人">
<input type="text" name="content" placeholder="内容">
<button onclick="send_msg();">提交</button>
</form> function send_msg() {
$.ajax({
url:'/send_msg',
data:$('#fm').serialize(),
type:'POST',
dataType:'JSON',
success:function (arg) {
if (arg.BaseResponse.Ret == 0){
console.log('发送成功');
$('#fm').find(':input').val('')
}
}
})
}

发送信息

json.dumps需要注意的问题

json.dumps需要注意的问题

6.接收信息

接收消息也是不断的向服务端发送请求,检查是否有人发送消息

@app.route('/get_msg',methods=['GET','POST'])
def get_msg():
user_init_list = session.get('SyncKey').get('List')
syn_list=[]
for item in user_init_list:
temp = '%s_%s'%(item['Key'],item['Val'])
syn_list.append(temp) syn_list_str = '|'.join(syn_list)
get_url = 'https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin/synccheck'
ctime = str(int(time.time() * 1000))
syn_dict={
'r':ctime,
'DeviceID': "e901523268059245",
'Sid': session['xml_dic'].get('wxsid'),
'Skey': session['xml_dic'].get('skey'),
'Uin': session['xml_dic'].get('wxuin'),
'synckey':syn_list_str
}
all_cookies={}
all_cookies.update(session['login_cookies'])
all_cookies.update(session['pass_cookies'])
response = requests.get(
url=get_url,params=syn_dict,cookies=all_cookies
)
print(response.text)
if 'selector:"2"' in response.text:
data = {
'BaseRequest': {
'DeviceID': "e901523268059245",
'Sid': session['xml_dic'].get('wxsid'),
'Skey': session['xml_dic'].get('skey'),
'Uin': session['xml_dic'].get('wxuin'),
},
'synckey': session.get('SyncKey'),
'rr': ctime,
}
url = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync?sid={0}&skey={1}'.format(session['xml_dic'].get('wxsid'),
session['xml_dic'].get('skey'), )
response_msg = requests.post(
url=url,json=data
)
response_msg.encoding = 'utf-8'
response_msg_dic = response_msg.json()
session['SyncKey'] = response_msg_dic['SyncKey']
for item in response_msg_dic:
print(item['Content'],'=========>',item['FromUserName'],'========',item['ToUserName'])
return 'pass' #######前端#######
$(function () {
get_msg();
}); function get_msg() {
$.ajax({
url:'/get_msg',
type:'GET',
success:function (arg) {
if (arg){
get_msg();
}
}
})
}

轮询

轮询:
浏览器每一段时间(2s)向浏览器发一次请求,检查用户是否扫码.
浏览器发的url主要是检验用户是否扫码,只要扫码就返回头像 缺点:不断的向服务器发请求,服务器的内存压力大, 效率低,存在时间差 长轮询:
浏览器在像web微信服务器发请求的时候,没有立即断开而是挂在那里,一直连接着,
最多连接30秒,自动断开后,又马上挂起一个请求
只要用户一扫码服务器就可以马上检测到.

高性能

  高性能相关:
开进程->单线程
本质:
浏览器本质:1.socket客户端遵循HTTP协议
2.http协议建立在tcp协议之上
3.规定了发送的时候的数据格式 \r\n\r\n
4.短连接,无状态

协程

协程是'微线程',真实是不存在的,是程序员人为创造出来并控制程序先执行段代码,再执行某段代码.
-如果遇到非IO请求就切换,性能低.
-如果遇到IO请求切换,性能高.能够实现并发(IO等待的过程,再去干其他的事)

IO多路复用

select: 内部循环监听多个socket对象是否发生状态的变化 最多1024个
poll: 内部循环监听多个socket对象是否发生状态的变化
epoll: 回调的方式 通过硬件和操作系统

基于flask的web微信的更多相关文章

  1. 基于Flask 实现Web微信登陆

    网页版微信登陆网址 https://login.wx.qq.com/ 获取微信登陆的二维码 在浏览器中访问登陆接口 https://login.wx.qq.com/ 我们查找二维码的图片可以看到 其中 ...

  2. 基于Flask开发web微信

    1. 获取二维码 app.py import re import time import requests from flask import Flask,render_template app = ...

  3. 树莓派搭建基于flask的web服务器-通过移动端控制LED

    1.概述 在局域网内,基于flask搭建web服务,从而可以使用移动客户端访问该web服务.由于是flask新手,所以本次实现的web服务功能较为简单,即控制LED灯的开/关及闪烁. 2.准备工作 2 ...

  4. 基于Flask的Web应用程序插件式结构开发

    事实上,很多应用程序基于插件式结构开发,可以很方便了扩展软件的功能,并且这些功能完全可以依托于第三方开发者,只要提供好接口和完备文档,比如wordpress.谷歌火狐浏览器等. Python这样的动态 ...

  5. 基于Flask的Web应用部署到SAE上遇到的问题

    我的应用底层数据库用的是MySQL,利用Flask-SQLALchemy实现接口操作.我遇到的问题是: 在我把代码部署到SAE上后,当数据向数据库insert的时候总是出现“2006,MySQL ha ...

  6. 基于Flask实现博客开发--准备工作

    背景说明 本项目是基于<深入理解flask>一书,主要是用来记录学习历程和交流心得,所以写得不好请大神勿喷. 准备工作 virtualenv介绍 也许 Virtualenv 是你在开发中最 ...

  7. SZhe_Scan碎遮:一款基于Flask框架的web漏洞扫描神器

    SZhe_Scan碎遮:一款基于Flask框架的web漏洞扫描神器 天幕如遮,唯我一刀可碎千里华盖,纵横四海而无阻,是谓碎遮 --取自<有匪> 写在前面 这段时间很多时间都在忙着编写该项目 ...

  8. Python flask 基于 Flask 提供 RESTful Web 服务

    转载自 http://python.jobbole.com/87118/ 什么是 REST REST 全称是 Representational State Transfer,翻译成中文是『表现层状态转 ...

  9. 《Flask Web开发——基于Python的Web应用开发实践》一字一句上机实践(上)

    目录 前言 第1章 安装 第2章 程序的基本结构 第3章 模板 第4章 Web表单 第5章 数据库 第6章 电子邮件 第7章 大型程序的结构   前言 学习Python也有一个半月时间了,学到现在感觉 ...

随机推荐

  1. ListView控件绑定DataSet

    DataSet数据集,数据缓存在客户端内存中,支持断开式连接.   在对DataSet做操作的时候,首先一定要修改其行的状态,然后执行SqlDataAdapter的Update方法,Update方法根 ...

  2. scss使用后的简单入门总结

    端午节第一天 将之前做的一个小demo的css样式改为了scss 好吧 改完了 赶紧由小兵 升级到中尉了 什么是scss? 我的理解是scss 就是css 的预处理器,使css变得更加富有逻辑. 有什 ...

  3. URL相对路径和URL绝对路径

    经常在页面中引用图片,html页面等,自己常常弄错相对路径和绝对路径,今天写下此文总结一下.    直接举例说明吧. 在 D:\例子\html下有这么几个文件和文件夹     1.若引用的资源和本身在 ...

  4. html中插入php的方法

    .html文件是不可以被读取为php文件的必须修改后缀名为.php这个时候如果你在浏览器中调用此页面所有的HTML代码都会被正确显示 这个时候你可以在文件的任意为止插入<?php ?>作为 ...

  5. axios 处理并发请求

    //同时发起多个请求时的处理 axios.all([get1(), get2()]) .then(axios.spread(function (res1, res2) { // 只有两个请求都完成才会 ...

  6. Java 分页之最简单的算法

    分页实现有很多方式,如jQuery自带框架pagination或在java封装一个类pager等.   下写一个简单易懂的分页算法   逻辑:   // 步骤1:设置每页页数大小 long pageS ...

  7. Spring Framework简单介绍

    Spring Framework        学习java编程不知不觉已经三年时间了,開始的时候,总是喜欢看着视频,然后按部就班的敲打着键盘,每当系统正常执行后.心里乐开了花.最開始的时候,所有的代 ...

  8. 【COCOS2DX-LUA 脚本开发之一】在Cocos2dX游戏中使用Lua脚本进行游戏开发(基础篇)并介绍脚本在游戏中详细用途!

    [COCOS2DX-LUA 脚本开发之一]在Cocos2dX游戏中使用Lua脚本进行游戏开发(基础篇)并介绍脚本在游戏中详细用途! 分类: [Cocos2dx Lua 脚本开发 ] 2012-04-1 ...

  9. amchart 图表设置

    官网:https://www.amcharts.com/demos/ 属性介绍:https://docs.amcharts.com/3/javascriptcharts/AmLegend 安装 bow ...

  10. eclipse JVM Tomcat 内存堆栈大小设置

    1,  设置Eclipse内存使用情况 修改eclipse根目录下的eclipse.ini文件 -vmargs  //虚拟机设置 -Xms40m //初始内存 -Xmx256m //最大内存 -Xmn ...