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. elasticsearch 基础性操作

    1 基础概念 Elasticsearch是一个近实时的系统,从你写入数据到数据可以被检索到,一般会有1秒钟的延时.Elasticsearch是基于Lucene的,Lucene的读写是两个分开的句柄,往 ...

  2. FizzBuzz and Fibonacci优化

    ***************************************转载请注明出处:http://blog.csdn.net/lttree************************** ...

  3. webstrom 很卡 底下一直走进度条 scanning files to index

    最近工作总会遇到一些问题 先说说webstrom 其中有一次仅仅开了两个项目 电脑风扇就各种轰鸣 各种重启 安装卸载webstrom 都没有作用 好吧 其实解决很简单 选择一个文件夹,右键, Mark ...

  4. Transform.eulerAngles 欧拉角

    var eulerAngles : Vector3 Description描述 The rotation as Euler angles in degrees. 旋转作为欧拉角度. The x, y, ...

  5. react-native 启动页(react-native-splash-screen)

    用于解决iOS和Android启动白屏问题及简单的启动页面展示 下载 react-native-splash-screen yarn add react-native-splash-screen re ...

  6. 计算两个有序数组的第K大数(转)

    传统解法,最直观的解法是O(m+n).直接merge两个数组,然后求第K大的数字. 如果想要时间复杂度将为O(log(m+n)).我们可以考虑从K入手.如果我们每次能够删除一个一定在第K个元素之前的元 ...

  7. 使用nginx搭建https服务器(转)

    最近在研究nginx,整好遇到一个需求就是希望服务器与客户端之间传输内容是加密的,防止中间监听泄露信息,但是去证书服务商那边申请证书又不合算,因为访问服务器的都是内部人士,所以自己给自己颁发证书,忽略 ...

  8. web开发中的路径问题

    http://www.cnblogs.com/tianguook/archive/2012/08/31/2665755.html 转自:http://www.blogjava.net/meil/arc ...

  9. shadow密码文件

    登录Linux会要求输入用户名和密码.通常本地文件中会存储一份用户密码,并与用户输入对比,如果相同就允许用户登录.起初用户密码存储与/etc/passwd中,但由于/etc/passwd必须供所有用户 ...

  10. CocoaPods报错:The dependency `` is not used in any concrete target

    内容提要: podfile升级之后到最新版本,pod里的内容必须明确指出所用第三方库的target,否则会出现The dependency `` is not used in any concrete ...