BAT站在中国互联网的顶端,引导着中国互联网的发展走向。。。既受到了多数程序员的关注,也在被我们所惦记着。。。

  关于SmartQQ的协议来自HexBlog,根据他的博客我自己也一步一步的去分析,去尝试,自己不了解不知道的总是神秘的,如果你有这种好奇心,那么真相就只有一个。接下来我先把协议放出来,至于分析方法,以后有机会再谈谈。。。其实我也是个半吊子水平。。。谁知道下次改了协议还灵不灵呢!

  登录之前,获取二维码:https://ssl.ptlogin2.qq.com/ptqrshow?appid=501004106&e=0&l=M&s=5&d=72&v=4&t=0.22925435146316886,refer为:https://ui.ptlogin2.qq.com/cgi-bin/login

  循环获取二维码状态(是否失效,是否在手机上授权):https://ssl.ptlogin2.qq.com/ptqrlogin?webqq_type=10&remember_uin=1&login2qq=1&aid=501004106&u1=http%3A%2F%2Fw.qq.com%2Fproxy.html%3Flogin2qq%3D1%26webqq_type%3D10&ptredirect=0&ptlang=2052&daid=164&from_ui=1&pttype=1&dumy=&fp=loginerroralert&action=0-0-136435&mibao_css=m_webqq&t=undefined&g=1&js_type=0&js_ver=10139&login_sig=&pt_randsalt=0   refer为:https://ui.ptlogin2.qq.com/cgi-bin/login

  获取cookie中ptwebqq:这次的url是手机扫描二维码之后得到的返回值。refer不变。

  获取返回值vfwebqq:http://s.web2.qq.com/api/getvfwebqq?ptwebqq=" + ptwebqq + "&clientid=53999199&psessionid=&t=1446710396202。refer为http://s.web2.qq.com/proxy.html?v=20130916001&callback=1&id=1。

  成功登录,得到uin,psessionid:http://d.web2.qq.com/channel/login2,refer为http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=2,数据为:"r=%7B%22ptwebqq%22%3A%22"+ptwebqq+"%22%2C%22clientid%22%3A53999199%2C%22psessionid%22%3A%22%22%2C%22status%22%3A%22online%22%7D",host地址为:"d1.web2.qq.com"

  根据得到的信息获取好友列表:http://s.web2.qq.com/api/get_user_friends2,数据为:data="r=%7B%22vfwebqq%22%3A%22"+vfwebqq+"%22%2C%22hash%22%3A%22"+__hash+"%22%7D",refer为:http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=2

  让我们来看看程序:

  

  下面我们用python来尝试一下(分为两个文件,其中继续沿用我们的HttpClient类,以及WebQQ类,代码如下):

 #HttpClient.py
  # -*- coding: utf-8 -*-
import cookielib, urllib, urllib2, socket class HttpClient:
__cookie = cookielib.CookieJar()
__req = urllib2.build_opener(urllib2.HTTPCookieProcessor(__cookie))
__req.addheaders = [
('Accept', 'application/javascript, */*;q=0.8'),
('User-Agent', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)')
]
urllib2.install_opener(__req) def Get(self, url, refer=None):
try:
req = urllib2.Request(url)
if not (refer is None):
req.add_header('Referer', refer)
return urllib2.urlopen(req, timeout=120).read()
except urllib2.HTTPError, e:
return e.read()
except socket.timeout, e:
return ''
except socket.error, e:
return '' def GetWithOutRead(self, url, refer=None):
try:
req = urllib2.Request(url)
if not (refer is None):
req.add_header('Referer', refer)
return urllib2.urlopen(req, timeout=120)
except urllib2.HTTPError, e:
return e.read()
except socket.timeout, e:
return ''
except socket.error, e:
return '' def Post(self, url, data, refer=None):
try:
#req = urllib2.Request(url, urllib.urlencode(data))
req = urllib2.Request(url,data)
if not (refer is None):
req.add_header('Referer', refer)
return urllib2.urlopen(req, timeout=120).read()
except urllib2.HTTPError, e:
return e.read()
except socket.timeout, e:
return ''
except socket.error, e:
return '' def Download(self, url, file):
output = open(file, 'wb')
output.write(urllib2.urlopen(url).read())
output.close() def getCookie(self, key):
for c in self.__cookie:
if c.name == key:
return c.value
return '' def setCookie(self, key, val, domain):
ck = cookielib.Cookie(version=0, name=key, value=val, port=None, port_specified=False, domain=domain, domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False)
self.__cookie.set_cookie(ck)
 #WebQQ.py
# -*- coding: utf-8 -*-
from Tkinter import *
from time import sleep
from HttpClient import HttpClient
import json,io
from multiprocessing import Process
import multiprocessing
from PIL import Image, ImageTk
class WebQQ(HttpClient):
def __init__(self):
self.__cookie = ""
self.__ptwebqq = ""
self.__vfwebqq = ""
self.__hash = ""
self.__uin = ""
self.__root = ""
self.__psessionid = ""
self.queue = multiprocessing.Queue() #获取二维码
def __ptqrshow(self):
img = self.Get(url="https://ssl.ptlogin2.qq.com/ptqrshow?appid=501004106&e=0&l=M&s=5&d=72&v=4&t=0.4139144900254905")
if(img!=None):
data_stream = io.BytesIO(img)
imgfile = Image.open(data_stream)
p = Process(target=self._run_proc, args=(imgfile,))
p.start()
print(u"二维码下载完毕,请尽快扫描...")
return True
else:
print(u"二维码下载失败")
return False #检测扫码状态,登录进度
def __ptqrlogin(self):
res = self.Get("https://ssl.ptlogin2.qq.com/ptqrlogin?webqq_type=10&remember_uin=1"+
"&login2qq=1&aid=501004106&u1=http%3A%2F%2Fw.qq.com%2Fproxy.html%3Flogin2qq%3D1%26webqq_type%3D10"+
"&ptredirect=0&ptlang=2052&daid=164&from_ui=1&pttype=1&dumy=&fp=loginerroralert&action=0-0-136435"+
"&mibao_css=m_webqq&t=undefined&g=1&js_type=0&js_ver=10139&login_sig=&pt_randsalt=0",
"https://ui.ptlogin2.qq.com/cgi-bin/login")
if(res!=None):
result = res.find("登录成功")
if(result==-1):
sleep(1) return self.__ptqrlogin()
elif(result!=-1):
res = res.decode("UTF-8")
return self.__check_sig(res[res.find("http"):res.find(u"','0','登录成功!'")].encode())
else:
return False
else:
return False
#获得ptwebqq cookie
def __check_sig(self,url):
res = self.Get(url=url,refer="https://ui.ptlogin2.qq.com/cgi-bin/login")
if(res!=None):
self.__ptwebqq = self.getCookie("ptwebqq")
self.__getvfwebqq()
return self.__login2()
else:
return False
#获得vfwebqq cookie
def __getvfwebqq(self):
res = self.Get(url="http://s.web2.qq.com/api/getvfwebqq?ptwebqq="+self.__ptwebqq+
"&clientid=53999199&psessionid=&t=1446710396202",
refer="http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=1")
if(res!=None):
jsn = json.loads(res)
self.__vfwebqq = jsn["result"]["vfwebqq"]
#登录 获取uin psessionid
def __login2(self):
data = "r=%7B%22ptwebqq%22%3A%22"+self.__ptwebqq+"%22%2C%22clientid%22%3A53999199%2C%22psessionid%22%3A%22%22%2C%22status%22%3A%22online%22%7D" res = self.Post(url = "http://d1.web2.qq.com/channel/login2",
data = data.encode(encoding="utf8"),
refer = "http://d.web2.qq.com/proxy.html?v=20130916001&callback=1&id=2")
if(res==None):
return False
jsn = json.loads(res)
if(jsn["retcode"]==0):
self.__uin = jsn["result"]["uin"]
self.__psessionid = jsn["result"]["psessionid"]
self.__hash = self.__friendsHash(self.__uin,self.__ptwebqq)
self.__get_user_friends()
return True
else:
return False
#好友的hash 参考HexBlog
def __friendsHash(self,uin,pt):
N=[0 for x in range(4)]
V=[0 for x in range(4)]
U=[0 for x in range(8)]
# 字符串转换为字符数组
k=pt.encode(encoding="UTF8")
n=["","","","","","","","","","","A","B","C","D","E","F"]
for x in range(len(k)):
N[x%4]^=ord(k[x])
x=int(uin)
V[0] = x >> 24 & 255 ^ 69;
V[1] = x >> 16 & 255 ^ 67;
V[2] = x >> 8 & 255 ^ 79;
V[3] = x & 255 ^ 75;
for x in range(8):
U[x]=(x%2==0) and N[x>>1] or V[x>>1]
result=""
for x in U:
result+=n[x>>4&15]
result+=n[x&15]
return result
#获取好友列表
def __get_user_friends(self):
data="r=%7B%22vfwebqq%22%3A%22"+self.__vfwebqq+"%22%2C%22hash%22%3A%22"+self.__hash+"%22%7D"
res=self.Post(url="http://s.web2.qq.com/api/get_user_friends2",
data=data.encode(encoding="utf8"),
refer="http://s.web2.qq.com/proxy.html?v=20130916001&callback=1&id=1")
if(res!=None):
# 记录好友列表
jsn=json.loads(res)
if(jsn["retcode"]==0):
# 正确返回列表后
for x in jsn["result"]["marknames"]:
print (x["markname"])
#心跳包并接收消息,现在不能用了
#def __poll(self):
# data="r=%7B%22ptwebqq%22%3A%22"+self.__ptwebqq+"%22%2C%22clientid%22%3A53999199%2C%22psessionid%22%3A%22"+self.__psessionid +"%22%2C%22key%22%3A%22%22%7D"
# res=self.Post(url="http://d1.web2.qq.com/channel/poll2",
# data=data.encode(encoding="utf8"),
# refer="http://d1.web2.qq.com/proxy.html?v=20151105001&callback=1&id=2")
# if(res!=None):
# print res def __check_queue(self):
try:
out = self.queue.get_nowait()
if out == 'stop':
self.__do_stop()
return
# Could check for other commands here, too
except :
pass
self.__root.after(100, self.__check_queue) def __stop(self):
self.queue.put('stop') def __do_stop(self):
self.__root.destroy() def _run_proc(self,imgfile):
self.__root = Tk()
result = ImageTk.PhotoImage(imgfile)
label = Label(self.__root, image=result)
label.pack()
self.__root.after(100, self.__check_queue)
self.__root.mainloop()
def run(self):
if(self.__ptqrshow()):
if(self.__ptqrlogin()):
print(u"登录成功")
self.__stop() if __name__ =="__main__":
qq=WebQQ()
qq.run()

最新文章

  1. Linux学习笔记(17) Shell编程之基础
  2. Representation Data in OpenCascade BRep
  3. U-BLOX GPS 模块及GPRMC指令解析
  4. webclient 比浏览器加载页面慢的一个问题
  5. PHP利用Curl实现多线程抓取网页和下载文件
  6. android WebView问题
  7. 转!!数据库 第一范式(1NF) 第二范式(2NF) 第三范式(3NF)的 联系和区别
  8. fedora22 无法联网的情况下rpm安装gcc5.1
  9. 将vs屏幕上内容重定向到一个log文本中
  10. Git提交代码的处理流程(转)
  11. BizTalk 2016 配置 RosettaNet遇到的坑
  12. 【Spring源码分析系列】ApplicationContext 相关接口架构分析
  13. [leetcode](4.21)2. 按字典序排列最小的等效字符串
  14. JS实现网站内容的禁止复制和粘贴、另存为
  15. Python基础-python基本语法(二)
  16. MySQL数据库的学习
  17. Spring集成MyBatis的使用-使用Mapper映射器
  18. Delphi 完全时尚手册之 Visual Style 篇 (界面不错) 转自http://blog.csdn.net/iseekcode/article/details/4733229
  19. 【leetcode】solution in java——Easy5
  20. 数据库事物用法 SET XACT_ABORT ON

热门文章

  1. CF1148D-Dirty Deeds Done Dirt Cheap
  2. EF 配置
  3. C语言比较好的风格梳理
  4. 铁大FaceBook的使用体验副本
  5. hdu 5170 精度控制
  6. Delphi 10.3.2最新消息
  7. [Bzoj4195] [NOI2015] 程序自动分析 [并查集,哈希,map] 题解
  8. 2.3. Configuring sudo Access-RedHat
  9. 洛谷 P3078 [USACO13MAR]扑克牌型Poker Hands
  10. 洛谷 P2965 [USACO09NOV]农活比赛The Grand Farm-off