python实现微信自动回复机器人+查看别人撤回的消息(部署到云服务器)

声明:仅供技术交流,请勿用于非法用途,如有其它非法用途造成损失,和本博客无关

目录

  • python实现微信自动回复机器人+查看别人撤回的消息(部署到云服务器)
  • 前言
    • 一、准备
    • 二、开始
    • 三、完整代码
    • 四、思维导图(逻辑结构)
    • 五、部署到云服务器
    • 六、运行展示
  • 写在最后

前言

  • 首先你的微信号能够登录网页版微信,才能打造你的专属个人微信号机器人,点击跳转网页版微信登录页面
  • 类似的文章网上也都有,其实我也是受到别的文章的一些启发,因为不是每个人都想实现同样的功能的,直接套用别人的代码不严谨而且bug太多,于是就想自己动手从零开始实现一个属于自己的微信机器人,不过呢,也大同小异吧。
  • 算下来前前后后加上写这篇博客花了大概一周的时间,因为都是用零零散散的时间进行开发以及测试然后修改bug再加功能再开发,这么一个循环,从一开始的只能回复消息、到现在能够:回复特定群聊消息、特殊群聊特殊处理、回复表情包、查看所有别人撤回的消息以及操控微信机器人等等等等。

好的,废话不多说,接下来就开始吧。

一、准备

  1. python3.7(重中之重,后面会解释)
  2. itchat(直接用pip命令安装即可)
  3. jupyter notebook(随意,用你最喜欢的编译器即可,不过最后还是要把代码放在一个py文件里)
  4. NLP实现一个聊天机器人(限于本人没学过自然语言处理,并且空闲时间也不多,其实就是因为太难了。。那就只能先调用别人的接口啦)

二、开始

ps:详情请看代码注释,若不想分函数来看也可以直接看完整代码

  • 定义获取好友的昵称和好友的备注函数
def get_friendname():friends_name={} #存储好友的微信昵称和备注friends=itchat.get_friends(update=True) #返回的是一个存储所有好友信息的列表,每个好友的信息都是用一个字典来存放for friend in friends[1:]: #第一个为自己,所以这里排除了自己friends_name.update({friend['UserName']:{'nickname':friend['NickName'],'remarkname':friend['RemarkName']}})return friends_name
  • 定义群聊信息的函数
    ps:这个获取群聊信息的函数只能读取到你保存到通讯录中的群聊,那些没有保存到通讯录中的是显示不出来的,不过不影响获取群聊信息,它只是没有显示而已,后面添加特定群聊就算是没有保存通讯录的都是可以添加的,一样可以回复特定群聊。
def get_username():chatrooms=itchat.get_chatrooms(update=True) #返回的是一个所有群聊的信息的列表,每个群聊信息都是用一个字典来存放user_name=[] #接收特定群聊@本人的消息,并回复;存放特定群聊的usernameall_user_name=[] #存放全部群聊的usernamevip=[] #存放特定群聊的名称if os.path.exists('./vip.txt'):with open('./vip.txt','r',encoding='utf-8') as f:for i in f.read().split('\n')[:-1]:vip.append(i)for chatroom in chatrooms:all_user_name.append(chatroom['UserName'])if chatroom['NickName'] in vip:user_name.append(chatroom['UserName'])return all_user_name,user_name,vip
  • 定义获取聊天机器人返回信息的函数点击跳转在线聊天机器人
def get_response(msg):url=''#看到请求url好像涉及到一些sessionid、userid等信息,可能直接复制会用不了什么的,所以你们直接去分析一下网页即可拿到啦,把content参数format成msg即可headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'}r=requests.get(url,headers=headers)response=re.findall('"body":{"fontStyle":0,"fontColor":0,"content":"(.*?)","emoticons":{}}}',r.text)[1].replace('\\r\\n','')return response
  • 定义获取聊天机器人词穷时要回复消息的函数
def get_words():words=[]if os.path.exists('./words.txt'):with open('./words.txt','r',encoding='utf-8') as f:for i in f.read().split('\n')[:-1]:words.append(i)return words
  • 定义注册消息函数(重头戏)
# 包括文本(表情符号)、位置、名片、通知、分享、图片(表情包)、语音、文件、视频
@itchat.msg_register([TEXT,MAP,CARD,SHARING,PICTURE,RECORDING,ATTACHMENT,VIDEO],isFriendChat=True,isGroupChat=True) #监听个人消息和群聊消息
def download_reply_msg(msg):global flag,sj,isrun,use_info #flag判断要不要进入斗图模式,sj控制斗图的时间长短,isrun判断是否启动自动回复机器人(默认运行中),通过向传输助手发指令来控制,use_info说明文档all_user_name,user_name,vip=get_username()#每次接受消息时要拿到当前规定的群聊和特定群聊信息,后面用来分别做处理words=get_words() #拿到当前自定义回复消息的信息now_time=int(time.time()) #记录获取这条消息的时间,后面处理撤回消息的时候用到b=[] #用来记录已经过了可以撤回的时间的消息if len(msg_dict) != 0:for key,value in msg_dict.items():if (now_time - value['time']) >= 125: #经过验证发现消息2分钟之内才能撤回,这里为了保险起见加多5秒钟b.append(key)for eachkey in list(msg_dict.keys()):if eachkey in b: #要是过了撤回时间的消息是文件类型的就把它们删除,避免增加不必要的磁盘空间,盘大的请随意if 'file' in msg_dict[eachkey].keys():os.remove(msg_dict[eachkey]['file'])msg_dict.pop(eachkey)
#---------------------------------------------------------
#下面开始存储各类消息,主要是用来查看别人撤回的消息,后面会用到if msg['Type'] in [MAP,SHARING]: #地图或者分享old_id=msg['MsgId']link=msg['Url']msg_dict.update({old_id:{'type':msg['Type'],'data':link,'time':now_time}})elif msg['Type'] in [PICTURE,RECORDING,ATTACHMENT,VIDEO]:if msg['ToUserName'] != 'filehelper': # 避免给文件传输助手发文件也传入字典,没必要而且传入字典只是为了防止撤回,况且它是没有撤回的old_id=msg['MsgId']file='./保存的文件/'+ msg['MsgId'] + '.' + msg['FileName'].split('.')[-1]msg['Text'](file)msg_dict.update({old_id:{'type':msg['Type'],'file':file,'time':now_time}})else:file='./保存的文件/'+ msg['FileName']msg['Text'](file)elif msg['Type'] == CARD: #名片old_id=msg['MsgId']link=re.findall('bigheadimgurl="(.*)" smallheadimgurl',str(msg))[0]msg_content = '来自' + msg['RecommendInfo']['Province'] +msg['RecommendInfo']['City'] + '的'+ msg['RecommendInfo']['NickName'] + '的名片'    #内容就是推荐人的昵称和性别if msg['RecommendInfo']['Sex'] == 1:msg_content += ',男的'else:msg_content += ',女的'msg_dict.update({old_id:{'type':msg['Type'],'head':link,'data':msg_content,'time':now_time}})elif msg['Type'] == TEXT: #文本old_id=msg['MsgId']text=msg['Text']msg_dict.update({old_id:{'type':msg['Type'],'data':text,'time':now_time}})
#---------------------------------------------------------
#下面是自动回复消息的(一切回复逻辑都在这里)if msg['ToUserName'] != 'filehelper': # 避免给文件传输助手发消息也自动回复if isrun == '运行中......': #操控机器人的,想停就停,想启动就启动,不用关掉程序,而且不影响查看撤回消息的功能if msg['FromUserName'] in all_user_name:if msg['FromUserName'] in user_name: #当消息来自特定群聊时,下面代码才会执行if sj is not None:if int(time.time()) - sj >= 900: #斗图时间:15分钟flag=0sj=Noneif (msg['isAt'] is True)&(msg['Type'] == TEXT):myname='@' + re.findall("'Self'.*?'DisplayName': '(.*?)', 'KeyWord'",str(msg))[0] if re.findall("'Self'.*?'DisplayName': '(.*?)', 'KeyWord'",str(msg))[0] != '' else '这里填你自己的微信昵称'if '帅哥来斗图' in msg['Text']:flag=1sj=int(time.time())num=random.choice(os.listdir('./表情包'))msg.user.send('@img@./表情包/{}'.format(num))return Nonereply = get_response(msg['Text'].replace(myname,''))if 'I am' in reply:reply=reply.replace('小i机器人','your father')if '小i' in reply: #这个我是不想让别人知道是小i机器人,才把它换掉的,你想换成什么随你,不换也行,就把这段代码删除即可reply=reply.replace('小i','你爸爸')if '机器人' in reply:reply=reply.replace('机器人','')if '输入' in reply:if flag == 0:reply='有种来斗图,输入“帅哥来斗图”即可。'else:reply=random.choice(words)itchat.send('@%s\u2005%s' % (msg['ActualNickName'], reply), msg['FromUserName'])if (msg['Type'] == PICTURE)&(flag == 1):num=random.choice(os.listdir('./表情包'))msg.user.send('@img@./表情包/{}'.format(num))else: #这里是当消息来自不是特定群聊时,要执行的代码if msg['Type'] == TEXT:if '收到请回复' in msg['Text']:return '收到'else: #下面是处理个人消息的#经过测试发现如果自己手动发消息到新建的群中,也会触发下面自动回复的代码,于是就要排除这个bug用下面第一个if语句if msg['FromUserName'] == itchat.search_friends(nickName='这里填你自己的微信昵称')[0]['UserName']:return Noneif msg['Type'] == TEXT: #下面跟处理群聊的时候差不多,就不重复了嘻嘻reply = get_response(msg['Text'])if 'I am' in reply:reply=reply.replace('小i机器人','your father')if '小i' in reply:reply=reply.replace('小i','你爸爸')if '机器人' in reply:reply=reply.replace('机器人','')if '输入' in reply:reply=random.choice(words)msg.user.send(reply+'\n                                    [不是本人]') # 36个空格elif msg['Type'] == PICTURE: #表情包回复num=random.choice(os.listdir('./表情包'))msg.user.send('@img@./表情包/{}'.format(num))elif msg['Type'] == RECORDING:msg.user.send('请打字和我交流,谢谢。'+'\n                                    [不是本人]')
#---------------------------------------------------------
#下面是用来控制机器人的(给文件传输助手发指令)代码很简单,也很清晰else:if msg['Type'] == TEXT:if '添加vip' in msg['Text']:with open('./vip.txt','a',encoding='utf-8') as f:f.write(msg['Text'][5:])f.write('\n')if '查看vip' in msg['Text']:now_vip='\n'.join(vip)itchat.send('当前的vip群有:\n{0}'.format(now_vip), toUserName='filehelper')if '删除vip' in msg['Text']:if os.path.exists('./vip.txt'):with open('./vip.txt','r',encoding='utf-8') as f1:lines=f1.readlines()with open('./vip.txt','w',encoding='utf-8') as f2:for line in lines:if msg['Text'][5:] != line.strip():f2.write(line)if '清空vip' in msg['Text']:with open('./vip.txt','w',encoding='utf-8') as f:f.flush()if '添加words' in msg['Text']:with open('./words.txt','a',encoding='utf-8') as f:f.write(msg['Text'][7:])f.write('\n')if '查看words' in msg['Text']:now_words='\n'.join(words)itchat.send('当前的words有:\n{0}'.format(now_words), toUserName='filehelper')if '删除words' in msg['Text']:if os.path.exists('./words.txt'):with open('./words.txt','r',encoding='utf-8') as f1:lines=f1.readlines()with open('./words.txt','w',encoding='utf-8') as f2:for line in lines:if msg['Text'][7:] != line.strip():f2.write(line)if '清空words' in msg['Text']:with open('./words.txt','w',encoding='utf-8') as f:f.flush()if '停止机器人' in msg['Text']:isrun='已停止!'if '启动机器人' in msg['Text']:isrun='运行中......'if '查看机器人' in msg['Text']:itchat.send(isrun, toUserName='filehelper')if 'robot' in msg['Text']:itchat.send(use_info, toUserName='filehelper')
  • 定义监控撤回消息的函数(别人撤回的消息都会发到文件传输助手中)
@itchat.msg_register(NOTE,isFriendChat=True,isGroupChat=True)
def get_note(msg):if '撤回了一条消息' in msg['Text']:if '你撤回了一条消息' in msg['Text']:return Nonenew_id=re.findall('<msgid>(\d+)</msgid>',str(msg))[0]public_time=time.strftime('%Y-%m-%d %H:%M:%S',time.gmtime(msg['CreateTime']+28800))data=msg_dict[new_id]nickname=re.findall("'UserName': '@[a-zA-Z0-9]+', 'NickName': '(.*?)', 'HeadImgUrl'",str(msg))[0]if len(nickname) > 100:friends_name=get_friendname()#群名这句我觉得还会有bug,由于测试的时候只在2个人的群中测试,多个的话可能会出bug,这个后面再说吧,反正我24小时挂着,有bug咱再说哈哈qun=re.findall("'NickName': '.*",re.findall("'UserName': '@[a-zA-Z0-9]+', 'NickName': '(.*)', 'HeadImgUrl'",str(msg))[0][-100:])[0].replace("'NickName': '",'')an=msg['ActualNickName']nickname='{0}在{1}群中'.format(an,qun)if msg['ActualUserName'] in friends_name.keys():if friends_name[msg['ActualUserName']]['remarkname'] != '':nickname='{0}({1})在{2}群中'.format(an,friends_name[msg['ActualUserName']]['remarkname'],qun)else:nickname='{0}({1})在{2}群中'.format(an,friends_name[msg['ActualUserName']]['nickname'],qun)if data['type'] == MAP:itchat.send('%s在%s撤回了一个位置,其位置:\n%s'%(nickname,public_time,data['data']),toUserName='filehelper')elif data['type'] == CARD:itchat.send('%s在%s撤回了一个名片,名片信息:\n%s,其头像:'%(nickname,public_time,data['data']),toUserName='filehelper')itchat.send('%s'%(data['head']),toUserName='filehelper')elif data['type'] == SHARING:itchat.send('%s在%s撤回了一个分享,其链接:\n%s'%(nickname,public_time,data['data']),toUserName='filehelper')elif data['type'] == TEXT:itchat.send('%s在%s撤回了一个信息,其内容:\n%s'%(nickname,public_time,data['data']),toUserName='filehelper')elif data['type'] in [PICTURE,RECORDING,ATTACHMENT,VIDEO]:itchat.send('%s在%s撤回了一张图片或者一个表情或者一段语音或者一个视频又或者一个文件,如下:'%(nickname,public_time),toUserName='filehelper')itchat.send('@%s@%s'%({'Picture': 'img', 'Video': 'vid'}.get(data['type'], 'fil'),data['file']),toUserName='filehelper')
  • 到这里已经定义好了全部所需要的函数了,接下来就是文件的创建和表情包的收集,目前表情包是手动发表情让程序自动保存下来,其实可以定义一个添加表情的函数的,这个我后面会做出来,所以先这样吧,收集自定义表情包的函数如下:

ps:这个函数要另外单独运行(亲测商城里的表情包是保存不了的)

@itchat.msg_register(PICTURE) #只需要注册图片消息类型就可以了
def download_msg(msg):global q  #给文件传输助手发送你想要保存的表情包即可if msg['ToUserName'] == 'filehelper':msg['Text']('./表情包/' + str(q) + '.' + msg['FileName'].split('.')[-1])q+=1
q=1
itchat.auto_login(hotReload=True)
if not os.path.exists('./表情包'):os.makedirs('./表情包')
itchat.run()

三、完整代码

import requests
import itchat
from itchat.content import *
import urllib
import random
import re
import os
import timedef get_response(msg):url=''#看到请求url好像涉及到一些sessionid、userid等信息,可能直接复制会用不了什么的,所以你们直接去分析一下网页即可拿到啦,把content参数format成msg即可headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'}r=requests.get(url,headers=headers)response=re.findall('"body":{"fontStyle":0,"fontColor":0,"content":"(.*?)","emoticons":{}}}',r.text)[1].replace('\\r\\n','')return responsedef get_words():words=[]if os.path.exists('./words.txt'):with open('./words.txt','r',encoding='utf-8') as f:for i in f.read().split('\n')[:-1]:words.append(i)return wordsdef get_friendname():friends_name={} #存储好友的微信昵称和备注friends=itchat.get_friends(update=True) #返回的是一个存储所有好友信息的列表,每个好友的信息都是用一个字典来存放for friend in friends[1:]: #第一个为自己,所以这里排除了自己friends_name.update({friend['UserName']:{'nickname':friend['NickName'],'remarkname':friend['RemarkName']}})return friends_namedef get_username():chatrooms=itchat.get_chatrooms(update=True) #返回的是一个所有群聊的信息的列表,每个群聊信息都是用一个字典来存放user_name=[] #接收特定群聊@本人的消息,并回复;存放特定群聊的usernameall_user_name=[] #存放全部群聊的usernamevip=[] #存放特定群聊的名称if os.path.exists('./vip.txt'):with open('./vip.txt','r',encoding='utf-8') as f:for i in f.read().split('\n')[:-1]:vip.append(i)for chatroom in chatrooms:all_user_name.append(chatroom['UserName'])if chatroom['NickName'] in vip:user_name.append(chatroom['UserName'])return all_user_name,user_name,vip# 包括文本(表情符号)、位置、名片、通知、分享、图片(表情包)、语音、文件、视频
@itchat.msg_register([TEXT,MAP,CARD,SHARING,PICTURE,RECORDING,ATTACHMENT,VIDEO],isFriendChat=True,isGroupChat=True) #监听个人消息和群聊消息
def download_reply_msg(msg):global flag,sj,isrun,use_info #flag判断要不要进入斗图模式,sj控制斗图的时间长短,isrun判断是否启动自动回复机器人(默认运行中),通过向传输助手发指令来控制,use_info说明文档all_user_name,user_name,vip=get_username()#每次接受消息时要拿到当前规定的群聊和特定群聊信息,后面用来分别做处理words=get_words() #拿到当前自定义回复消息的信息now_time=int(time.time()) #记录获取这条消息的时间,后面处理撤回消息的时候用到b=[] #用来记录已经过了可以撤回的时间的消息if len(msg_dict) != 0:for key,value in msg_dict.items():if (now_time - value['time']) >= 125: #经过验证发现消息2分钟之内才能撤回,这里为了保险起见加多5秒钟b.append(key)for eachkey in list(msg_dict.keys()):if eachkey in b: #要是过了撤回时间的消息是文件类型的就把它们删除,避免增加不必要的磁盘空间,盘大的请随意if 'file' in msg_dict[eachkey].keys():os.remove(msg_dict[eachkey]['file'])msg_dict.pop(eachkey)
#---------------------------------------------------------
#下面开始存储各类消息,主要是用来查看别人撤回的消息,后面会用到if msg['Type'] in [MAP,SHARING]: #地图或者分享old_id=msg['MsgId']link=msg['Url']msg_dict.update({old_id:{'type':msg['Type'],'data':link,'time':now_time}})elif msg['Type'] in [PICTURE,RECORDING,ATTACHMENT,VIDEO]:if msg['ToUserName'] != 'filehelper': # 避免给文件传输助手发文件也传入字典,没必要而且传入字典只是为了防止撤回,况且它是没有撤回的old_id=msg['MsgId']file='./保存的文件/'+ msg['MsgId'] + '.' + msg['FileName'].split('.')[-1]msg['Text'](file)msg_dict.update({old_id:{'type':msg['Type'],'file':file,'time':now_time}})else:file='./保存的文件/'+ msg['FileName']msg['Text'](file)elif msg['Type'] == CARD: #名片old_id=msg['MsgId']link=re.findall('bigheadimgurl="(.*)" smallheadimgurl',str(msg))[0]msg_content = '来自' + msg['RecommendInfo']['Province'] +msg['RecommendInfo']['City'] + '的'+ msg['RecommendInfo']['NickName'] + '的名片'    #内容就是推荐人的昵称和性别if msg['RecommendInfo']['Sex'] == 1:msg_content += ',男的'else:msg_content += ',女的'msg_dict.update({old_id:{'type':msg['Type'],'head':link,'data':msg_content,'time':now_time}})elif msg['Type'] == TEXT: #文本old_id=msg['MsgId']text=msg['Text']msg_dict.update({old_id:{'type':msg['Type'],'data':text,'time':now_time}})
#---------------------------------------------------------
#下面是自动回复消息的(一切回复逻辑都在这里)if msg['ToUserName'] != 'filehelper': # 避免给文件传输助手发消息也自动回复if isrun == '运行中......': #操控机器人的,想停就停,想启动就启动,不用关掉程序,而且不影响查看撤回消息的功能if msg['FromUserName'] in all_user_name:if msg['FromUserName'] in user_name: #当消息来自特定群聊时,下面代码才会执行if sj is not None:if int(time.time()) - sj >= 900: #斗图时间:15分钟flag=0sj=Noneif (msg['isAt'] is True)&(msg['Type'] == TEXT):myname='@' + re.findall("'Self'.*?'DisplayName': '(.*?)', 'KeyWord'",str(msg))[0] if re.findall("'Self'.*?'DisplayName': '(.*?)', 'KeyWord'",str(msg))[0] != '' else '这里填你自己的微信昵称'if '帅哥来斗图' in msg['Text']:flag=1sj=int(time.time())num=random.choice(os.listdir('./表情包'))msg.user.send('@img@./表情包/{}'.format(num))return Nonereply = get_response(msg['Text'].replace(myname,''))if 'I am' in reply:reply=reply.replace('小i机器人','your father')if '小i' in reply: #这个我是不想让别人知道是小i机器人,才把它换掉的,你想换成什么随你,不换也行,就把这段代码删除即可reply=reply.replace('小i','你爸爸')if '机器人' in reply:reply=reply.replace('机器人','')if '输入' in reply:if flag == 0:reply='有种来斗图,输入“帅哥来斗图”即可。'else:reply=random.choice(words)itchat.send('@%s\u2005%s' % (msg['ActualNickName'], reply), msg['FromUserName'])if (msg['Type'] == PICTURE)&(flag == 1):num=random.choice(os.listdir('./表情包'))msg.user.send('@img@./表情包/{}'.format(num))else: #这里是当消息来自不是特定群聊时,要执行的代码if msg['Type'] == TEXT:if '收到请回复' in msg['Text']:return '收到'else: #下面是处理个人消息的#经过测试发现如果自己手动发消息到新建的群中,也会触发下面自动回复的代码,于是就要排除这个bug用下面第一个if语句if msg['FromUserName'] == itchat.search_friends(nickName='这里填你自己的微信昵称')[0]['UserName']:return Noneif msg['Type'] == TEXT: #下面跟处理群聊的时候差不多,就不重复了嘻嘻reply = get_response(msg['Text'])if 'I am' in reply:reply=reply.replace('小i机器人','your father')if '小i' in reply:reply=reply.replace('小i','你爸爸')if '机器人' in reply:reply=reply.replace('机器人','')if '输入' in reply:reply=random.choice(words)msg.user.send(reply+'\n                                    [不是本人]') # 36个空格elif msg['Type'] == PICTURE: #表情包回复num=random.choice(os.listdir('./表情包'))msg.user.send('@img@./表情包/{}'.format(num))elif msg['Type'] == RECORDING:msg.user.send('请打字和我交流,谢谢。'+'\n                                    [不是本人]')
#---------------------------------------------------------
#下面是用来控制机器人的(给文件传输助手发指令)代码很简单,也很清晰else:if msg['Type'] == TEXT:if '添加vip' in msg['Text']:with open('./vip.txt','a',encoding='utf-8') as f:f.write(msg['Text'][5:])f.write('\n')if '查看vip' in msg['Text']:now_vip='\n'.join(vip)itchat.send('当前的vip群有:\n{0}'.format(now_vip), toUserName='filehelper')if '删除vip' in msg['Text']:if os.path.exists('./vip.txt'):with open('./vip.txt','r',encoding='utf-8') as f1:lines=f1.readlines()with open('./vip.txt','w',encoding='utf-8') as f2:for line in lines:if msg['Text'][5:] != line.strip():f2.write(line)if '清空vip' in msg['Text']:with open('./vip.txt','w',encoding='utf-8') as f:f.flush()if '添加words' in msg['Text']:with open('./words.txt','a',encoding='utf-8') as f:f.write(msg['Text'][7:])f.write('\n')if '查看words' in msg['Text']:now_words='\n'.join(words)itchat.send('当前的words有:\n{0}'.format(now_words), toUserName='filehelper')if '删除words' in msg['Text']:if os.path.exists('./words.txt'):with open('./words.txt','r',encoding='utf-8') as f1:lines=f1.readlines()with open('./words.txt','w',encoding='utf-8') as f2:for line in lines:if msg['Text'][7:] != line.strip():f2.write(line)if '清空words' in msg['Text']:with open('./words.txt','w',encoding='utf-8') as f:f.flush()if '停止机器人' in msg['Text']:isrun='已停止!'if '启动机器人' in msg['Text']:isrun='运行中......'if '查看机器人' in msg['Text']:itchat.send(isrun, toUserName='filehelper')if 'robot' in msg['Text']:itchat.send(use_info, toUserName='filehelper')@itchat.msg_register(NOTE,isFriendChat=True,isGroupChat=True)
def get_note(msg):if '撤回了一条消息' in msg['Text']:if '你撤回了一条消息' in msg['Text']:return Nonenew_id=re.findall('<msgid>(\d+)</msgid>',str(msg))[0]public_time=time.strftime('%Y-%m-%d %H:%M:%S',time.gmtime(msg['CreateTime']+28800))data=msg_dict[new_id]nickname=re.findall("'UserName': '@[a-zA-Z0-9]+', 'NickName': '(.*?)', 'HeadImgUrl'",str(msg))[0]if len(nickname) > 100:friends_name=get_friendname()#群名这句我觉得还会有bug,由于测试的时候只在2个人的群中测试,多个的话可能会出bug,这个后面再说吧,反正我24小时挂着,有bug咱再说哈哈qun=re.findall("'NickName': '.*",re.findall("'UserName': '@[a-zA-Z0-9]+', 'NickName': '(.*)', 'HeadImgUrl'",str(msg))[0][-100:])[0].replace("'NickName': '",'')an=msg['ActualNickName']nickname='{0}在{1}群中'.format(an,qun)if msg['ActualUserName'] in friends_name.keys():if friends_name[msg['ActualUserName']]['remarkname'] != '':nickname='{0}({1})在{2}群中'.format(an,friends_name[msg['ActualUserName']]['remarkname'],qun)else:nickname='{0}({1})在{2}群中'.format(an,friends_name[msg['ActualUserName']]['nickname'],qun)if data['type'] == MAP:itchat.send('%s在%s撤回了一个位置,其位置:\n%s'%(nickname,public_time,data['data']),toUserName='filehelper')elif data['type'] == CARD:itchat.send('%s在%s撤回了一个名片,名片信息:\n%s,其头像:'%(nickname,public_time,data['data']),toUserName='filehelper')itchat.send('%s'%(data['head']),toUserName='filehelper')elif data['type'] == SHARING:itchat.send('%s在%s撤回了一个分享,其链接:\n%s'%(nickname,public_time,data['data']),toUserName='filehelper')elif data['type'] == TEXT:itchat.send('%s在%s撤回了一个信息,其内容:\n%s'%(nickname,public_time,data['data']),toUserName='filehelper')elif data['type'] in [PICTURE,RECORDING,ATTACHMENT,VIDEO]:itchat.send('%s在%s撤回了一张图片或者一个表情或者一段语音或者一个视频又或者一个文件,如下:'%(nickname,public_time),toUserName='filehelper')itchat.send('@%s@%s'%({'Picture': 'img', 'Video': 'vid'}.get(data['type'], 'fil'),data['file']),toUserName='filehelper')# 下面开始运行机器人和创建所需目录以及定义默认变量
#itchat.auto_login(hotReload=True) #windows下用这个
itchat.auto_login(hotReload=True,enableCmdQR=2) #linux下用这个
msg_dict={} # 储存聊天记录,找到撤回的消息
flag=0 # 判断vip群要不要进入斗图模式(默认不会,flag为1时就会)
sj=None # 判断啥时候flag恢复为0
use_info='一、特殊群聊管理\n①增加:添加vip+群名\n②删除:删除vip+群名\n③查询:查看vip+群名\n④清空:清空vip+群名\n二、默认回复管理\n①增加:添加words+语句\n②删除:删除words+语句\n③查询:查看words+语句\n④清空:清空words+语句\n三、robot管理\n①启动:启动机器人\n②停止:停止机器人\n③状态:查看机器人\n四、说明文档:\n①指令:robot\n②注意:如果添加的群没有名字,那么把群里每个人的昵称用英文逗号隔开' #说明文档
isrun='运行中......' # 是否启动自动回复机器人(默认运行中),通过向传输助手发指令来控制
if not os.path.exists('./表情包'):os.makedirs('./表情包')
if not os.path.exists('./保存的文件'):os.makedirs('./保存的文件')
itchat.run()

四、思维导图(逻辑结构)

ps:单看代码不过瘾的话看下面的图片吧,机器人处理消息的大致流程如下:

五、部署到云服务器

前面我有说过就是一定要python3.7版本的原因就在这里(也不是非要3.7版本,不过我敢肯定的是3.4版本是一定不行。)因为我本机上的就是3.7,可是服务器上的系统自带的是python3.4,然后如果你直接用3.4版本来运行,是可以运行的,只是返回来的msg是乱序的,每一次登录它都不一样,这样为什么不行呢,因为代码里面用了正则匹配,每次返回来的信息顺序都不一样的话,是没办法确定正则表达式的。这个坑坑了我一天好像,因为当时我就差这一步就完成了!想到会不会是jsonxml版本的原因啊,然后这些又都是标准库,那么会不会是python版本原因造成的呢,于是乎,结果真的是这么回事!!说到云服务器,我之前的文章就有介绍过了,我用的是三丰云服务器,土豪请无视。

  • 一样首先要在linux系统下先将自定义的表情包给上传了,这里推荐一个命令:rz ,若还没有安装的,可以在终端运行如下代码,成功之后,进去想要上传的文件夹路径输入rz命令,会弹出选择文件的框,这时就可以把表情包全部上传了。
sudo apt-get install lrzsz
  • 要用crontab添加定时任务,就当前时间的下几分钟就好了,到点之后找到日志输入文件扫码进行登录即可,完了之后将定时任务注释掉即可。
10 12 * * * root cd /home/Juneway/ && python3.7 wechat.py >/home/Juneway/robot.log 2>&1 &

扫码登录成功之后,就可以开始属于你的个人微信机器人啦!!
ps:经过几天的验证,可以一直挂着,不会掉线,我怀疑那个心跳机制是假的??这还需要经过时间的验证才能下定论。

更新如下:

  • 2020-1-7
    到目前为止,我的个人微信号机器人已经在云服务器上运行了一周的时间,从未掉过线。网上很多说手机端要保持在线,我不这么认为,我晚上睡觉前手机都是开飞行模式的,早上起来也没有掉线。结论:没有心跳机制,所以放心挂在服务器上就行。

  • 2020-1-31
    到目前为止,已经正常连续运行了一个月整,总结:没有心跳机制

六、运行展示


ps:由于gif有点难弄,就只先展示处理个人消息的吧,还有哪些处理群聊啊、给文件传输助手发指令啊,那些就不一一展示了,有兴趣的自己去实践就行了哈哈


参考链接
https://www.php.cn/xiaochengxu-364486.html
https://itchat.readthedocs.io/zh/latest/
https://blog.csdn.net/enweitech/article/details/79585043

写在最后

没想到一开始从itchat教程的入门案例中,陷进去了,觉得挺好玩的,可是好景不长,就是他提供的那个图灵测试的key,竟然调用次数没有了,于是乎,便开始了属于自己的个人微信号自动回复机器人之旅,一开始也只是处理个人消息,后面就不断地加需求,才有了现在的robot1.0,其实我想实现的功能远不止这些:自动回复+监控撤回消息。其实我想到的还有:

  1. 自动回复中可以把语音识别给加进去,别人发语音也能跟他们交流;
  2. 不调用别人的接口,自己用NLP来实现一个自己的聊天机器人,让人工智障更加趋向人工智能;
  3. 退出重登,因为我看到有个参数是控制退出后会执行的函数,应该可以通过那个来实现,这个我就等看有没有心跳机制再搞吧;
  4. 实现建群拉人,找出那些删除了你的人;
  5. 通过微信机器人控制电脑,通过手机发送指令就可以操作电脑,从而实现更多的功能;
  6. 未完待续……

python实现微信自动回复机器人+查看别人撤回的消息(部署到云服务器)相关推荐

  1. python 微信自动回复机器人_python实现微信自动回复机器人+查看别人撤回的消息(部署到云服务器)...

    前言首先你的微信号能够登录网页版微信,才能打造你的专属个人微信号机器人,点击跳转网页版微信登录页面 类似的文章网上也都有,其实我也是受到别的文章的一些启发,因为不是每个人都想实现同样的功能的,直接套用 ...

  2. python 贴吧自动回复机-Python实现微信自动回复机器人详细教程

    首先,我们需要安装并配置好Python环境,并安装requests和itchat包,我用的是Windows7环境! https://www.python.org/ python官网 下载 然后直接打开 ...

  3. python 贴吧自动回复机-python实现微信自动回复机器人功能

    一 简单介绍 wxpy基于itchat,使用了 Web 微信的通讯协议,,通过大量接口优化提升了模块的易用性,并进行丰富的功能扩展.实现了微信登录.收发消息.搜索好友.数据统计等功能. 安装:wxpy ...

  4. python 贴吧自动回复机-python实现微信自动回复机器人

    一 简单介绍 wxpy基于itchat,使用了 Web 微信的通讯协议,,通过大量接口优化提升了模块的易用性,并进行丰富的功能扩展.实现了微信登录.收发消息.搜索好友.数据统计等功能. 总而言之,可用 ...

  5. Python实现微信自动回复机器人

    还记得"人人"火的时候,有个小黄鸡很有名,可以不知疲倦地和你聊上一整天,而且各种搞怪金句频出,让人欲罢不能.如今人人已经成为"人人直播-高颜值品质直播平台"了( ...

  6. Python制作微信自动回复机器人,打游戏时自动回复女友消息

    前言 自从微信网页版登录禁止后,原来的自动登录回复就失效了.接下来使用一个库PyWeChatSpy,需要pip下载 一.创建机器人 进入图灵机器人官网http://www.tuling123.com/ ...

  7. Python制作微信自动回复机器人

    文章目录 前言 一.创建机器人 二.完成代码 前言 自从微信网页版登录禁止后,原来的自动登录回复就失效了.接下来使用一个库PyWeChatSpy,需要pip下载 一.创建机器人 进入图灵机器人官网ht ...

  8. Python制作微信自动回复机器人,打游戏时自动回复女朋友消息

    大家好,我是辰哥~ 点击下方名片关注和星标『Python研究者』!

  9. 微信上想看别人撤回的消息怎么办?这个小功能或许可以帮到你

    已经记不得是从哪个版本开始,微信就有了消息撤回这个功能.本来好好的功能,但是放在特定的聊天场合,就是分分钟要逼疯处女座的节奏啊!就像这样,功能本身是为了"人无完人,每个人都会说错话,给一时的 ...

最新文章

  1. 树莓派修改密码(有单独屏幕)
  2. java web 框架整合开发_SpringBoot(二)Web整合开发
  3. [转] linux-Centos7安装python3并与python2共存
  4. 机器学习实战(用Scikit-learn和TensorFlow进行机器学习)(四)
  5. linux网络编程之用socket实现简单客户端和服务端的通信(基于TCP)
  6. 配置 aws cli_AWS CLI教程–如何安装,配置和使用AWS CLI了解您的资源环境
  7. 【AI视野·今日NLP 自然语言处理论文速览 第十五期】Fri, 25 Jun 2021
  8. Visual Studio 2010 C++ 用户属性设置
  9. Java 蓝桥杯 装箱问题
  10. Kubernentes
  11. 纯前端实现pdf分页下载,完美支持横屏竖屏
  12. 两种索引:MyISAM(非聚集索引)和InnoDB(聚集索引)的介绍
  13. 彻底卸载微软拼音输入法
  14. Android 视频直播的流程总览
  15. 武汉科技大学计算机学院研究生复试,2019年武汉科技大学硕士研究生复试及录取工作方案...
  16. 百度冰桶算法4.5更新:发力打击恶劣广告行为
  17. Android 自定义View实现照片裁剪框与照片裁剪
  18. c语言万年历一行打印两个月,万年历 c语言 两月一行
  19. 列表最后一页的最后一条数据删除之后,页码自动减一
  20. 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】Oops在Linux 2.6内核+PowerPC架构下的前世今生

热门文章

  1. 语言中的历史——汉语和突厥语的纠缠
  2. 不需编程也可实现钉钉自动打卡
  3. C++ if条件语句用法
  4. java setw_setw()函数使用
  5. c语言书面作业3,C语言程序设计
  6. 基于单片机的信号发生器设计
  7. iOS内嵌unity
  8. rk3288 MINILOADERALL生成
  9. 【翻译】Chromium 网络栈 disk cache 设计原理
  10. html页面回退,HTML5小结