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. caffe卷积层代码阅读笔记

    卷积的实现思想: 通过im2col将image转为一个matrix,将卷积操作转为矩阵乘法运算 通过调用GEMM完毕运算操作 以下两个图是我在知乎中发现的,"盗"用一下,确实非常好 ...

  2. Hadoop之——分布式集群安装过程简化版

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46352315 1.hadoop的分布式安装过程 1.1 分布结构 主节点(1个,是 ...

  3. C++基础学习教程(一)

    開始自己的C++复习进阶之路. 声明: 这次写的博文纯当是一个回想复习的教程.一些非常基础的知识将不再出现.或者一掠而过,这次的主要风格就是演示样例代码非常多~~~ 全部代码在Ubuntu 14.04 ...

  4. swoole编译安装/数据库连接池/异步mysql客户端

    一.编译安装php5.6 0.安装必要软件 http://www.cnblogs.com/itfenqing/p/6055138.html 1.下载php5.6.30 http://php.net/d ...

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

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

  6. python——type()创建类

    今天我算是长知识了,我是一个python菜鸟,以前一直认为type(A)可以返回A的类型,但是不知道type还可以用于创建class,这篇经验就是介绍一下如何用type()创建一个类,以及如何设置该类 ...

  7. html中插入php的方法

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

  8. 【BIEE】11_BIEE图形报表在谷歌浏览器64.0.3282.140中访问图例乱码解决

    如上图,使用谷歌浏览器访问BIEE图形报表的时候,标题.图例等涉及到中文的地方全部乱码了!但是用IE打开是不会乱码的,这是由于:谷歌需要设置编码格式 但是55版本以后,谷歌公司为了加快浏览器的速度,提 ...

  9. <转>Windows平台下Makefile学习笔记(一)

    本文转自:http://blog.csdn.net/clever101/article/details/8147352 决心学习Makefile,一方面是为了解决编译开源代码时需要跨编译平台的问题(发 ...

  10. 什么是CouchDB?

    ※本文对CouchDB的解释是来自Apache CouchDB的官网的译文,如果有什么问题,请指正. 1.CouchDB简介 CouchDB是一种利用JSON文件,javascript作为MapRed ...