要说微信最让人恶心的发明,消息撤回绝对能上榜。

比如你现在正和女朋友用微信聊着天,或者跟自己喜欢的女孩子聊着天,一个不留神,你没注意到对方发的消息就被她及时撤回了,这时你很好奇,好奇她到底发了什么?于是你打算问问她发了什么,结果她回一句"没什么"。这一回复,让你的好奇心更加强烈了,顿时就感觉消息撤回这一功能就是用来折磨人的。

那么有没有什么办法能够知道你心爱的她(他)到底撤回了什么呢?不要着急,Python帮你搞定。

模块介绍

本篇文章将用Python实现微信的防撤回功能,针对微信操作,Python有一个十分强大的库:itchat。相信没有使用过也有所耳闻吧。官方是这样描述它的:

Project description
itchat is a open souce wechat api project for personal account.It enables you to access your personal wechat account through command line.

翻译过来就是:itchat是一个针对个人帐户的开放式微信api项目,它使您可以通过命令行访问您的个人微信帐户。

既然是针对微信的开发,我们就离不开这个模块的协助,所以,首先下载该模块:

pip install itchat

也可以在开发工具Pycharm中直接导入该模块,Pycharm会提示你下载。

模块初体验

考虑到应该有些人从来没有使用过该模块,这里对该模块进行一个简单的入门。

1、如何登陆微信

既然要操作微信,那么摆在我们面前的问题就是如何登录微信,登录微信非常简单,直接看代码:

import itchatitchat.login()

没错,一句代码即可完成登录,运行之后就会弹出一个二维码,扫描之后在手机上授权登录,控制台就会提示是否登录成功。

Login successfully as Y

这样就说明登录成功了。

这里需要注意一个问题,就是你会发现每次运行程序都要扫描二维码登录,这样未免太麻烦,有没有办法只扫描一次,以后就自动登录了呢?这当然是可以的。

import itchatitchat.auto_login(hotReload=True)

通过函数名也能知道该方法可以实现自动登录,运行程序,扫码登录之后会在项目路径下创建一个itchat.pkl文件,该文件用于存储登录的状态,所以千万不要动它,如果你想换一个微信账号登录,就要先把这个文件删除,因为该文件记录的是上一个微信的状态,删除之后即可登录。

需要注意:这种方式只能保证你在短时间内无需重复登录,时间长了,还是需要重新扫码登录的。

进行到这里,有些人可能会发现自己的微信登录不上的情况,据我所知,有些新注册的微信和长期不使用的微信是无法登录网页版微信的,所以这里也会导致登录不上。如果登录不上,那也是没有办法的,下面的内容也就没有意义了。

2、获取好友列表

登录上微信之后,我们来用一用itchat模块提供的一些api,比如获取好友列表。

import itchatitchat.auto_login(hotReload=True)
friends = itchat.get_friends()  # 好友列表
print(friends)

使用get_friends()函数即可获取到好友列表的所有好友信息,包括昵称、备注名、地址、个性签名、性别等等。

这里我随意地复制了一个好友的个人信息,当然由于隐私问题,这里的部分信息我用"*"号代替了,我们重点是分析一下这些信息的内容。比如最开始的UserName,这是用户的唯一标识,相当于身份证号码,你的每个好友都会有这样一个标识,每个好友之间肯定都是不一样的;然后是NickName,这是好友的昵称;HeadImgUrl是好友的头像地址;RemarkName是你对好友的备注名;Province是省份等等,这里就不一一介绍了,感兴趣的话可以自己去了解一下。

3、如何发送消息给好友

如何发送一条消息给指定的好友呢?也非常简单:

import itchatitchat.auto_login(hotReload=True)
itchat.send('Hello World', toUserName='@f9e42aafa1175b38b60a0be4d651a34c77f2528d9b7784e7aaf415090eca8fa6')

此时的UserName就派上用场了,也就是好友的唯一标识,这样,我们就给该标识对应的好友发送了一条消息,所以,我们可以这样改进程序:

import itchatitchat.auto_login(hotReload=True)
friends = itchat.get_friends()
nickName = '诚信通授权渠道商-老曾'
for i in friends:if '诚信通授权渠道商-老曾' == i['NickName']:itchat.send('Hello World', toUserName=i['UserName'])break

这样,就可以指定发送给任意好友,通过好友的昵称在好友列表中进行检索,找到的话,就获取该好友的UserName,然后发送消息,也可以通过对好友的备注名(RemarkName)查找,大家可以自己尝试。

4、装饰器

关于itchat模块还有很多功能,这里就不作过多讲解了,我们只讲关于这次程序的知识点,这里是最后一个内容,装饰器。

关于装饰器,一时半会还讲不清楚,这里只是简单介绍一下,装饰器的作用就是用于拓展原来函数功能的一种函数,目的是在不改变原函数名(或类名)的情况下,给函数增加新的功能。

例如现在有一个函数fun(),你并不知晓函数的实现原理,你肯定也不能去修改这个函数的代码,而你需要给该函数添加一个输出开始运行时间和结束运行时间的功能,该如何实现呢?这个时候就可以使用装饰器。

import timedef show_time(fun):def inner():print(time.time())fun()print(time.time())return inner   @show_time
def fun():passfun()

该如何理解这段程序呢?首先@show_time即是使用一个装饰器show_time,此时会将装饰的函数,也就是fun()作为参数传递给装饰器show_time(),我们知道函数作为返回值的话,执行的其实是该函数,所以程序会执行内部函数inner(),此时输出开始运行时间,然后调用fun()函数(原有的功能不能丢),最后输出结束运行时间。这样就通过装饰器实现了一个函数的功能扩展,这也是典型的面向切面编程思想。

如何获取好友发送的消息

准备工作做完了,接下来就进入正题了,对于上面的知识点,大家一定要掌握,如果不懂的话,接下来的代码你可能会很懵。

首先,我们看看该如何获取到好友发送的消息。

import itchatitchat.auto_login(hotReload=True)@itchat.msg_register(itchat.content.TEXT)
def resever_info(msg):print(msg)itchat.run() #保持运行

itchat模块提供了@itchat.msg_register装饰器来监听消息,比如这里我们自定义了一个resever_info()函数,并用装饰器对消息进行监听,装饰器中传入了itchat.content.TEXT类型,这样监听的就是文本消息,监听到输入之后,装饰器就会将文本消息传入resever_info()的参数中。所以,msg就是监听到的消息内容。

对于@itchat.msg_register装饰器,它不仅可以监听文本,还可以监听语音、图片、地图、名片、视频等等,为了方便,这里我们导入itchat模块下的content模块中的全部内容,因为这些消息类型都是在该模块下声明的。

TEXT       = 'Text'
MAP        = 'Map'
CARD       = 'Card'
NOTE       = 'Note'
SHARING    = 'Sharing'
PICTURE    = 'Picture'
RECORDING  = VOICE = 'Recording'
ATTACHMENT = 'Attachment'
VIDEO      = 'Video'
FRIENDS    = 'Friends'
SYSTEM     = 'System'INCOME_MSG = [TEXT, MAP, CARD, NOTE, SHARING, PICTURE,RECORDING, VOICE, ATTACHMENT, VIDEO, FRIENDS, SYSTEM]

还有要注意的地方,最后记得调用itchat的run()函数,保持程序运行,否则程序就直接结束了。

接下来我们就可以测试一下了,我让我的好友发了一条消息给我,控制台就输出了如下内容:

内容很多,我们只挑重要的看。例如FromUserName,这是发送者的标识;ToUserName,这是接收者的标识;Content,这当然就是文本内容了;CreateTime,这是发送时间;注意最后的两个值:Type,这是消息类型,这里是文本类型Text,然后Text也是文本内容,所以如果想取出好友发送的消息内容的话,用Content和Text都可以。分析过后,取出内容就很简单了:

import itchat
import time
from itchat.content import *  # 导入itchat下的content模块itchat.auto_login(hotReload=True)@itchat.msg_register(TEXT)
def resever_info(msg):info = msg['Text']  # 取出文本消息info_type = msg['Type']  # 取出消息类型fromUser = itchat.search_friends(userName=msg['FromUserName'])['NickName']ticks = msg['CreateTime']  # 获取信息发送的时间time_local = time.localtime(ticks)dt = time.strftime("%Y-%m-%d %H:%M:%S", time_local)  # 格式化日期print("发送人:" + fromUser + '\n消息类型:' + info_type + '\n发送时间:' + dt + '\n消息内容:' + info)itchat.run()

这里用到了time模块,用于格式化日期。

为了测试方便,我就自己发了一条消息给别人,自己发的消息也是会被监听的,看运行结果:

发送人:Y
消息类型:Text
发送时间:2019-11-28 16:19:13
消息内容:土鳖

再来试试语音和图片能获取到吗?我们回到刚才的代码:

import itchat
from itchat.content import *  # 导入itchat下的content模块itchat.auto_login(hotReload=True)@itchat.msg_register(TEXT)
def resever_info(msg):print(msg)itchat.run()

运行之后,发送语音和图片试试,不管怎么发,控制台就是没反应,这是当然的了,我们还没对语音和图片进行监听呢,修改代码:

import itchat
from itchat.content import *  # 导入itchat下的content模块itchat.auto_login(hotReload=True)@itchat.msg_register([TEXT, PICTURE, RECORDING])  #添加了对图片和语音的监听
def resever_info(msg):print(msg)itchat.run()

再运行试试,先发送一张图片,再发送一段语音,控制台输出了两段内容,由于篇幅过长,就不贴出来了,无非还是那些信息,发送者,接收者,日期,消息内容等等,这里只需注意图片和语音的内容:

'Type': 'Picture', 'Text': <function get_download_fn.<locals>.download_fn at 0x0000000003574158>
'Type': 'Recording', 'Text': <function get_download_fn.<locals>.download_fn at 0x0000000002CFED08>

这是一段地址,通过它我们就能够将图片和语音保存起来。

如何保存好友发送的图片和语音

下面我们对好友发送的图片和语音进行保存。

import itchat
import os
from itchat.content import *  # 导入itchat下的content模块itchat.auto_login(hotReload=True)
temp = 'C:/Users/Administrator/Desktop/CrawlerDemo' + '/' + '撤回的消息'
# 如果不存在该文件夹,就创建
if not os.path.exists(temp):os.mkdir(temp)@itchat.msg_register([TEXT, PICTURE, RECORDING])
def resever_info(msg):info = msg['Text']  # 取出文本消息info_type = msg['Type']  # 取出消息类型name = msg['FileName']  # 取出语音(图片)文件名if info_type == 'Recording':# 保存语音info(temp + '/' + name)elif info_type == 'Picture':# 保存图片info(temp + '/' + name)itchat.run()

运行起来,然后发送一张图片和一条语音,就会在指定目录下生成两个文件:

如何监听好友撤回了消息

到这里,我们其实已经完成了消息监听,只需要稍加修改即可,但是这个程序是有缺陷的,因为不是所有消息我们都需要去保存的,好友正常发送过来的消息我们直接就能看到,保存下来不是多此一举吗?我们的目的是想知道好友撤回了什么内容,这就涉及到如何监听好友是否撤回了消息这一问题了。其实也非常简单,Content模块为我们提供了NOTE类型,该类型指的是系统消息。

所以我们可以自定义一个函数用来监听系统消息:

import itchat
from itchat.content import *  # 导入itchat下的content模块itchat.auto_login(hotReload=True)@itchat.msg_register(NOTE)
def note_info(msg): # 监听系统消息print(msg)itchat.run()

运行程序,我们撤回一条消息测试一下,输出结果如下:

......
'DisplayName': '', 'ChatRoomId': 0, 'KeyWord': '', 'EncryChatRoomId': '', 'IsOwner': 0}>, 'Type': 'Note', 'Text': '你撤回了一条消息'}
......

这里截取了部分内容,会发现,撤回消息的文本内容为"你撤回了一条消息",所以要想知道好友是否撤回了消息就非常简单了,判断msg['Text'] == '你撤回了一条消息'即可。

实现微信防撤回程序

关于程序每个步骤的代码到这里就分析完了,接下来是对所有代码的汇总,也是整个程序的完整代码:

import itchat
from itchat.content import *
import os
import time
import xml.dom.minidom  # 解析xml模块# 这是保存撤回消息的文件目录(如:图片、语音等),这里已经写死了,大家可以自行修改
temp = 'C:/Users/Administrator/Desktop/CrawlerDemo' + '/' + '撤回的消息'
if not os.path.exists(temp):os.mkdir(temp)itchat.auto_login(True)   # 自动登录dict = {}    # 定义一个字典# 这是一个装饰器,给下面的函数添加新功能
# 能够捕获好友发送的消息,并传递给函数参数msg
@itchat.msg_register([TEXT, PICTURE, FRIENDS, CARD, MAP, SHARING, RECORDING, ATTACHMENT, VIDEO])  # 文本,语音,图片
def resever_info(msg):global dict   # 声明全局变量info = msg['Text']  # 取出消息内容msgId = msg['MsgId']  # 取出消息标识info_type = msg['Type']  # 取出消息类型name = msg['FileName']  # 取出消息文件名# 取出消息发送者标识并从好友列表中检索fromUser = itchat.search_friends(userName=msg['FromUserName'])['NickName']ticks = msg['CreateTime']  # 获取信息发送的时间time_local = time.localtime(ticks)dt = time.strftime("%Y-%m-%d %H:%M:%S", time_local)  # 格式化日期# 将消息标识和消息内容添加到字典# 每一条消息的唯一标识作为键,消息的具体信息作为值,也是一个字典dict[msgId] = {"info": info, "info_type": info_type, "name": name, "fromUser": fromUser, "dt": dt}@itchat.msg_register(NOTE)  # 监听系统提示
def note_info(msg):# 监听到好友撤回了一条消息if '撤回了一条消息' in msg['Text']:# 获取系统消息中的Content结点值content = msg['Content']# Content值为xml,解析xmldoc = xml.dom.minidom.parseString(content)# 取出msgid标签的值result = doc.getElementsByTagName("msgid")# 该msgId就是撤回的消息标识,通过它可以在字典中找到撤回的消息信息msgId = result[0].childNodes[0].nodeValue# 从字典中取出对应消息标识的消息类型msg_type = dict[msgId]['info_type']if msg_type == 'Recording':   # 撤回的消息为语音recording_info = dict[msgId]['info']  # 取出消息标识对应的消息内容info_name = dict[msgId]['name'] # 取出消息文件名fromUser = dict[msgId]['fromUser'] # 取出发送者dt = dict[msgId]['dt'] # 取出发送时间recording_info(temp + '/' + info_name) # 保存语音# 拼接提示消息send_msg = '【发送人:】' + fromUser + '\n' + '发送时间:' + dt + '\n' + '撤回了一条语音'itchat.send(send_msg, 'filehelper') # 将提示消息发送给文件助手# 发送保存的语音itchat.send_file(temp + '/' + info_name, 'filehelper')del dict[msgId] # 删除字典中对应的消息print("保存语音")elif msg_type == 'Text':text_info = dict[msgId]['info'] # 取出消息标识对应的消息内容fromUser = dict[msgId]['fromUser'] # 取出发送者dt = dict[msgId]['dt'] # 取出发送时间# 拼接提示消息send_msg = '【发送人:】' + fromUser + '\n' + '发送时间:' + dt + '\n' + '撤回内容:' + text_info# 将提示消息发送给文件助手itchat.send(send_msg, 'filehelper')del dict[msgId] # 删除字典中对应的消息print("保存文本")elif msg_type == 'Picture':picture_info = dict[msgId]['info'] # 取出消息标识对应的消息内容fromUser = dict[msgId]['fromUser'] # 取出发送者dt = dict[msgId]['dt'] # 取出发送时间info_name = dict[msgId]['name'] # 取出文件名picture_info(temp + '/' + info_name) # 保存图片# 拼接提示消息send_msg = '【发送人:】' + fromUser + '\n' + '发送时间:' + dt + '\n' + '撤回了一张图片'itchat.send(send_msg, 'filehelper') # 将图片发送给文件助手# 发送保存的语音itchat.send_file(temp + '/' + info_name, 'filehelper')del dict[msgId] # 删除字典中对应的消息 print("保存图片")itchat.run()

这样,一个完整的防撤回程序就完成了,如果你对于前面的铺垫能够掌握得很好的话,这个程序对你来说就是小菜一碟,每一句代码的注释我都有写,应该很容易看懂。

测试程序

到了激动人心的测试环节,我们来测试一下这个程序是否编写成功了。

我向我的好友发送了三条消息,分别是文本、图片和语音,接着我一一撤回,然后,微信程序就自动向文件传输助手发送了三条消息:

到这里,这个程序就基本完成了。你们在测试的时候也可以叫自己的好友、同学发给你几条消息,然后撤回看看是否能够成功获取到撤回的消息。

撤回的消息发给别人肯定不行,这样不仅泄露了隐私,也会骚扰到别人,所以这里我选择将撤回的消息发送给文件传输助手,如何将消息发送给文件传输助手也很简单:

itchat.send(send_msg, toUserName='filehelper')

toUserName传入filehelper即可,这样,如果对方撤回了消息,你就可以前往文件传输助手查看对方究竟撤回了什么。

说说我遇到的一些坑

这个程序说它难,其实并不难,但我也在编写的过程中遇到了一些坑,一开始我是一条消息一条消息地进行测试,发现程序是正常的,但我连续撤回几条消息,却发现程序出现了Bug。比如我一开始发送了一张图片和一段文字,结果我撤回这两条消息后,得到的却是两段文字。后面我才醒悟过来,是后面的消息覆盖了前面的消息,导致了这个结果,所以在程序中,我定义了一个字典,用于存放好友输入的消息,当监听到消息被撤回时,就通过撤回消息产生的内容中的msgId去和字典中的匹配,匹配到的就是被撤回的消息,然后进行操作即可。

使用教程

想使用该程序非常简单,实现微信防撤回程序节点下有程序的完整代码,直接复制粘贴到你自己的python文件,然后运行该文件即可,运行后会产生一个二维码,用手机验证登录即可。
当然,你也可以选择将该程序打包成可执行的exe文件,这样运行更加方便,打包方式:
首先打开cmd窗口,下载pyinstaller模块,有的话就不用下载了,下载指令:pip insall pyinstaller,此时我们通过cmd窗口进入到python文件目录,比如我这里

那就进入到该目录下:

然后执行下面这条指令:

pyinstaller -F wechat.py

后面是需要打包的文件名,执行命令后,就会在文件同级目录下生成一个dist文件夹。

进入该文件夹,就看到我们的.exe文件了,然后双击执行即可。

最后

这个程序目前只实现了监听好友的文本、图片、语音类型的消息,对于其它类型的消息,还有群聊的消息都是无法监听到的,感兴趣的话大家可以自己试着实现一下。

因为自己也是刚刚接触这个模块,文中的程序可能会出现一些意想不到的Bug,但目前我测试来看是没有问题的,如有问题,欢迎评论区留言。

想查看微信好友撤回的消息?Python帮你搞定相关推荐

  1. python查看微信撤回消息_想查看微信好友撤回的消息?Python帮你搞定

    要说微信最让人恶心的发明,消息撤回绝对能上榜. 比如你现在正和女朋友用微信聊着天,或者跟自己喜欢的女孩子聊着天,一个不留神,你没注意到对方发的消息就被她及时撤回了,这时你很好奇,好奇她到底发了什么?于 ...

  2. 利用Python查看微信好友撤回的消息

    效果图如下: 不仅可以查看微信好友撤回的文字消息,如位置.视频.音频.图片等等都可以查看. 直接上源代码: # Python查看微信撤回消息 import re import os import ti ...

  3. 如何用Python查看微信好友撤回的消息?

    首先声明,本文主要就是在试图复现这篇文档中所说的: https://cloud.tencent.com/developer/article/1701130 因此要是下文中有什么讲的不清楚的地方,大家也 ...

  4. 想知道微信对方撤回的消息是什么吗?快看这里

    欢迎来使用WeChatPlugin微信小助手mac版,其功能非常多,包括自动回复.消息防撤回.远程控制.微信多开.登录免认证.会话多选删除等.如果你需要一个可以让你的微信客户端更强大的插件,可以试试这 ...

  5. 情人眼里出西施,我用Python帮你搞定了!

    情人节就要到了,不知道大家都准备了什么礼物呢?情人之间送礼,追求的是心意,今天小编就带领大家做一个程序员情人节专属礼物-<我的眼里只有你>,如下如所示: 图片来源:全民小视频 大家仔细观察 ...

  6. 数据分析?小意思!python帮你搞定

    前言 如果大家经常阅读Python爬虫相关的公众号,都会是以爬虫+数据分析的形式展现的,这样很有趣,图表也很不错,今天了,我就来分享上一次在培训中的一个作品:猫眼电影爬虫及分析. 通过猫眼电影TOP1 ...

  7. 撤回的消息服务器上查的出来吗,想查看对方已撤回的微信消息?就用这一招!...

    原标题:想查看对方已撤回的微信消息?就用这一招! 不知道大家有没有这样的感觉, 有时候你在给朋友发微信时, 对方可能趁你不注意发了消息然后撤回了- 比如↓↓↓ 好想知道女神跟我说了什么~ 是同意了? ...

  8. 你了解微信好友多少?用Python可以更清楚

    运行平台: Windows Python版本: Python3.6   IDE: Sublime Text 1.准备工作 1.1 库介绍 只有登录微信才能获取到微信好友的信息,本文采用 wxpy 该第 ...

  9. python降低图片分辨率_手把手:扫描图片又大又不清晰?这个Python小程序帮你搞定!...

    原标题:手把手:扫描图片又大又不清晰?这个Python小程序帮你搞定! 大数据文摘作品 编译:HAPPEN.于乐源.小鱼 一位乐于分享学生精彩笔记的大学教授对于扫描版的文件非常不满意--颜色不清晰并且 ...

  10. python从视频中提取音频_提取视频中的音频——python三行程序搞定!

    原标题:提取视频中的音频--python三行程序搞定! 写在开头 身处数据爆炸增长的时代,各种各样的数据都飞速增长,视频数据也不例外.我们可以使用 python 来提取视频中的音频,而这仅仅需要安装一 ...

最新文章

  1. (转)新开发Apple Store上软件的实施步骤
  2. linux 终端管理工具,linux服务器-远程管理-screen:强大的终端管理工具
  3. 五邑大学数据结构邢润丹实验_哪个大学楼最高:全国大学高楼海拔高度排名
  4. java 0b,java 1.6.0_38-b05 vm 20.13-b02优化手记
  5. 服务拆分-案例Demo
  6. An example of EXPORT / IMPORT usage - in office integration and odata metadata model cache
  7. IPC-----消息队列
  8. javascript设计模式-Constructor(构造器)模式
  9. 玩转Heartbeat,快速实现高可用性集群
  10. 「leetcode」234. 回文链表:【数组模拟】【翻转后半部分】详解
  11. Symbian操作系统
  12. c语言二进制转十六进制代码,C语言--二进制转十六进制
  13. 奇幻RPG(人物构建 与 Abstract Factory模式)
  14. 3dmax建模如何设置凹凸贴图
  15. 浅析嵌入式开发中的RAM和ROM
  16. Unable to find image ‘XXX‘ locally docker: Error response from daemon: pull access denied for
  17. 2020-10-20 Ant Design Vue 关闭国际化设置默认语言为中文的
  18. 【Unity连载】斗兽棋-棋类游戏开发演示(2)
  19. IPv4地址(定义、分类、特殊、公有、私有)
  20. 360校园招聘2016笔试题

热门文章

  1. Python Requests爬取百思不得姐视频
  2. 前沿 | 社区问答系统及相关技术
  3. problem 1148
  4. 学习周记 CSS合集
  5. android 实现果冻动画效果,Android实现果冻滑动效果的控件
  6. 2021年全新UI界面1:1仿皮皮虾APP段子
  7. 网页删除mysql数据库_网站数据库被删除了
  8. 桌面、文档、下载等文件夹移动后无法复原或desktop.ini不起作用的修复方法
  9. 解析北斗部标协议_部标一体机北斗模块预测试
  10. 生成文字和二维码合成