听说用python来批量删除说说也挺快乐的呢~
先睹为快
在终端运行如下命令即可:
python clearQzone.py (--manual)
如果加了--manual选项,意思就是每条说说删除前你都要先人工确认一下是否真的需要删除它,否则就是直接把所有说说都删了。
效果如下(借的别人不用的小号测试的,不是我的QQ号T_T):
批量删除说说https://www.zhihu.com/video/1248312837506195456
导语
接昨天的那篇文章:
带大家用python来享受一下批量删除微博的快感呗~
看到有小伙伴留言说批量删除说说也挺让人快乐的,顿时明白了ta的意思。干脆趁热打铁,再来一期用python批量删除QQ空间说说的教程吧。
废话不多说,让我们愉快地开始吧~
相关文件
https://github.com/CharlesPikachu/DecryptLogin
开发工具
Python版本:3.6.4
相关模块:
DecryptLogin模块;
argparse模块;
以及一些python自带的模块。
环境搭建
安装Python并添加到环境变量,pip安装需要的相关模块即可。
原理简介
和之前类似,还是先利用我们开源的DecryptLogin包实现一波QQ空间的模拟登录操作:
from DecryptLogin import login
@staticmethod
def login():
lg = login.Login()
infos_return, session = lg.QQZone()
return session
然后,我们去QQ空间抓一波包,即进入QQ空间之后按F12打开开发者工具,再点击一下说说按钮,可以发现如下链接:
即:
https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6?
它可以返回说说页首页的说说数据。简单分析一下这个链接需要携带的参数有哪些:
1. 易知参数
uin: 用户的QQ号
ftype: 可以始终为'0'
sort: 可以始终为'0'
pos: 可以始终为'0'
num: 可以始终为'20'
replynum: 可以始终为'100'
callback: 可以始终为'_preloadCallback'
code_version: 可以始终为'1'
format: 可以始终为'jsonp'
need_private_comment: 可以始终为'1'
2. 不易知参数
g_tk
qzonetoken
其中g_tk我们在以前的文章里说过应该怎么算:
模拟登录系列 | QQ空间模拟登录
即找到对应的js代码:
然后转成py的就行了:
'''计算g_tk'''
def __calcGtk(self, string):
e = 5381
for c in string:
e += (e << 5) + ord(c)
return 2147483647 & e
而参数qzonetoken,我们也可以找到对应的js代码:
原来它可以是一个固定值。写个简单的程序测试一下:
'''获得首页的说说数据'''
def __getAllTwitters(self):
url = 'https://user.qzone.qq.com/proxy/domain/taotao.qq.com/cgi-bin/emotion_cgi_msglist_v6?'
params = {
'uin': self.uin,
'ftype': '0',
'sort': '0',
'pos': '0',
'num': '20',
'replynum': '100',
'g_tk': self.g_tk,
'callback': '_preloadCallback',
'code_version': '1',
'format': 'jsonp',
'need_private_comment': '1',
'qzonetoken': '12a2df7fc3ce126e67c62b0577cdea5133e79e77f46ae920b2a8b822ac867e54416698be9ee883f09e'
}
response = self.session.get(url, params=params)
response_json = response.content.decode('utf-8').replace('_preloadCallback(', '')[:-2]
response_json = json.loads(response_json)
msglist = response_json['msglist']
if msglist is None:
msglist = []
all_twitters = {}
for item in msglist:
tid = item['tid']
created_time = item['created_time']
content = item['content']
all_twitters[tid] = [created_time, content]
return all_twitters
可以发现返回的数据如下:
和我们首页的数据是对上的:
看来我们前面的分析是完全正确的。现在,我们只需要再抓包看看删除说说需要请求哪个接口就ok啦(自己手动删除一条说说就能抓到这个接口了,很简单的):
需要携带的参数如下:
hostuin: 用户的QQ号
tid: 说说的id
t1_source: 固定值'1'
code_version: 固定值'1'
format: 固定值'fs'
qzreferrer: 格式为'https://user.qzone.qq.com/{用户QQ号}/infocenter'
于是,我们现在就可以愉快地开始写代码啦:
'''外部调用'''
def run(self):
url = 'https://user.qzone.qq.com/proxy/domain/taotao.qzone.qq.com/cgi-bin/emotion_cgi_delete_v6?'
del_count = 0
total_count = 0
while True:
all_twitters = self.__getAllTwitters()
if not all_twitters:
break
for key, value in all_twitters.items():
total_count += 1
print('[INFO]: 正在处理第%s条说说, 已成功删除%s条说说...' % (total_count, del_count))
if self.is_manual:
print('说说时间: %s, 说说内容: %s...' % (str(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(value[0]))), value[1]))
user_input = input('是否需要删除该条说说(yes/no): ')
if user_input.lower() == 'n' or user_input.lower() == 'no':
continue
data = {
'hostuin': self.uin,
'tid': key,
't1_source': '1',
'code_version': '1',
'format': 'fs',
'qzreferrer': f'https://user.qzone.qq.com/{self.uin}/infocenter'
}
params = {
'qzonetoken': self.qzonetoken,
'g_tk': self.g_tk
}
try:
response = self.session.post(url, data=data, params=params)
del_count += 1
time.sleep(random.randrange(1, 3)+random.random())
except:
pass
time.sleep(random.randrange(3, 6)+random.random())
print('[INFO]: 程序运行完毕, 共检测到您的账户一共有%s条说说, 其中%s条已被成功删除...' % (total_count, del_count))
基本的原理和之前批量删除微博那个代码一样,只不过加了个是否需要手动确认之后再删除的选项。
大功告成,完整源代码详见相关文件~