撤回我也能看到!教你用Python制作微信防撤回脚本


Posted in Python onJune 11, 2021

一、之前解决方案

大概是这样:短时间内同一位好友发送了多条消息,当他随便撤回一条消息时,我们不能确定他到底撤回的到底是哪一条消息。只能猜他可能是撤回了最近的一条消息,然后将其他消息贴出来作为备选。代码如下:

target_msg_pattern = '"{}" 撤回了一条消息'.format(sender_name)
if content == target_msg_pattern:
    return_msg = '【{}】撤回了一条消息:\n'.format(sender_name)
    if len(log[sender_name].items()) == 0:
        return_msg = '缓存信息列表为空!'
    else:
        return_msg += log[sender_name].items()[-1][-1] + '\n'
        if len(log[sender_name].items()) > 1:
            msgs = [msg for timestamp, msg in log[sender_name].items()[:-1]]
            return_msg += '也有可能是下列信息中的某一条:\n' + '\n'.join(msgs)

实际效果是这样:


撤回我也能看到!教你用Python制作微信防撤回脚本 

我这个强迫症简直受不了这么不确定的说法。

二、分析msg信息

要想确定撤回了哪一条信息,就必须先熟悉普通msg和撤回的msg里面都有哪些信息,他们的相同点和不同点。下面就来看看这两种情况下msg都是怎么样的,不需要仔细的看每一行,后面会作具体分析。

先是用机器人“小帮帮”发送过来的信息得到的msg信息:

{
	'MsgId': '2018511155698964390',
	'FromUserName': '@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3',
	'ToUserName': '@**********c2e61fdb47b5c241553a2f',
	'MsgType': 1,
	'Content': 'msg里面到底有什么?',
	'Status': 3,
	'ImgStatus': 1,
	'CreateTime': 1578069291,
	'VoiceLength': 0,
	'PlayLength': 0,
	'FileName': '',
	'FileSize': '',
	'MediaId': '',
	'Url': '',
	'AppMsgType': 0,
	'StatusNotifyCode': 0,
	'StatusNotifyUserName': '',
	'RecommendInfo': {
		'UserName': '',
		'NickName': '',
		'QQNum': 0,
		'Province': '',
		'City': '',
		'Content': '',
		'Signature': '',
		'Alias': '',
		'Scene': 0,
		'VerifyFlag': 0,
		'AttrStatus': 0,
		'Sex': 0,
		'Ticket': '',
		'OpCode': 0
	},
	'ForwardFlag': 0,
	'AppInfo': {
		'AppID': '',
		'Type': 0
	},
	'HasProductId': 0,
	'Ticket': '',
	'ImgHeight': 0,
	'ImgWidth': 0,
	'SubMsgType': 0,
	'NewMsgId': 2018511155698964390,
	'OriContent': '',
	'EncryFileName': '',
	'User': < User: {
		'MemberList': < ContactList: [] > ,
		'Uin': 0,
		'UserName': '@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3',
		'NickName': '小帮帮',
		'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=699837854&username=@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3&skey=@crypt_****c00c_92668c8ba7d285c221a85e**********',
		'ContactFlag': 2049,
		'MemberCount': 0,
		'RemarkName': '小帮帮',
		'HideInputBarFlag': 0,
		'Sex': 2,
		'Signature': '',
		'VerifyFlag': 0,
		'OwnerUin': 0,
		'PYInitial': 'XBB',
		'PYQuanPin': 'xiaobangbang',
		'RemarkPYInitial': 'XBB',
		'RemarkPYQuanPin': 'xiaobangbang',
		'StarFriend': 0,
		'AppAccountFlag': 0,
		'Statues': 0,
		'AttrStatus': 33658937,
		'Province': '浙江',
		'City': '台州',
		'Alias': '',
		'SnsFlag': 17,
		'UniFriend': 0,
		'DisplayName': '',
		'ChatRoomId': 0,
		'KeyWord': '',
		'EncryChatRoomId': '',
		'IsOwner': 0
	} > ,
	'Type': 'Text',
	'Text': 'msg里面到底有什么?'
}

下面是机器人撤回刚才的信息得到的msg信息:

{
	'MsgId': '4056955577161654067',
	'FromUserName': '@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3',
	'ToUserName': '@**********c2e61fdb47b5c241553a2f',
	'MsgType': 10002,
	'Content': '<sysmsg type="revokemsg"><revokemsg><session>wxid_4gngrr04aqjn21</session><oldmsgid>1123721956</oldmsgid><msgid>2018511155698964390</msgid><replacemsg><![CDATA["小帮帮" 撤回了一条消息]]></replacemsg></revokemsg></sysmsg>',
	'Status': 4,
	'ImgStatus': 1,
	'CreateTime': 1578069381,
	'VoiceLength': 0,
	'PlayLength': 0,
	'FileName': '',
	'FileSize': '',
	'MediaId': '',
	'Url': '',
	'AppMsgType': 0,
	'StatusNotifyCode': 0,
	'StatusNotifyUserName': '',
	'RecommendInfo': {
		'UserName': '',
		'NickName': '',
		'QQNum': 0,
		'Province': '',
		'City': '',
		'Content': '',
		'Signature': '',
		'Alias': '',
		'Scene': 0,
		'VerifyFlag': 0,
		'AttrStatus': 0,
		'Sex': 0,
		'Ticket': '',
		'OpCode': 0
	},
	'ForwardFlag': 0,
	'AppInfo': {
		'AppID': '',
		'Type': 0
	},
	'HasProductId': 0,
	'Ticket': '',
	'ImgHeight': 0,
	'ImgWidth': 0,
	'SubMsgType': 0,
	'NewMsgId': 4056955577161654067,
	'OriContent': '',
	'EncryFileName': '',
	'User': < User: {
		'MemberList': < ContactList: [] > ,
		'Uin': 0,
		'UserName': '@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3',
		'NickName': '小帮帮',
		'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=699837854&username=@**********f511363f8200853d724137bb31236a7ea81e5183cc06cb4ec978e3&skey=@crypt_****c00c_92668c8ba7d285c221a85e**********',
		'ContactFlag': 2049,
		'MemberCount': 0,
		'RemarkName': '小帮帮',
		'HideInputBarFlag': 0,
		'Sex': 2,
		'Signature': '',
		'VerifyFlag': 0,
		'OwnerUin': 0,
		'PYInitial': 'XBB',
		'PYQuanPin': 'xiaobangbang',
		'RemarkPYInitial': 'XBB',
		'RemarkPYQuanPin': 'xiaobangbang',
		'StarFriend': 0,
		'AppAccountFlag': 0,
		'Statues': 0,
		'AttrStatus': 33658937,
		'Province': '浙江',
		'City': '台州',
		'Alias': '',
		'SnsFlag': 17,
		'UniFriend': 0,
		'DisplayName': '',
		'ChatRoomId': 0,
		'KeyWord': '',
		'EncryChatRoomId': '',
		'IsOwner': 0
	} > ,
	'Type': 'Note',
	'Text': '"小帮帮" 撤回了一条消息'
}

得到了两种类型的msg,下面是对比(高亮的部分是不同处,省略了部分相同内容。可以点击放大查看大图

撤回我也能看到!教你用Python制作微信防撤回脚本

现在来分析几条关键信息:

  • MsgId(与下面的NewMsgId同)
  • 消息编号。这个很好理解,每条消息都是通过一个独一无二的编号来与其他消息区分,所以这两条消息的编号不同很正常。如果我们能拿到好友撤回消息的编号,也就能锁定这条消息了。
  • MsgType(与下面的Type同)
  • 消息类型。如下图,左边是普通的对话消息,右边类似于系统提示消息。是不是可以根据这条信息来判断是不是有好友撤回了消息?

撤回我也能看到!教你用Python制作微信防撤回脚本

Content

消息内容,注意与下面的Text区分,这两种消息类型在内容上最大的区别可能就在这里了。

来看一下撤回消息的Content是怎么样的(为了便于查看,已经经过格式化)

<sysmsg type="revokemsg">
    <revokemsg>
        <session>wxid_4gngrr04aqjn21</session>
        <oldmsgid>1123721956</oldmsgid>
        <msgid>2018511155698964390</msgid>
        <replacemsg><![CDATA["小帮帮" 撤回了一条消息]]></replacemsg>
    </revokemsg>
</sysmsg>

一眼就能发现关键点:撤回的那条消息属于系统消息(sysmsg),类型是撤回消息(revokemsg),对应的消息编号是2018511155698964390

细心的读者已经发现,这个消息编号正好就是左边那条消息的编号。

通过这个推理,猜测Content字段是系统内部传输的内容,而Text字段则是用户看到的内容。

三、确定消息类型

根据上述分析,有三个地方帮助确定收到的某条信息是否是撤回的消息:

1.MsgType

1就是普通消息,是10002则可能为撤回消息。

2.Content

如果Content里有包含type="revokemsg"则可能为撤回消息,否则不是撤回消息。

3.Type

是Text就是普通消息,是Note则可能为撤回消息。

精确起见,消息还要同时满足上面三种情况才可认定为撤回消息。

四、锁定撤回的消息

由于要锁定撤回消息必须要MsgId才能确定,所以在存储临时消息时需要加上这一字段。

log[sender_name][cur_timestamp] = msg['MsgId'] + '|||' + content

为了简化数据复杂度,我通过分隔符|||直接把MsgId加在前面。

于是,锁定并发送撤回消息的代码就时这样:

content = str(msg['Text'])
revoke_info = msg['Content']
print('{}, {} 发来消息: {}'.format(formatted_timestamp, sender_name, content))
target_msg_pattern = '"{}" 撤回了一条消息'.format(sender_name)
if target_msg_pattern == content and msg['Type'] == 'Note' and str(msg['MsgType']) == '10002' and 'type="revokemsg"' in revoke_info:
    return_msg = ''
    return_msg_head = '{},【{}】撤回了一条消息:\n'.format(formatted_timestamp, sender_name)
    revoke_msg_id = revoke_info.split('<msgid>')[-1].split('</msgid>')[0]
    for _, value in log[sender_name].items():
        if value.split('|||')[0] == revoke_msg_id:
            return_msg = value.split('|||')[1]
    if return_msg == '':
        return_msg = '缓存信息列表为空!'
    return_msg = return_msg_head + return_msg
    print(return_msg)
    itchat.send_msg(return_msg, 'filehelper')

测试一下,为便于查看,将撤回提醒直接发给机器人“小帮帮”

撤回我也能看到!教你用Python制作微信防撤回脚本 

一个完美的微信防撤回脚本大功告成!

五、结语

Python有很多好用好玩的库,可以慢慢发掘。本期我们利用ItChat库编写了一个微信防撤回脚本。其实ItChat功能远远不止这些,它还可以处理微信群消息以及各种其他类型的消息,我们讲到的只是九牛一毛,更多的还要大家自己去探索。

到此这篇关于撤回我也能看到!教你用Python制作微信防撤回脚本的文章就介绍到这了,更多相关Python微信防撤回脚本内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python多重继承新算法C3介绍
Sep 28 Python
pandas修改DataFrame列名的方法
Apr 08 Python
Python使用到第三方库PyMuPDF图片与pdf相互转换
May 03 Python
Python_查看sqlite3表结构,查询语句的示例代码
Jul 17 Python
python中的列表与元组的使用
Aug 08 Python
Django接收自定义http header过程详解
Aug 23 Python
Django自关联实现多级联动查询实例
May 19 Python
Elasticsearch py客户端库安装及使用方法解析
Sep 14 Python
python调用jenkinsAPI构建jenkins,并传递参数的示例
Dec 09 Python
python实现经纬度采样的示例代码
Dec 10 Python
Django Paginator分页器的使用示例
Jun 23 Python
Flask使用SQLAlchemy实现持久化数据
Jul 16 Python
用Python创建简易网站图文教程
python+opencv实现视频抽帧示例代码
用Python将GIF动图分解成多张静态图片
OpenCV-Python 实现两张图片自动拼接成全景图
matplotlib如何设置坐标轴刻度的个数及标签的方法总结
PyQt5结合QtDesigner实现文本框读写操作
Python中seaborn库之countplot的数据可视化使用
You might like
php中的登陆login
2007/01/18 PHP
php中opendir函数用法实例
2014/11/15 PHP
php通过递归方式复制目录和子目录的方法
2015/03/13 PHP
php链式操作的实现方式分析
2019/08/12 PHP
javascript new 需不需要继续使用
2009/07/02 Javascript
JavaScript CSS修改学习第六章 拖拽
2010/02/19 Javascript
js整数字符串转换为金额类型数据(示例代码)
2013/12/26 Javascript
单元选择合并变色示例代码
2014/05/26 Javascript
jQuery+HTML5实现手机摇一摇换衣特效
2015/06/05 Javascript
jQuery采用连缀写法实现的折叠菜单效果
2015/09/18 Javascript
如何提高javascript加载速度
2016/12/26 Javascript
ejsExcel模板在Vue.js项目中的实际运用
2018/01/27 Javascript
layui实现文件或图片上传记录
2018/08/28 Javascript
在Node.js下运用MQTT协议实现即时通讯及离线推送的方法
2019/01/24 Javascript
vue按需加载实例详解
2019/09/06 Javascript
Bootstrap实现前端登录页面带验证码功能完整示例
2020/03/26 Javascript
Vue-resource安装过程及使用方法解析
2020/07/21 Javascript
JavaScript常用8种数组去重代码实例
2020/09/09 Javascript
python批量生成本地ip地址的方法
2015/03/23 Python
Python算法输出1-9数组形成的结果为100的所有运算式
2017/11/03 Python
python selenium 对浏览器标签页进行关闭和切换的方法
2018/05/21 Python
Python中的元组介绍
2019/01/28 Python
numpy.random模块用法总结
2019/05/27 Python
学习Django知识点分享
2019/09/11 Python
解决django model修改添加字段报错的问题
2019/11/18 Python
django有外键关系的两张表如何相互查找
2020/02/10 Python
CSS3 优势以及网页设计师如何使用CSS3技术
2009/07/29 HTML / CSS
公积金转移接收函
2014/01/11 职场文书
教师党员公开承诺书
2014/03/25 职场文书
大学第二课堂活动总结
2014/07/08 职场文书
2015年平安创建工作总结
2015/04/29 职场文书
2016年暑期见闻作文
2015/11/25 职场文书
redis配置文件中常用配置详解
2021/04/14 Redis
python 爬取京东指定商品评论并进行情感分析
2021/05/27 Python
MySql子查询IN的执行和优化的实现
2021/08/02 MySQL
Win11 Dev 预览版25174.1000发布 (附更新修复内容汇总)
2022/08/05 数码科技