真真是遇到一个好玩的python库,可以玩好几天。
上上篇文章中使用itchat对消息进行实时备份和自动回复,同时兼顾防撤回功能,但是有个知友说了:你这防撤回功能代价太大了,要把所有的消息都备份一遍。确实,我也觉得这么做太傻*。想了想看能不能有什么好一点的办法,最起码别这么笨重。
为什么说这是个用处不大的功能,文末再说。
这个功能实现也很简单(实话.mp3->我就不会写难的),120行代码就可以实现。大家可以拿来练练手。
老规矩,使用的库itchat、re、time、shutil、os
实现思路,将接收到的消息都存进一个字典(msg_dict),接收到撤回通知时,提取撤回消息的id,从字典中进行比对,然后发送、保存。那么字典能放得下那么多消息吗?当接收到新消息时,执行函数对字典中超过两分钟的消息进行清理(两分钟内消息不会很多)。
对于四种消息:图片、语音、附件、视频 这些不像文字一样、没法直观看见消息内容。于是收到消息后,将这些消息内容下载缓存,超过两分钟进行删除。同时,如果撤回这些消息的话,便将相应的消息内容保存到另一文件夹中,并发送消息到文件助手进行通知。
文件助手的通知
PC保存的文件(图片、视频、附件、语音):
这个过程中踩到的坑:
1. 对于字典:在使用for item in msg_dict.keys() 进行遍历时,不能进行增删操作,否则报错
2. 注意做好异常处理和细节处理
3.if item['msg_type'] == "Picture" / or item['msg_type'] == "Recording" / or item['msg_type'] == "Video" / or item['msg_type'] == "Attachment":上面的消息,如果写在一行中,错误不容易找出来。
对于发送的比较大的附件或视频,大家可以判断一下大小再决定要不要保存。
代码里写的注释写的比较详细,大家看代码:
# -*-encoding:utf-8-*- import os import re import shutil import time import itchat from itchat.content import * # {msg_id:(msg_from,msg_to,msg_time,msg_time_touser,msg_type,msg_content,msg_url)} msg_dict = {} #ClearTimeOutMsg用于清理消息字典,把超时消息清理掉 #为减少资源占用,此函数只在有新消息动态时调用 def ClearTimeOutMsg(): if msg_dict.__len__() > 0: for msgid in list(msg_dict): #由于字典在遍历过程中不能删除元素,故使用此方法 if time.time() - msg_dict.get(msgid, None)["msg_time"] > 130.0: #超时两分钟 item = msg_dict.pop(msgid) #print("超时的消息:", item['msg_content']) #可下载类消息,并删除相关文件 if item['msg_type'] == "Picture" / or item['msg_type'] == "Recording" / or item['msg_type'] == "Video" / or item['msg_type'] == "Attachment": print("要删除的文件:", item['msg_content']) os.remove(item['msg_content']) #将接收到的消息存放在字典中,当接收到新消息时对字典中超时的消息进行清理 #没有注册note(通知类)消息,通知类消息一般为:红包 转账 消息撤回提醒等,不具有撤回功能 @itchat.msg_register([TEXT, PICTURE, MAP, CARD, SHARING, RECORDING, ATTACHMENT, VIDEO, FRIENDS]) def Revocation(msg): mytime = time.localtime() # 这儿获取的是本地时间 #获取用于展示给用户看的时间 2017/03/03 13:23:53 msg_time_touser = mytime.tm_year.__str__() / + "/" + mytime.tm_mon.__str__() / + "/" + mytime.tm_mday.__str__() / + " " + mytime.tm_hour.__str__() / + ":" + mytime.tm_min.__str__() / + ":" + mytime.tm_sec.__str__() msg_id = msg['MsgId'] #消息ID msg_time = msg['CreateTime'] #消息时间 msg_from = itchat.search_friends(userName=msg['FromUserName'])['NickName'] #消息发送人昵称 msg_type = msg['Type'] #消息类型 msg_content = None #根据消息类型不同,消息内容不同 msg_url = None #分享类消息有url #图片 语音 附件 视频,可下载消息将内容下载暂存到当前目录 if msg['Type'] == 'Text': msg_content = msg['Text'] elif msg['Type'] == 'Picture': msg_content = msg['FileName'] msg['Text'](msg['FileName']) elif msg['Type'] == 'Card': msg_content = msg['RecommendInfo']['NickName'] + r" 的名片" elif msg['Type'] == 'Map': x, y, location = re.search("<location x=/"(.*?)/" y=/"(.*?)/".*label=/"(.*?)/".*", msg['OriContent']).group(1, 2, 3) if location is None: msg_content = r"纬度->" + x.__str__() + " 经度->" + y.__str__() else: msg_content = r"" + location elif msg['Type'] == 'Sharing': msg_content = msg['Text'] msg_url = msg['Url'] elif msg['Type'] == 'Recording': msg_content = msg['FileName'] msg['Text'](msg['FileName']) elif msg['Type'] == 'Attachment': msg_content = r"" + msg['FileName'] msg['Text'](msg['FileName']) elif msg['Type'] == 'Video': msg_content = msg['FileName'] msg['Text'](msg['FileName']) elif msg['Type'] == 'Friends': msg_content = msg['Text'] #更新字典 # {msg_id:(msg_from,msg_time,msg_time_touser,msg_type,msg_content,msg_url)} msg_dict.update( {msg_id: {"msg_from": msg_from, "msg_time": msg_time, "msg_time_touser": msg_time_touser, "msg_type": msg_type, "msg_content": msg_content, "msg_url": msg_url}}) #清理字典 ClearTimeOutMsg() #收到note类消息,判断是不是撤回并进行相应操作 @itchat.msg_register([NOTE]) def SaveMsg(msg): # print(msg) #创建可下载消息内容的存放文件夹,并将暂存在当前目录的文件移动到该文件中 if not os.path.exists(".//Revocation//"): os.mkdir(".//Revocation//") if re.search(r"/<replacemsg/>/</!/[CDATA/[.*撤回了一条消息/]/]/>/<//replacemsg/>", msg['Content']) != None: old_msg_id = re.search("/<msgid/>(.*?)/<//msgid/>", msg['Content']).group(1) old_msg = msg_dict.get(old_msg_id, {}) #print(old_msg_id, old_msg) msg_send = r"您的好友:" / + old_msg.get('msg_from', None) / + r" 在 [" + old_msg.get('msg_time_touser', None) / + r"], 撤回了一条 ["+old_msg['msg_type']+"] 消息, 内容如下:" / + old_msg.get('msg_content', None) if old_msg['msg_type'] == "Sharing": msg_send += r", 链接: " / + old_msg.get('msg_url', None) elif old_msg['msg_type'] == 'Picture' / or old_msg['msg_type'] == 'Recording' / or old_msg['msg_type'] == 'Video' / or old_msg['msg_type'] == 'Attachment': msg_send += r", 存储在当前目录下Revocation文件夹中" shutil.move(old_msg['msg_content'], r".//Revocation//") itchat.send(msg_send, toUserName='filehelper') #将撤回消息的通知以及细节发送到文件助手 msg_dict.pop(old_msg_id) ClearTimeOutMsg() if __name__ == '__main__': itchat.auto_login(hotReload=True) itchat.run()
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/aiops/55129.html