一键生成属于自己的QQ历史报告,看看你对自己的QQ了解程度有多深?

简介

近几年,由于微信的流行,大部分人不再频繁使用QQ,所以我们对于自己的QQ数据并不是特别了解。我相信,如果能够生成一份属于自己的QQ历史报告,那将是无比开心的一件事。

目前网上关于QQ的数据分析工具较少,原因是QQ相关接口比较复杂。而本程序的运行十分简单,具有良好的用户交互界面,只需要扫码登录一步操作即可。

目前本程序获取的数据包括:QQ详细数据、手机在线时间、非隐身状态下在线时间、QQ活跃时间、单向好友数量、QQ财产分析、群聊分析、过去一年我退出的群聊数据、退去一个月我删除的好友数据、所有代付信息、我最在意的人以及最在意我的人。由于相关的数据接口有访问限制,所以本程序并没有对QQ好友进行分析。

功能截图







如何运行

# 跳转到当前目录
cd 目录名
# 先卸载依赖库
pip uninstall -y -r requirement.txt
# 再重新安装依赖库
pip install -r requirement.txt
# 开始运行
python main.py

编写思路

本程序分为多个模块,模块如下:

  1. main.py,主程序,用于获取并处理相关数据,并导出数据报告。
  2. qq_bot.py, 核心模块,实现了qq相关的接口,较为复杂。
  3. tkinter_gui.py,绘制gui模块,使用tkinter绘制基本的交互界面。
  4. static_data.py,数据存储模块,所有数据采用base64编码存储。

main.py模块

首先,初始化相关文件夹,并调用qq_bot.py模块,定义一个qq bot对象,该对象为本程序的核心对象,所有数据获取均从该对象获取。

同时,本程序数据的报告文件为.md格式

	# 初始化文件夹
init_folders()
# 写入项目所需资源文件到本地目录
write_data() # 创建一个自己编写的qq bot对象
bot = Bot()
custom_print(u'登录成功,正在获取数据...') # 定义欲输出的markdown字符串
markdown_content = '''
<p align="center">
<font size='6px'>{qq_number}的个人QQ历史报告</font>
<img src="{qq_icon_png}" align="right" height="60">
</p>
'''
# 更新一下欲输出的markdown文本
markdown_content = markdown_content.replace('{qq_number}',bot.qq_number)
markdown_content = markdown_content.replace('{qq_icon_png}', 'data/qq_icon.png')

登录成功后,开始获取该登录账户的详细资料

    custom_print(u'正在获取该登录账户的详细数据...')
detail_information = bot.get_detail_information()
# content为markdown语法文本
content = '\n<br/><br/>\n' + '## 我的详细资料\n' + '种类|内容\n:- | :-\n'
for key, value in detail_information.items():
if key == 'qq_level':
star_count, moon_count, sun_count, crown_count = calculate_level(value)
data = crown_count * '![](data/level_crown.png)' + sun_count * '![](data/level_sun.png)' + moon_count * '![](data/level_moon.png)' + star_count * '![](data/level_star.png)'
content += '{}|{}\n'.format(key_dict[key], data)
else:
content += '{}|{}\n'.format(key_dict[key], value)
# 更新一下欲输出的markdown文本
markdown_content += content
markdown_content += '\n> 注:单向好友表示他/她的列表中有你,而你的列表中没有他/她'
# 每个步骤完成后,保存markdown文件,以便防止程序出错时能够保存到最新的数据
with open('{}的个人QQ历史报告.md'.format(bot.qq_number), 'w', encoding='utf-8') as file:
file.write(markdown_content)

接着,获取所有qq好友的备注名和qq号

    all_qq_friends = bot.get_all_friends_in_qq()
custom_print(u'所有qq好友号码和备注名中...')
qq_number_list = []
for key, friend_group in all_qq_friends.items():
for info in friend_group['mems']:
qq_number_list.append(info['uin'])

并获取所有群数据

    # 获取所有群信息
custom_print(u'获取该QQ加入的所有群信息...')
group_list = bot.get_group()
print(group_list)
# content为markdown语法文本
content = '\n\n<br/><br/>\n' + '## 我加入的群资料\n' + '序号|群名|群号|群主QQ\n:- | :-| :-| :-\n'
# 获取某个群的群成员信息
for index, group in enumerate(group_list):
group_number = group['gc']
group_name = group['gn']
owner = group['owner']
content += '{}|{}|{}|{}\n'.format(str(index+1), str(group_name), str(group_number), str(owner)) # 更新一下欲输出的markdown文本
markdown_content += content
# 每个步骤完成后,保存markdown文件,以便防止程序出错时能够保存到最新的数据
with open('{}的个人QQ历史报告.md'.format(bot.qq_number), 'w', encoding='utf-8') as file:
file.write(markdown_content)

接下来的步骤如你所需,也就是获取其他相关的数据,所以本小节就不一一详细解释了,您可以查看相关源代码查看。获取的数据包括:

  1. 获取过去30天内退出的群名单
  2. 获取过去364天内删除的好友名单
  3. 判断此次登录的qq是否为vip或者svip
  4. 获取qb值
  5. 获取代付信息
  6. 亲密度排行榜
  7. 共同好友数
  8. 成为好友的天数

qq_bot模块

此模块实现了获取qq数据的接口,主要通过抓包获得数据、分析数据,对参数进行加密解密等。

首先,是模拟扫码登录id.qq.com,qun.qq.com,qzone.qq.com。三者登录方式大同小异,唯一有区别的就是提交数据中的参数加密方式不同。

我们以id.qq.com登录为例:

    def login_id_qq_com(self):
# 登录id.qq.com # 访问网页,为了获取参数pt_login_sig
login_url = 'https://xui.ptlogin2.qq.com/cgi-bin/xlogin?pt_disable_pwd=1&appid=1006102&daid=1&style=23&hide_border=1&proxy_url=https://id.qq.com/login/proxy.html&s_url=https://id.qq.com/index.html'
html = get_html(login_url, '')
# 对返回的cookies进行转化为dict类型,方便处理
cookies_back_dict = dict_from_cookiejar(html.cookies)
pt_login_sig = cookies_back_dict['pt_login_sig']
self.cookies_merge_dict_in_id_qq_com.update(cookies_back_dict) # 访问网页,为了获取参数ptqrtoken
qrcode_url = 'https://ssl.ptlogin2.qq.com/ptqrshow?appid=1006102&e=2&l=M&s=4&d=72&v=4&t=0.10239549811477189&daid=1&pt_3rd_aid=0'
html = get_html(qrcode_url, '')
# 对返回的cookies进行转化为dict类型,方便处理
cookies_back_dict = dict_from_cookiejar(html.cookies)
qrsig = cookies_back_dict['qrsig']
ptqrtoken = hash33_token(qrsig)
self.cookies_merge_dict_in_id_qq_com.update(cookies_back_dict) # 将二维码显示到图片框
BytesIOObj = BytesIO()
BytesIOObj.write(html.content)
qr_code = PIL.Image.open(BytesIOObj)
image = PIL.ImageTk.PhotoImage(qr_code)
image_label['image'] = image # 实时检测二维码状态
while (True):
# 目标网址
target_url = 'https://ssl.ptlogin2.qq.com/ptqrlogin?u1=https://id.qq.com/index.html&ptqrtoken=' + str(ptqrtoken) + '&ptredirect=1&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=0-0-1556812236254&js_ver=19042519&js_type=1&login_sig=' + str(pt_login_sig) + '&pt_uistyle=40&aid=1006102&daid=1&' # 登录,需要带上访问cookies
html = get_html(target_url, self.cookies_merge_dict_in_id_qq_com) # 返回的响应码为200说明二维码没过期
if (html.status_code):
if ('二维码未失效' in html.text):
custom_print(u'(1/3)登录id.qq.com中,当前二维码未失效,请你扫描二维码进行登录')
elif ('二维码认证' in html.text):
custom_print(u'(1/3)登录id.qq.com中,扫描成功,正在认证中')
elif ('登录成功' in html.text):
self.is_login = True
custom_print(u'(1/3)登录id.qq.com中,登录成功')
break
if ('二维码已经失效' in html.text):
custom_print(u'(1/3)登录id.qq.com中,当前二维码已失效,请重启本软件')
exit() # 延时
time.sleep(2) # 登录成功后,把返回的cookies合并进去
self.cookies_merge_dict_in_id_qq_com = dict_from_cookiejar(html.cookies)
self.cookies_merge_dict_in_id_qq_com.update(cookies_back_dict)
# print(u'当前cookies:{}'.format(cookies_merge_dict)) # 获取此次登录的qq号码
qq_list = re.findall(r'&uin=(.+?)&service', html.text)
self.qq_number = qq_list[0] # 登录成功后,会返回一个地址,需要对该地址进行访问以便获取新的返回cookies
startIndex = (html.text).find('http')
endIndex = (html.text).find('pt_3rd_aid=0')
url = (html.text)[startIndex:endIndex] + 'pt_3rd_aid=0' # 屏蔽https证书警告
urllib3.disable_warnings() # 这里需要注意的是,需要禁止重定向,才能正确获得返回的cookies
html = get(url, cookies=self.cookies_merge_dict_in_id_qq_com, allow_redirects=False, verify=False)
# 把返回的cookies合并进去
cookies_back_dict = dict_from_cookiejar(html.cookies)
self.cookies_merge_dict_in_id_qq_com.update(cookies_back_dict)

首先是访问指定网址,获取参数pt_login_sig,其次是访问另外一个网址,获取参数qrsig,通过加密函数,将参数qrsig转化为ptqrtoken,然后就是获取二维码图片的状态了。当我们检测到登录成功时,就证明用户已经完成扫码操作,此时将网址返回的cookie保存下来。

这里要说明的是,加密函数的获取,需要具备一定的抓包基础才能获取得到。本程序的几个加密函数如下:

# 对qrsig进行基本的加密,该加密函数由抓包获得,需要具备一定抓包知识才能找到该加密函数
# 根据javascript版的加密函数,将其改写成python版本
def hash33_token(t):
e, n = 0, len(t)
for i in range(0,n):
e += (e << 5) + ord(t[i])
return 2147483647 & e # 对skey进行基本的加密,该加密函数由抓包获得,需要具备一定抓包知识才能找到该加密函数
# 根据javascript版的加密函数,将其改写成python版本
def hash33_bkn(skey):
e = skey
t = 5381 for n in range(0,len(e)):
t += (t << 5) + ord(e[n])
return 2147483647 & t

由于该模块下具有许多获取相关数据的qq接口,但是它们的形式非常相似,所以本节仅仅以获取所有qq群数据为例:

    def get_group(self):

        # 获取所有群基本信息
# bkn由参数skey通过另一个加密函数得到
bkn = hash33_bkn(self.cookies_merge_dict_in_qun_qq_com['skey'])
submit_data = {'bkn': bkn}
html = post_html('https://qun.qq.com/cgi-bin/qun_mgr/get_group_list', self.cookies_merge_dict_in_qun_qq_com, submit_data)
group_info = loads(html.text)
print(group_info)
return group_info['join']

这里主要涉及到的还是参数的加密、解密过程,这是一个难点,其他的话还是比较简单的。

tkinter_gui模块

这个模块是绘制基本的gui模块,采用python内置的tkinter模块完成,用法相当简单,这里就不详细讲了。

static_data模块

这个模块主要是用来存储相关的数据的,在程序每次运行时,将该静态资源文件输出。这么做的原因是可以防止用户将某些静态数据给删除了,导致程序运行错误。

补充

完整版源代码存放在github上,有需要的可以下载

项目持续更新,欢迎您star本项目

License

The MIT License (MIT)

一键生成属于自己的QQ历史报告,看看你对自己的QQ了解程度有多深?的更多相关文章

  1. 一键生成HTML4和WAP站

    前两天在QQ空间上提到微信上线风铃时,把其中的HTML5错打成HTML4,结果发现很多媒体微博照着转载,依旧说成 "一键生成HTML4和WAP站",这就是转载不注明出处.不署名.不 ...

  2. 个人永久性免费-Excel催化剂功能第57波-一键生成完全组合的笛卡尔积结果表

    在数据库的多表查询中,通常会有各种连接关系,同样地在Excel环境中,也有很大的场景需要用到类似数据库的多表查询,如经典的VLOOKUP就是其中一种类似LEFT JOIN查询的查询效果.在很多时候需要 ...

  3. [Java 开源项目]一款无需写任何代码,即可一键生成前后端代码的工具

    作者:HelloGitHub-小鱼干 JeecgBoot 是一款基于代码生成器的低代码开发平台,零代码开发.JeecgBoot 采用开发模式:Online Coding 模式-> 代码生成器模式 ...

  4. 开源框架 WebFirst 一键生成项目,在线建表

    1.WebFirst框架描述 WebFirst  是果糖大数据团队开发的新一代 高性能 代码生成器&数据库设计工具,由.net core 3.1 + sqlsugar 开发 导入1000个表只 ...

  5. 一键生成APP官网

    只需要输入苹果下载地址,安卓市场下载地址,或者内测下载地址,就能一键生成APP的官网,方便在网上推广. 好推APP官网 www.hotapp.cn/app

  6. Ant搭建 一键生成APP技术 平台

    1.博客概要 本文详细介绍了当今流行的一键生成APP技术.介绍了这种设计思想的来源,介绍了国内外的研究背景,并介绍了这个技术体系中的一些实现细节,欢迎各路大神们多提意见.一键生成技术,说的通俗点就是, ...

  7. 使用sencha cmd 一键生成你的应用程序代码

    一键生成你的应用程序代码: ------------------------------------------------------------ 我们的出发点就是使用命令来产生一个应用程序,执行以 ...

  8. Automator一键生成所需的iOS 图片icon

    iOS到8了, 终于受不了它的各种尺寸的icon了. 写一个Finder服务来一键生成吧. 拖放几次再重复, 无技术含量, 但很有用. // 存放目录    ~/资源库/Services/

  9. PHP通过(PDO)Mysql表字段一键生成创建sqlite的SQL

    首发于:http://www.zzzzy.com/201406053158.html /** * Mysql表字段一键生成创建sqlite的SQL 2 * @author: Skiychan < ...

随机推荐

  1. poj1185-炮兵阵地(状态压缩dp)

    炮兵阵地 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 25647   Accepted: 9892 Description ...

  2. Jmeter4.0----监控服务器性能(7)

    1.说明 JMeter是一款压力测试工具. 通常在压力测试中我们也需要监控和知道服务器的相关资源情况,jmeter本身不具备这个功能,今天我们主要说一下如何通过JMeter插件来监控服务器CPU.内存 ...

  3. SpringCloud多模块整理

    1.项目架构 —— project        父项目 —— client        子项目(客户端)    对外暴露的接口 —————— pom.xml          子项目的pom文件 ...

  4. JAVA的API部分介绍

    个人理解: Object作为最大的父类,里面存在不少方法,可以在API中具体的查找.比如可以帮助查看是否相同的equals方法,不过要想看具体属性是否相同需要得重写,打印.调用对象相当于调用其tost ...

  5. CF1168A Increasing by Modulo

    思路: 首先得做个转化,如果某个解法最终分别对a[i](i = 1, 2, ..., n)做了b[i](i = 1, 2, ..., n)次加1再取余的运算,那么可以等价地构造出x次(x = max( ...

  6. To the world you may be one person, but to one person you may be the world.

    To the world you may be one person, but to one person you may be the world.对于世界而言,你是一个人:但对于某人而言,你是他的 ...

  7. css3动画之圆形运动轨迹

    css3中通过@keyframes定义动画,animation设置动画属性,从而实现动画效果: 在animation属性当中,可以规定动画的名称.整个动画的运行时间.运动的速度曲线以及其延迟时间.播放 ...

  8. macOS Sierra 最新系统找回允许任何软件安装

    终端输入就可以了 安装macOS Sierra后,会发现系统偏好设置的“安全与隐私”中默认已经去除了允许“任何来源”App的选项,无法运行一些第三方应用. 如果需要恢复允许“任何来源”的选项,即关闭G ...

  9. Hadoop 2.7.0模拟分布式实验环境搭建[亲测]

    实验目的: 本实验通过在PC电脑上同时运行3个虚拟机,一个为master节点,两个slave节点.    搭建环境: 主机:mac os 10.10   OS:CenOS 6.5 虚拟机:VMware ...

  10. SubSonic框架使用图解

    简介:SubSonic框架是一个优秀的.开源的ORM映射框架,同时提供符合自身需要的代码生成器. 官方下载地址:http://subsonicproject.com/Download 明白了SubSo ...