51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

初学Python--微信好友/群消息防撤回,查看相关附件

写在开头:这个功能是小白在学Python中做的小玩意儿。慎用,万一你朋友不小心说了句你不爱听的话,撤回了你没看见,大家还是好朋友;万一你看到了,那友情就打折扣了,这可不好。您也别做啥不合法的事,小白还得准备考研二战~

上篇文章[ 初学python--微信防撤回功能改进(一个用处不大的功能)]中,使用Python的itchat库实现了好友聊天消息防撤回:实现原理,备份两分钟之内的消息,通过撤回通知的信息找到被撤回消息的ID,然后提取发送到文件助手,并保存相关的附件,只能保存在PC,手机没法直接查看;对储存的超时消息进行清理。只有简单的exe,没有界面,也没有Mac和Linux版(穷屌用不上Mac(⋟﹏⋞),怎么开发)。

各位跟我一样的小白,看完这两篇文章,我觉得你应该学会以下内容(不管是看书,上网查资料):字符串及其相关常用函数;元组、列表、字典等数据结构及其常用相关函数的使用;正则表达式及其re库的相关函数;time库的常用函数;文件/文件夹的增删改查(os 和 shutil);itchat库的使用。一定要把基础打牢,不要像我一样求快。最后,欢迎学完这些知识后来重构我的代码或者自己写出来,大家一起学习。

这次的版本中添加了:

1.群聊消息的撤回备份

2.保存的附件并不是零散的堆放在程序文件附近,统一存放在cache中,撤回的消息的附件放在revocation中。

3.实现了发送指令到文件助手可以进行查看删除文件。暂不支持中文名称的文件,还在找原因。

4.支持gif动图,但是不支持微信表情包中表情的撤回及备份

效果图:

撤回消息以及查看:

初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第1张PC端Cache和Revocation文件夹

初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第2张初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第3张各种形式的撤回消息,主要是针对可下载的附件:

初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第4张初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第5张初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第6张

(注:看图最后,不支持查看中文文件名的文件,但是中文文件已经保存)

已打包生成exe:http://pan.baidu.com/s/1ckZi14 密码:ksu0

最新版本:修复群聊非好友bug,多谢@嘻笑怒骂提出bug并帮忙改进

链接:http://pan.baidu.com/s/1eRAtqTk 密码:4iy1

最新版本3.0 :群聊添加群聊昵称 链接:http://pan.baidu.com/s/1jHVjOhC 密码:6xc3

初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第7张

双击运行,扫码登陆,即可挂在电脑后台,退出的话从手机点击退出网页版微信

初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第8张初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第9张初学Python--微信好友/群消息防撤回,查看相关附件_https://www.tiejiang.org_python_第10张

有知友说要弹窗,这样好点儿。有程序界面的版本还得等几天,小白正在努力学习GUI。

微信公众号自动签到功能和查询哪位好友删除自己功能还在实现中,如果可以的话我会第一时间在专栏发布。

刚学Python一个多月,代码和思路远远不够pythonic,请各路大神批评指正,不胜感激(´▽`ʃƪ)

下面是主要代码,大部分跟上篇文章中的代码相似。这个文件功能主要执行发送给文件助手的命令:

查看文件[文件名] e.g. 查看文件[170304-220138.gif]

删除文件[文件名] e.g. 删除文件[170304-220138.gif]

撤回附件列表

有问题请及时通过评论,私信反馈给我,帮我进步,谢谢~

喜欢的话点个赞再走呗~

用着还可以的话赞赏一个更好(●'◡'●)ノ❤

最后是代码~

#WechatForRevocation.py

# -*-encoding:utf-8-*-
import os
import re
import shutil
import time
import itchat
from itchat.content import *
import Execution
{msg_id:(msg_from,msg_to,msg_time,msg_time_touser,msg_type,msg_content,msg_url)}
msg_store = {}
ClearTimeOutMsg用于清理消息字典,把超时消息清理掉
为减少资源占用,此函数只在有新消息动态时调用
def ClearTimeOutMsg():
if msg_store.len() > 0:
for msgid in list(msg_store):  # 由于字典在遍历过程中不能删除元素,故使用此方法
#print("TimeOut:", time.time() - msg_store.get(msgid, None)["msg_time"])
if time.time() - msg_store.get(msgid, None)["msg_time"] > 130.0:  # 超时两分钟
item = msg_store.pop(msgid)
`            # 可下载类消息,并删除相关文件
            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(".\\Cache\\" + item['msg_content'])
`
将接收到的消息存放在字典中,当接收到新消息时对字典中超时的消息进行清理
没有注册note(通知类)消息,通知类消息一般为:红包 转账 消息撤回提醒等,不具有撤回功能
@itchat.msg_register([TEXT, PICTURE, MAP, CARD, SHARING, RECORDING, ATTACHMENT, VIDEO, FRIENDS], isFriendChat=True,
isGroupChat=True)
def Revocation(msg):
# 处理指令
itchat.get_friends(update=True)
print("TEst",msg)
if msg['ToUserName'] == "filehelper" and msg['Type'] == "Text":
result = Execution.Execution(msg)
`    if result[0] == 0:
        itchat.send(result[1] + r"文件:" + result[2] + r" 失败", toUserName="filehelper")
    elif result[0] == 1:
        itchat.send(r"删除文件:" + result[2] + r" 成功", toUserName="filehelper")
    else:
        pass
    return

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'] # 消息时间 if itchat.search_friends(userName=msg['FromUserName']): if itchat.search_friends(userName=msg['FromUserName'])['RemarkName']: msg_from = itchat.search_friends(userName=msg['FromUserName'])['RemarkName'] # 消息发送人备注 elif itchat.search_friends(userName=msg['FromUserName'])['NickName']: # 消息发送人昵称 msg_from = itchat.search_friends(userName=msg['FromUserName'])['NickName'] # 消息发送人昵称 else: msg_from = r"读取发送消息好友失败" else: msg_from = msg['ActualNickName'] 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' shutil.move(msg_content, r".\Cache\") 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' shutil.move(msg_content, r".\Cache\") elif msg['Type'] == 'Attachment': msg_content = msg['FileName'] msg'Text' shutil.move(msg_content, r".\Cache\") elif msg['Type'] == 'Video': msg_content = msg['FileName'] msg'Text' shutil.move(msg_content, r".\Cache\") elif msg['Type'] == 'Friends': msg_content = msg['Text']

# print(r"消息提取",
# {"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})

print("消息提取", msg)

更新字典

{msg_id:(msg_from,msg_time,msg_time_touser,msg_type,msg_content,msg_url)}

msg_store.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() ` @itchat.msg_register([NOTE], isFriendChat=True, isGroupChat=True) def SaveMsg(msg):

print(msg)

创建可下载消息内容的存放文件夹,并将暂存在当前目录的文件移动到该文件中

if not os.path.exists(".\Revocation"): os.mkdir(".\Revocation") `itchat.search_chatrooms() if re.search(r"![CDATA[.撤回了一条消息]]", msg['Content']) != None: print("撤回Msg", msg) if re.search("<msgid>(.?)</msgid>", msg['Content']) != None: old_msg_id = re.search("<msgid>(.?)</msgid>", msg['Content']).group(1) elif re.search(";msgid>(.?)&lt", msg['Content']) != None: old_msg_id = re.search(";msgid>(.*?)&lt", msg['Content']).group(1) old_msg = msg_store.get(old_msg_id, {})

print(r"撤回的消息", old_msg_id, old_msg)
if old_msg:
    msg_send = r"您的好友:" \
               + old_msg.get('msg_from', None) \
               + r"  在 [" + old_msg.get('msg_time_touser', None) \
               + r"], 撤回了一条 [" + old_msg.get('msg_type', None) + "] 消息, 内容如下:" \
               + 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(r".\\Cache\\" + old_msg['msg_content'], r".\\Revocation\\")
else:
    msg_send = r"您的好友可能撤回了一个微信表情包,暂时不支持微信表情包,请谅解。"

itchat.send(msg_send, toUserName='filehelper')  # 将撤回消息的通知以及细节发送到文件助手

msg_store.pop(old_msg_id)

` if name == 'main': ClearTimeOutMsg() if not os.path.exists(".\Cache"): os.mkdir(".\Cache") itchat.auto_login(hotReload=True) itchat.run()


#Execution.py

import os
import re
import time
import itchat
def Execution(message):
command = message['Text']
print("command:", command)
if re.search(r"(.?)文件\[(.?)]", command):
action, filename = re.search(r"(.?)文件\[(.?)]", command).group(1, 2)
return ViewDeleteFile(action, filename)
elif re.search(r"^公众号签到$", command):
return Signin()
elif re.search(r"^查询好友状态$", command):
return (3,"","")
#return FriendStutas()
elif re.match(r"^撤回附件列表$", command):
return ReturnAttachmentList()
else:
itchat.send(r"亲,暂时支持以下指令:"
r"【查看/删除文件[文件名] e.g.123345234.mp3】 "
r"【撤回附件列表(查看都有哪些保存在电脑中的已撤回附件)】 "
r"其他指令暂不支持,请期待最新版本。", toUserName="filehelper")
return (3, "指令", "失败")
def ViewDeleteFile(action, filename):
if action == None or filename == None:
itchat.send(r"亲,目前支持两种指令:查看/删除文件[文件名] e.g.查看文件[12345678.jpg]", toUserName="filehelper")
return (3, "指令", "文件")
`if action == r"查看":
    if re.search(r"png|jpg|bmp|jpeg|gif", filename):
        msg_type = "Picture"
    elif re.search(r"avi|rm|map4|wmv", filename):
        msg_type = "Video"
    else:
        msg_type = "fil"
itchat.send("@%s@%s" % (
    {"Picture": "img", "Video": "vid"}.get(msg_type, 'fil'), r".\\Revocation\\" + filename),
            toUserName="filehelper")
return (2, action, filename)

elif action == r"删除": if os.path.exists(r".\Revocation\" + filename): os.remove(r".\Revocation\" + filename) return (1, action, filename)

return (0, action, filename) 查询把自己删除的好友 除了一个个添加好友,还有一个实现方式:全部添加进去,然后获取群聊好友列表然后逐个比对。 def FriendStutas(): friendlist = itchat.get_friends()[0:1] delete_friend_list = [] succeed_friend_list = []chat_topic = r"球队专属聊天群" itchat.create_chatroom(memberList=friendlist, topic=chat_topic) if itchat.search_chatrooms(name=chat_topic): for new_friend in itchat.get_friends()[1:]: result_friend = itchat.add_member_into_chatroom(itchat.search_chatrooms(name=chat_topic)[0]['UserName'], [new_friend]) if result_friend.get('BaseResponse', None).get('ErrMsg', None): print(r"添加结果 ", result_friend) succeed_friend_list.append(new_friend) else: if new_friend['RemarkName']: delete_friend_list.append(new_friend['RemarkName']) else: delete_friend_list.append(new_friend['NickName']) itchat.delete_member_from_chatroom(itchat.search_chatrooms(name=chat_topic)[0]['UserName'], succeed_friend_list)

msg_send = r"以下好友把你删除了,请核实:"
for item in delete_friend_list:  msg_send.join(item + ", ")
itchat.send(msg_send, toUserName="filehelper")

else: itchat.send(r"查询失败(包括这次一共有三次机会)", toUserName="filehelper") print('#' * 30) print(r"以下好友删除你了...") print("deleted:", delete_friend_list) print(r"以下好友没有删除你:") print("succeed:", succeed_friend_list) print(itchat.search_chatrooms(name=chat_topic))

return (3, "查询", "状态") ` 返回撤回附件所有文件名 def ReturnAttachmentList(): filepath = ".\Revocation" filelist = os.listdir(filepath) if filelist: msg_send = r"所有储存的附件如下:" for item in filelist: msg_send = msg_send + item + ", " itchat.send(msg_send, toUserName="filehelper") else: itchat.send(r"亲,暂时没有撤回的附件", toUserName="filehelper") return (3, "附件列表", "成功") 微信公众号签到 def Signin(): itchat.send("亲,暂时不支持公众号签到功能,请谅解。", toUserName="filehelper") return (3, "签到", "状态")


赞(1)
未经允许不得转载:工具盒子 » 初学Python--微信好友/群消息防撤回,查看相关附件