美文网首页技术类文章收集大杂烩Pythonpython开发
基于itchat实现微信群消息同步机器人

基于itchat实现微信群消息同步机器人

作者: 宏伦工作室 | 来源:发表于2017-02-26 22:40 被阅读16985次

最近 全栈数据工程师养成攻略 的微信群已经将近500人,开了二群之后为了打通不同微信群之间的消息,花了点时间做了个消息同步机器人,在任意群收到消息时同步到其他群,并且将聊天内容上传至数据库,以供进一步分析、统计和展示。

基本思路是,用 Python 模拟微信网页版登陆,接收到群里消息后,对文本、图片、分享等各类消息类型分别处理,并转发至其他群。

前期准备

首先得有一个微信号,用于代码模拟登陆。由于我的微信号得自己留着用,现阶段注册微信又必须要手机号,于是只好特意办了个电信号,用来申请了一个新的微信,微信号是 honlanbot。虽说似乎可以用阿里小号来注册微信,不过听说存在反复回收和安全隐患问题,故不采用。

其次,需要用到一个Python库 itchat,这个库已经做好了用代码调用微信的大多数功能,非常好用,官方文档在这里,安装的时候使用 pip 即可。

pip install itchat

我的手机支持双卡双待,于是把两张卡都装手机里,再双开微信,同时保持两个微信号手机在线,差不多就可以开始写代码了。用 itchat 调用微信主要是模拟微信网页版登陆,所以必须保持微信号手机在线,因为手机端微信一旦退出,其在网页、PC、MAC、IPAD等相应终端认证的账号也会随之退出。

初步尝试

itchat 提供了一些官方代码,让我们在自己的本本或电脑上新建一个 py 文件,初步尝试一下。

运行以下代码,会出现出现一张二维码,扫码登陆之后将会给“文件传输助手”发送一条消息。

# 加载包
import itchat
# 登陆
itchat.auto_login()
# 发送文本消息,发送目标是“文件传输助手”
itchat.send('Hello, filehelper', toUserName='filehelper')

以下代码则注册了一个消息响应事件,用来定义接收到文本消息后如何处理。在 itchat 里可以定义文本、图片、名片、位置、通知、分享、文件等多种消息类型,从而分别执行不同的处理。

import itchat
# 注册消息响应事件,消息类型为itchat.content.TEXT,即文本消息
@itchat.msg_register(itchat.content.TEXT)
def text_reply(msg):
    # 返回同样的文本消息
    return msg['Text']

itchat.auto_login()
# 绑定消息响应事件后,让itchat运行起来,监听消息
itchat.run()

再来看看如何处理其他类型消息,可以把在消息响应事件里把 msg 打印出来,是一个字典,看看有哪些感兴趣的字段。

import itchat
# import全部消息类型
from itchat.content import *

# 处理文本类消息
# 包括文本、位置、名片、通知、分享
@itchat.msg_register([TEXT, MAP, CARD, NOTE, SHARING])
def text_reply(msg):
    # 微信里,每个用户和群聊,都使用很长的ID来区分
    # msg['FromUserName']就是发送者的ID
    # 将消息的类型和文本内容返回给发送者
    itchat.send('%s: %s' % (msg['Type'], msg['Text']), msg['FromUserName'])

# 处理多媒体类消息
# 包括图片、录音、文件、视频
@itchat.msg_register([PICTURE, RECORDING, ATTACHMENT, VIDEO])
def download_files(msg):
    # msg['Text']是一个文件下载函数
    # 传入文件名,将文件下载下来
    msg['Text'](msg['FileName'])
    # 把下载好的文件再发回给发送者
    return '@%s@%s' % ({'Picture': 'img', 'Video': 'vid'}.get(msg['Type'], 'fil'), msg['FileName'])

# 处理好友添加请求
@itchat.msg_register(FRIENDS)
def add_friend(msg):
    # 该操作会自动将新好友的消息录入,不需要重载通讯录
    itchat.add_friend(**msg['Text']) 
    # 加完好友后,给好友打个招呼
    itchat.send_msg('Nice to meet you!', msg['RecommendInfo']['UserName'])

# 处理群聊消息
@itchat.msg_register(TEXT, isGroupChat=True)
def text_reply(msg):
    if msg['isAt']:
        itchat.send(u'@%s\u2005I received: %s' % (msg['ActualNickName'], msg['Content']), msg['FromUserName'])

# 在auto_login()里面提供一个True,即hotReload=True
# 即可保留登陆状态
# 即使程序关闭,一定时间内重新开启也可以不用重新扫码
itchat.auto_login(True)
itchat.run()

开发消息同步机器人

经过以上示例代码,可以总结出消息同步机器人的开发思路:

  • 登陆后使用get_chatrooms()获取全部群聊的数据,包括每个群聊的ID和昵称,可以将需要同步消息的群聊保存至通讯录;
  • 接收到群聊消息时,如果消息来自于需要同步消息的群聊,就根据消息类型进行处理,同时转发到其他需要同步的群聊。

直接上代码好了,首先定义一个消息响应函数,文本类消息我感兴趣的是 TEXTSHARING 两类,使用 isGroupChat=True 指定消息来自于群聊,这个参数默认为 False

# 自动回复文本等类别的群聊消息
# isGroupChat=True表示为群聊消息
@itchat.msg_register([TEXT, SHARING], isGroupChat=True)
def group_reply_text(msg):
    # 消息来自于哪个群聊
    chatroom_id = msg['FromUserName']
    # 发送者的昵称
    username = msg['ActualNickName']

    # 消息并不是来自于需要同步的群
    if not chatroom_id in chatroom_ids:
        return

    if msg['Type'] == TEXT:
        content = msg['Content']
    elif msg['Type'] == SHARING:
        content = msg['Text']

    # 根据消息类型转发至其他群
    if msg['Type'] == TEXT:
        for item in chatrooms:
            if not item['UserName'] == chatroom_id:
                itchat.send('%s\n%s' % (username, msg['Content']), item['UserName'])
    elif msg['Type'] == SHARING:
        for item in chatrooms:
            if not item['UserName'] == chatroom_id:
                itchat.send('%s\n%s\n%s' % (username, msg['Text'], msg['Url']), item['UserName'])

再来处理下图片等多媒体类消息。

# 自动回复图片等类别的群聊消息
# isGroupChat=True表示为群聊消息          
@itchat.msg_register([PICTURE, ATTACHMENT, VIDEO], isGroupChat=True)
def group_reply_media(msg):
    # 消息来自于哪个群聊
    chatroom_id = msg['FromUserName']
    # 发送者的昵称
    username = msg['ActualNickName']

    # 消息并不是来自于需要同步的群
    if not chatroom_id in chatroom_ids:
        return

    # 如果为gif图片则不转发
    if msg['FileName'][-4:] == '.gif':
        return

    # 下载图片等文件
    msg['Text'](msg['FileName'])
    # 转发至其他需要同步消息的群聊
    for item in chatrooms:
        if not item['UserName'] == chatroom_id:
            itchat.send('@%s@%s' % ({'Picture': 'img', 'Video': 'vid'}.get(msg['Type'], 'fil'), msg['FileName']), item['UserName'])

以上代码实现了对文本、分享、图片、视频四类消息的处理,如果对其他类型的消息也感兴趣,进行相应的处理即可。在前面补上 import 的代码,在后面补上登陆、获取群聊数据和开始监测的代码,就大功告成了。

完整代码在这里:https://pan.baidu.com/s/1bpAJk0B

成果展示

目前两个群之间可以进行消息同步了,一群和二群的小伙伴终于可以畅快地聊了起来(当群主不容易,经常要发很多红包 = =)。

进一步工作

当然,我不可能一直在笔记本上运行这么个 py 代码,所以把它部署到服务器上运行就好了,开个 screen 或者用 IPython 都可以。如果账号偶尔下线了,再运行一下就好。

另外,我还写了个 API,响应消息的时候会把相应的数据 POST 到我的服务器并存到数据库,以供进一步的分析、统计和展示,这也是我身为一个群主应尽的职责~

相关文章

网友评论

  • dc35b4ffd46c:大佬,为啥我想艾特群里某人总是不成功呢?因为我是自发艾特所以不能用msg事件,添加了'\u2005'+群昵称也没有用,用[actualusername]字段又获取不到.头疼呜呜呜
  • GroomLake:楼主:我想问下,我用自己的微信号开发的图灵机器人,在群聊中,我发消息可以接受到机器人会的消息,为啥其他群成员不能够和机器人聊天,望解答
  • TcAlan:在微信群里 如何实现@机器人的消息 机器人才处理 其他消息不做处理
    d00dee6a6601:msg['isAt'] # 是否@本号
  • 天河韬奋:10行代码实现微信群消息同步(wxpy)
    https://www.jianshu.com/p/62bdfacc6e36
  • 05f3df1b9e63:楼主,我有个想法,不知道能不能实现,麻烦帮从技术可行性方面给予分析一下:在一些微信群里安置一个微信机器人(或者就是一对一的聊天),保存所有的聊天记录,并根据聊天关键字自动提供相应的信息,比如群里某人说想看看简书系统的资源使用情况,机器人就直接回复简书服务器的信息,有@机器人的,就直接解析语义,初步想法是用开源的jieba做分词,后端用开源的errbot机器人去提取相应的信息(具体提供的信息另行写插件完成),不知道以上能否实现?或有没有更好的方法?
    宏伦工作室:技术上都是可行的,问题在于现在腾讯经常封号,导致web微信登陆不了,所以itchat、wxpy之类的不好用了
  • 7f9ce92128b0:\u2005是什么意思
  • acd24d14dafa:大佬,你这个微信号不会被封web吗?我用itchat几天就被封了web。。。。
  • 硅谷少年:感谢,根据你上文中“成果展示”上面那行地址下载的代码,我改了一下达到了预想的效果。原来是向所有群同步消息,坑我一次,工作群全问我怎么了。。。改了一下,只有在我指定的群之间再同步消息,就OK了。只有除自己以外的人发的消息才会被正常同步。
  • 2111176cda0d:大神,我参考了你的代码,怎么转化成python3来使用呢,我是希望从一个群获取的聊天记录能够被导出成txt
    宏伦工作室:@MrLiu_fa54 每次收到消息,写到txt就行啦
  • 扬沙沙:厉害👍
  • 宏伦工作室:文章已更新,登陆后使用 get_chatrooms() 获取需要同步消息的群聊数据,包括群聊的 ID 和昵称,便于后续同步消息。
    宏伦工作室:@泉水_8b2d 现在腾讯封得厉害,之前是账号异常就限制登陆Web微信,现在是直接新注册的账号都不能登陆Web微信
    dec5c51bb572:现在用这个登录,会不会被封了,不让你用微信网页版登呢
    b7defe39e0b6:源码已经不能下载了
  • 5d862e3d6f4f:按这上边弄个微信群同步助手,用itchat的getchatroom那个函数,能取到微信群id和微信群名,但用监听群聊的函数,从msg中取到的微信群id又变了。请问网盘中的源码怎么得到微信群名?
  • 师爷快上:你好,我想问一下,这个itchat可以做到聊天过程中接受到的图片自动下载吗?就是跟朋友通过微信聊天,网友在聊天窗口给我发来一些图片,这个程序可以帮我做到自动把朋友发过来的图片保存到指定电脑的指定目录?
  • 吃饱的疯子:楼主有没有遇到自动掉线的问题, log out 几乎每隔24小时掉线一次。求解决。
  • 宏伦工作室:这是我目前用的py代码,如果在笔记本上测试,直接python运行就可以了。注意,收到任何群的第一条消息都会记录该群,并转发到其他全部已经记录的群中,所以最好用小号测试,不然用自己的微信号肯定要各种乱发消息了。
    链接: https://pan.baidu.com/s/1o8NQ0MQ 密码: kq4i,这是我目前用的,功能还比较简单
    5d862e3d6f4f:@宏伦工作室 代码中没法取到微信群名?
    578074e45ef1:我想直接发消息到某个群,请问itchat能实现吗
  • 4a1de2a86fba:msg['FromUserName'] 就是群聊的ID不断在变化如何处理?
    578074e45ef1:您好,请问能直接实现给发送文件给群吗
    宏伦工作室:@米饭_b687 我也发现这个问题了。后来我就在代码里把groups设为空,每次运行时我的大号会在群里说一声,“一群机器人激活”之类的消息,这样机器人就知道这个id是哪个群了。后来觉得每次这样在群里念咒有点二,就干脆取消了群的标记,收到任何群的消息都全部转发到其他群,当然每次收到消息,如果这个群还没有记录,就加到groups里。这样我在重新运行代码之后,只要往群里分享一篇文章,这个群就被机器人记住了,加到转发的目标里,这样比较低调……
  • d6be41ae940e:开个 screen 或者用 IPython 都可以。
    哈咯,这句话没大理解,为什么是或者呢?他们两个之间的关系是并集?
    screen不是一个类似xshell的终端管理软件么?跟ipython有啥关系
    d6be41ae940e:@宏伦工作室 soga,我就说
    宏伦工作室:@童话at 这两个完全没关系啦,不过都可以在服务器上一直运行python代码。用screen重新开一个终端,这样断开服务器连接程序也不会断;ipython运行代码之后,只要不shutdown,notebook也会一直运行。
  • f1a3bd5c6b0c:如何部署到服务器啊:disappointed_relieved:
  • CrazySteven:照你这个写的,我发送语音的时候报错,而且是错误在库里。。。难道库升级更新了?
  • CrazySteven:这个不错。。。
  • 6bf4671977ce:厉害,楼主放到github了没有
    b7defe39e0b6:已经取消共享了。。
    宏伦工作室:@噢瑞利 不用放到github哇,完整实现都在文章里了
  • 向右奔跑:这个牛,正需要~
  • justZero:前排~在群里基本不说话😄

本文标题:基于itchat实现微信群消息同步机器人

本文链接:https://www.haomeiwen.com/subject/bbuawttx.html