撤回我也能看到!教你用Python制作微信防撤回脚本
作者:克金森沐沐 发布时间:2021-08-05 14:38:30
一、之前解决方案
大概是这样:短时间内同一位好友发送了多条消息,当他随便撤回一条消息时,我们不能确定他到底撤回的到底是哪一条消息。只能猜他可能是撤回了最近的一条消息,然后将其他消息贴出来作为备选。代码如下:
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)
实际效果是这样:
我这个强迫症简直受不了这么不确定的说法。
二、分析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,下面是对比(高亮的部分是不同处,省略了部分相同内容。可以点击放大查看大图
现在来分析几条关键信息:
MsgId(与下面的NewMsgId同)
消息编号。这个很好理解,每条消息都是通过一个独一无二的编号来与其他消息区分,所以这两条消息的编号不同很正常。如果我们能拿到好友撤回消息的编号,也就能锁定这条消息了。
MsgType(与下面的Type同)
消息类型。如下图,左边是普通的对话消息,右边类似于系统提示消息。是不是可以根据这条信息来判断是不是有好友撤回了消息?
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有很多好用好玩的库,可以慢慢发掘。本期我们利用ItChat
库编写了一个微信防撤回脚本。其实ItChat
功能远远不止这些,它还可以处理微信群消息以及各种其他类型的消息,我们讲到的只是九牛一毛,更多的还要大家自己去探索。
来源:https://blog.csdn.net/program_G/article/details/117661591
猜你喜欢
- 之前一直对于python类的继承机制认知的比较混乱,今天学习记录一下。(1)首先使用直接继承的方式class parent():  
- 本文主要分析的是web.py库的application.py这个模块中的代码。总的来说,这个模块主要实现了WSGI兼容的接口,以便应用程序能
- 什么是粘包问题最近在使用Golang编写Socket层,发现有时候接收端会一次读到多个数据包的问题。于是通过查阅资料,发现这个就是传说中的T
- 看到豆瓣上有网友提了这个问题,看到回答的人不多,忍不住写了下面的内容。工作中最常用到的统计方法有哪些?根据我自己的经验给举些例子。1.通过一
- 问题说明最近在写爬虫,由于单个账号访问频率太高会被封,所以需要在爬虫执行一段时间间隔后自己循环切换账号所以就在想,有没有像单片机那样子设置一
- 前言matplotlib.pyplot是一些命令行风格函数的集合,使matplotlib以类似于MATLAB的方式工作。每个pyplot函数
- 1、准备html文件首先我们需要准备一个鼠标滑动的html文件,用来演示鼠标滑动的效果,注意需要将我们的html文件放在自己的服务器上,这样
- 本文实例讲述了JS+CSS实现仿支付宝菜单选中效果代码。分享给大家供大家参考。具体如下:这是一个漂亮的JS+CSS仿支付宝菜单,总体风格和形
- 一 安装oracle数据库成功之后,会显示相关的数据库信息: 全局数据库名:oracle 系统标识符(SID):oracle 服务器参数文件
- 要很好地领会Ajax技术的关键是了解超文本传输协议(HTTP),该协议用来传输网页、图像以及因特网上在浏览器与服务器间传输的其他类型文件。只
- 当我们建好数据库及表后,首先想到的就是向数据库的表中输入数据.下面我们就来探讨一下如何向数据库增加数据:1.常用的方法是insert语句in
- 前言很多时候我们要用到图片上传功能,如果图片一直用放在别的网站上,通过加载网址的方式来显示的话其实也挺麻烦的,我们通过使用 django-f
- 以发布目录为例:<OBJECT ID="agobjOraSession" RUNAT=&quo
- 格式:Download.asp?FileName=要下载的文件名 代码如下:Dim Stream Dim Co
- 这篇文章主要介绍了Pytest mark使用实例及原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要
- 我们知道IE6是不支持透明的PNG的,这无疑限制了网页设计的发挥空间.然而整个互联网上解决这个IE6的透明PNG的方案也是多不胜数,从使用I
- 这里列出了13种实现图片或网页内容 lightbox 效果的方法,大部分是链接到各种lightbox作者的英文页面,里面都有源代码下载。Th
- 1.彻底弄懂CSS盒子模式一(DIV布局快速入门) 2.彻底弄懂CSS盒子模式二(导航栏实例) 3.彻底弄懂CSS盒子模式三(浮动的表演和清
- 1.多选按钮的方法以下为常用的方法:方法描述deselect()清除多选按钮选中选项。flash()在激活状态颜色和正常颜色之间闪烁几次多选
- PyCharm是Python著名的Python集成开发环境(IDE)conda有Miniconda和Anaconda,前者应该是类似最小化版