本文简介html
很久没更新文章啦,由于最近在赶一本Py的入门书,碰巧今天把这篇文章赶出来了。 而不少加群的小朋友不少都是咨询如何搭建微信机器人的,因此就把这一章放出来了, 取需,三个实用示例:定时发信息,集成图灵API实现聊天机器人,微信防撤回实现,基本够玩了。 另外,微信改版了网页端,不少接口都开始用不了,好比拉人进群,能够经过无障碍服务或者 Xposed来解决,具体怎么玩能够参见前面的章节,谢谢。git
2011年1月21日,微信推出第一个正式版本,到如今已有7个年头。从一开始的不被看到好,到如今的用户量超10亿,大众的平常生活愈来愈离不开微信。人生苦短我用Python,有没有办法经过Python来对咱们使用微信提供一些便利呢? 答案确定是有的,在Github上有一个基于微信网页版接口微信开源库:itchat,经过几十行的代码就能轻松实现一个微信机器人。本章咱们就来了解学习这个库,而后经过三个实用案例来帮你们玩转这个库。github
咱们跟着文档来解读下itchat这个库的用法。web
itchat的仓库地址:github.com/littlecoder… 官方文档:itchat.readthedocs.iojson
安装也很简单,直接经过pip命令安装便可,命令以下:api
pip install itchat
复制代码
经过一个简单的例子来让读者体会下经过itchat编写一个微信机器人有多简单,代码功能: 扫码登陆后给文件助手发送一条信息,监听接收到的文件信息,打印出来,具体代码以下。缓存
import itchat
import time
@itchat.msg_register(itchat.content.TEXT)
def reply_msg(msg):
print("收到一条信息:",msg.text)
if __name__ == '__main__':
itchat.auto_login()
time.sleep(5)
itchat.send("文件助手你好哦", toUserName="filehelper")
itchat.run()
复制代码
代码执行结果:bash
先会弹出一个二维码图片,扫描后会登录网页端微信,间隔一下子后文件助手收到如图19.1所示的信息服务器
图19.1 文件传输助手收到信息微信
而后用另外一个帐号发送一条信息给这个帐号,控制台会把接收到的信息打印出来
Getting uuid of QR code.
Downloading QR code.
Please scan the QR code to log in.
Please press confirm on your phone.
Loading the contact, this may take a little while.
TERM environment variable not set.
Login successfully as Robot Pig
Start auto replying.
收到一条信息: 你好
复制代码
经过上面8行有效代码就实现了一个简单的技巧人,酷不酷,带着这样的思路,咱们能够进行扩展,好比添加一个自动回复的功能,好比在忙的时候,别人给你发信息,自动回复:"在忙,晚点给你回复信息"等。
在学习itchat的详细用法前,先和读者说一些要注意的东西。
(1)itchat不是微信官方提供的库,意味使用这个库会有风险,笔者的小号就曾被微信封过一段时间,禁止网页端登陆微信,移动端和电脑客户端仍是能正常使用的,微信此举旨在封杀泛滥的微商机器人。 (2)如何减小被封几率:消息发送不要过于频繁;不要发送过多重复信息;尽可能少调用加人的接口; (3)被封如何解封:被封后是没法找到申述入口,只能随缘解封,笔者在坚持了一周用手机聊天和朋友圈点赞留言后忽然就解封了。 (4)微信正在慢慢收窄网页端的功能,意味着一些接口会慢慢失效,好比说拉人进群聊的接口,之前还能用,如今就不行了。在调用某个接口没有获得意料中的结果,可能就是接口失效了,能够到官方仓库查找相关的issues。 (5)微信只支持双端登陆,不使用黑科技的话,移动端加上Web网页端或PC客户端。 (6)新注册的微信号是没法使用网页版登陆的。
最后,仍是要感谢开源做者的无私奉献。
巧妇难为无米之炊,在扩展前先跟笔者把文档过一过,理解得差很少了,再开始去扩展,这样效率会高不少。
登录时经过itchat.auto_login()这个函数来完成的,不带参数的话会生成一个二维码图片文件供你扫描登录。通常的话咱们的电脑都会关机,若是机器人有须要持久在线的需求,咱们能够把脚本挂到服务器上,24小时跑,可是通常的云服务器是没有界面的,都是经过终端命令行进行操做,这个时候能够添加enableCmdQR=True参数,让二维码显示到命令行上,另外部分系统可能字符宽度有出入,如图19.2所示,能够经过把enableCmdQR赋值为特定的倍数进行调整。
图19.2 命令行二维码错位
好比enableCmdQR=2后,二维码图片如图19.3所示
图19.3 调整后正常的二维码图片
扫码登陆后,若是想退出程序之后还暂存登陆状态,从新执行程序也不用扫码能够添加参数hotReload=True。
若是在启动时没有设置hotReload=True参数,程序退出后过一下子就会自动掉线的了,若是想快速退出的话能够调用**itchat.logout()**注销登陆状态。另外,有时咱们可能想在登陆成功或者注销登陆后执行一些操做,能够添加两个调用登陆时传入两个方法参数loginCallback和exitCallback,简单示例以下:
import itchat
import time
def after_login():
print("登陆后调用")
def after_logout():
print("退出后调用")
if __name__ == '__main__':
itchat.auto_login(loginCallback=after_login, exitCallback=after_logout)
time.sleep(5)
itchat.logout()
复制代码
代码执行结果以下:
Getting uuid of QR code.
Downloading QR code.
Please scan the QR code to log in.
Please press confirm on your phone.
Loading the contact, this may take a little while.
登陆后调用
退出后调用
复制代码
itchat提供四种查找用户的搜索方式,
(1)获取本身的用户信息 示例以下:
# 获取本身的用户信息,返回本身的属性字典
result = itchat.search_friends()
print(result)
复制代码
代码执行结果以下:
{'MemberList': <ContactList: []>, 'UserName': '@299f59697878267efb48e8cad07xxxxcadd0efbb63xxxxxxx0964c51f028e8474', 'City': '', 'DisplayName': '', 'PYQuanPin': '', 'RemarkPYInitial': '', 'Province': '', 'KeyWord': '', 'RemarkName': '', 'PYInitial': '', 'EncryChatRoomId': '', 'Alias': '', 'Signature': '(´v`o)♡', 'NickName': 'Robot Pig', 'RemarkPYQuanPin': '', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=1663312400&username=@299f59697878267efb48e8cad07f5f1cadd0efbb63ae19610964c51f028e8474&skey=@crypt_2d4a1972_5e7829c893346a53135fb03affa39f9c', 'UniFriend': 0, 'Sex': 2, 'AppAccountFlag': 0, 'VerifyFlag': 0, 'ChatRoomId': 0, 'HideInputBarFlag': 0, 'AttrStatus': 0, 'SnsFlag': 1, 'MemberCount': 0, 'OwnerUin': 0, 'ContactFlag': 0, 'Uin': 3454488193, 'StarFriend': 0, 'Statues': 0, 'WebWxPluginSwitch': 0, 'HeadImgFlag': 1}
复制代码
(2)根据昵称查询某个用户,代码示例以下:
# 根据姓名查找用户
result = itchat.search_friends(name='培杰')
print(result)
复制代码
代码执行结果以下:
[<User: {'MemberList': <ContactList: []>, 'Uin': 0, 'UserName': '@xxb096c3036543exx2d4de4fc222xxxx', 'NickName': '培杰', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=625711027&username=@40b096c3036543e5b2d4de4fc22208ed&skey=@crypt_2d4a1972_ac0122b1740b332921afc9f2fffa546f', 'ContactFlag': 3, 'MemberCount': 0, 'RemarkName': '', 'HideInputBarFlag': 0, 'Sex': 1, 'Signature': 'Expectation is the root of all heartache.', 'VerifyFlag': 0, 'OwnerUin': 0, 'PYInitial': 'PJ', 'PYQuanPin': 'peijie', 'RemarkPYInitial': '', 'RemarkPYQuanPin': '', 'StarFriend': 0, 'AppAccountFlag': 0, 'Statues': 0, 'AttrStatus': 33783847, 'Province': '广东', 'City': '江门', 'Alias': '', 'SnsFlag': 17, 'UniFriend': 0, 'DisplayName': '', 'ChatRoomId': 0, 'KeyWord': 'zpj', 'EncryChatRoomId': '', 'IsOwner': 0}>]
复制代码
(3)根据微信号查找用户,代码示例以下:
# 根据微信号查找用户
result = itchat.search_friends(wechatAccount='zpj779878443')
print(result)
复制代码
代码执行结果以下:
[<User: {'MemberList': <ContactList: []>, 'Uin': 0, 'UserName': '@xxb096c3036543exx2d4de4fc222xxxx', 'NickName': '培杰', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=625711027&username=@40b096c3036543e5b2d4de4fc22208ed&skey=@crypt_2d4a1972_ac0122b1740b332921afc9f2fffa546f', 'ContactFlag': 3, 'MemberCount': 0, 'RemarkName': '', 'HideInputBarFlag': 0, 'Sex': 1, 'Signature': 'Expectation is the root of all heartache.', 'VerifyFlag': 0, 'OwnerUin': 0, 'PYInitial': 'PJ', 'PYQuanPin': 'peijie', 'RemarkPYInitial': '', 'RemarkPYQuanPin': '', 'StarFriend': 0, 'AppAccountFlag': 0, 'Statues': 0, 'AttrStatus': 33783847, 'Province': '广东', 'City': '江门', 'Alias': '', 'SnsFlag': 17, 'UniFriend': 0, 'DisplayName': '', 'ChatRoomId': 0, 'KeyWord': 'zpj', 'EncryChatRoomId': '', 'IsOwner': 0}>]
复制代码
另外,2和3功能能够同时使用,好比itchat.search_friends(name='培杰', wechatAccount='zpj779878443')
(4)根据UserName查找用户,就是上面返回结果里跟着的UserName字段,@xxxx这样一串东西,代码示例以下:
# 根据UserName查找用户
result = itchat.search_friends(userName='@xxb096c3036543exx2d4de4fc222xxxx')
print(result)
复制代码
代码执行结果以下:
[<User: {'MemberList': <ContactList: []>, 'Uin': 0, 'UserName': '@xxb096c3036543exx2d4de4fc222xxxx', 'NickName': '培杰', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=625711027&username=@xxb096c3036543exx2d4de4fc222xxxx&skey=@crypt_2d4a1972_ac0122b1740b332921afc9f2fffa546f', 'ContactFlag': 3, 'MemberCount': 0, 'RemarkName': '', 'HideInputBarFlag': 0, 'Sex': 1, 'Signature': 'Expectation is the root of all heartache.', 'VerifyFlag': 0, 'OwnerUin': 0, 'PYInitial': 'PJ', 'PYQuanPin': 'peijie', 'RemarkPYInitial': '', 'RemarkPYQuanPin': '', 'StarFriend': 0, 'AppAccountFlag': 0, 'Statues': 0, 'AttrStatus': 33783847, 'Province': '广东', 'City': '江门', 'Alias': '', 'SnsFlag': 17, 'UniFriend': 0, 'DisplayName': '', 'ChatRoomId': 0, 'KeyWord': 'zpj', 'EncryChatRoomId': '', 'IsOwner': 0}>]
复制代码
itchat提供了几个发送不一样类型信息的函数,没有发送语音的缘由是网页版没有这个接口,可供调用 的函数如表19.1所示。
函数名 | 做用 |
---|---|
send_msg() | 发送文字信息 |
send_file() | 发送文件 |
send_video() | 发送视频 |
send_image() | 发送图片 |
使用代码示例以下:
import itchat
import time
def after():
user_info = itchat.search_friends(name='培杰')
if len(user_info) > 0:
# 拿到用户名
user_name = user_info[0]['UserName']
# 发送文字信息
itchat.send_msg('培杰你好啊!', user_name)
# 发送图片
time.sleep(10)
itchat.send_image('cat.jpg', user_name)
# 发送文件
time.sleep(10)
itchat.send_file('19_2.py', user_name)
# 发送视频
time.sleep(10)
itchat.send_video('sport.mp4', user_name)
if __name__ == '__main__':
itchat.auto_login(loginCallback=after)
itchat.run()
复制代码
代码执行结果以下:
除了主动发送信息外,还能够对信息进行监控,支持对多种类型的信息进行监控,类型如表19.2所示。 另外,有多个注册信息监听,后注册的信息优先级高于先注册信息,带参数信息高于不带参数信息。
信息类型 | 解释 |
---|---|
itchat.content.TEXT | 文本内容 |
itchat.content.MAP | 位置文本 |
itchat.content.Card | 名片 |
itchat.content.Note | 通知文本 |
itchat.content.Sharing | 分享名称 |
itchat.content.RECORDING | 录音 |
itchat.PICTURE | 图片/表情 |
itchat.content.VOICE | 录音 |
itchat.content.ATTACHMENT | 附件 |
itchat.content.VIDEO | 短视频 |
itchat.content.FRIENDS | 好友邀请 |
itchat.content.SYSTEM | 系统信息 |
一个监听到文字信息并响应信息的代码示例以下:
import itchat
@itchat.msg_register(itchat.content.TEXT)
def reply_msg(msg):
if msg['Content'] == u'你好':
itchat.send_msg(msg['User']['NickName'] + "你好啊!", msg['FromUserName'])
if __name__ == '__main__':
itchat.auto_login()
itchat.run()
复制代码
代码执行结果以下:
在微信网页端改版后,建立群聊、拉人进群和删除群聊这几个接口都用不了,如今利用itchat能作的有:查找群聊,往群聊发送信息,以及监控群聊信息,使用代码示例以下:
import itchat
import time
@itchat.msg_register(itchat.content.TEXT, isGroupChat=True)
def reply_msg(msg):
print("收到一条群信息:", msg['ActualNickName'], msg['Content'])
def after_login():
# 得到完整的群聊列表
print("完整的群聊列表以下:")
print(itchat.get_chatrooms())
# 查找特定群聊
time.sleep(10)
# 经过群聊名查找
chat_rooms = itchat.search_chatrooms(name='小猪的Python学习交流群')
if len(chat_rooms) > 0:
itchat.send_msg('测试', chat_rooms[0]['UserName'])
if __name__ == '__main__':
itchat.auto_login(loginCallback=after_login)
itchat.run()
复制代码
代码执行结果以下:
完整的群聊列表以下:
[<Chatroom: {'MemberList': <ContactList: []>, 'Uin': 0, 'UserName': '@@60dc5027bbbb83d532aa633b8d126szcf497a98ceea5c098d2c65f0932139b88', 'NickName': '湖北人在深圳90后', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgetheadimg?seq=625714901&username=@@60dc502769a783d532aa633b8d126190f497a98ceea5c098d2c65f0932139b88&skey=@crypt_2d4a1972_ea00536c8ac4e35fae1c2a1c48dfe40d', 'ContactFlag': 3, 'MemberCount': 82, 'RemarkName': '', 'HideInputBarFlag': 0, 'Sex': 0, 'Signature': '', 'VerifyFlag': 0, 'OwnerUin': 0, 'PYInitial': 'HBRZSZ90H', 'PYQuanPin': 'hubeirenzaishenzhen90hou', 'RemarkPYInitial': '', 'RemarkPYQuanPin': '', 'StarFriend': 0, 'AppAccountFlag': 0, 'Statues': 0, 'AttrStatus': 0, 'Province': '', 'City': '', 'Alias': '', 'SnsFlag': 0, 'UniFriend': 0, 'DisplayName': '', 'ChatRoomId': 0, 'KeyWord': '', 'EncryChatRoomId': '', 'IsOwner': 0, 'IsAdmin': None, 'Self': <User: {'MemberList': <ContactList: []>, 'UserName': '@29b9cb6386352503319f411754e7424e383ae09e50a224feca754a4516db6a13', 'City': '', 'DisplayName': '', 'PYQuanPin': '', 'RemarkPYInitial': '', 'Province': '', 'KeyWord': '', 'RemarkName': '', 'PYInitial': '', 'EncryChatRoomId': '', 'Alias': '', 'Signature': '(´v`o)♡', 'NickName': 'Robot Pig', 'RemarkPYQuanPin': '', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=275167114&username=@29b9cb6386352503319f411754e7424e383ae09e50a224feca754a4516db6a13&skey=@crypt_2d4a1972_ea00536c8ac4e35fae1c2a1c48dfe40d', 'UniFriend': 0, 'Sex': 2, 'AppAccountFlag': 0, 'VerifyFlag': 0, 'ChatRoomId': 0, 'HideInputBarFlag': 0, 'AttrStatus': 0, 'SnsFlag': 1, 'MemberCount': 0, 'OwnerUin': 0, 'ContactFlag': 0, 'Uin': 3454488193, 'StarFriend': 0, 'Statues': 0, 'WebWxPluginSwitch': 0, 'HeadImgFlag': 1}>}> 内容过多省略... ]
收到一条群信息: 培杰 123
收到一条群信息: 培杰 你好
复制代码
聊天记录截图:
另外,群聊除了经过群名搜索外还能够经过username来查找,或者二者搭配使用; 在msg里有一个isAt字段,可用于判断是否被人@了。
使用方式和群聊的很是相似,搜索公众号方法search_mps,监听公众号信息添加isMpChat=True元素,使用代码示例以下:
import itchat
@itchat.msg_register(itchat.content.TEXT, isMpChat=True)
def reply_msg(msg):
print("收到一条公众号信息:", msg['User']['NickName'], msg['Content'])
def login_after():
mps = itchat.search_mps(name='CoderPig')
if len(mps) > 0:
print(mps)
itchat.send_msg('人生苦短', toUserName=mps[0]['UserName'])
if __name__ == '__main__':
itchat.auto_login(loginCallback=login_after)
itchat.run()
复制代码
代码执行结果以下:
[<MassivePlatform: {'MemberList': <ContactList: []>, 'Uin': 0, 'UserName': '@07585e92f75be7320e49627cf0c3ad43', 'NickName': 'CoderPig', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=610904174&username=@07585e92f75be7320e49627cf0c3ad43&skey=@crypt_2d4a1972_bc443bf966f94fa11f2db8f812e456cf', 'ContactFlag': 3, 'MemberCount': 0, 'RemarkName': '', 'HideInputBarFlag': 0, 'Sex': 0, 'Signature': '一枚咸鱼Android开发,会点Python,分享点学习经验,总结,鸡汤,读书笔记,生活技巧', 'VerifyFlag': 8, 'OwnerUin': 0, 'PYInitial': 'CODERPIG', 'PYQuanPin': 'CoderPig', 'RemarkPYInitial': '', 'RemarkPYQuanPin': '', 'StarFriend': 0, 'AppAccountFlag': 0, 'Statues': 0, 'AttrStatus': 0, 'Province': '广东', 'City': '深圳', 'Alias': '', 'SnsFlag': 0, 'UniFriend': 0, 'DisplayName': '', 'ChatRoomId': 0, 'KeyWord': 'gh_', 'EncryChatRoomId': '', 'IsOwner': 0}>]
收到一条公众号信息: CoderPig 我用Python
复制代码
聊天记录截图:
定时发送信息这个操做在平常生活中很是实用,好比给别人发生日或者节日祝福,晚上12点准时发,若是有早睡习惯的要熬到12点就很难受了,咱们能够利用itchat编写一个简单的定时发送信息脚本。这里咱们用到一个apscheduler定时调度任务模块,在命令行键入pip install apscheduler便可完成安装。这里并不会详细讲解,有兴趣的可移步到官方文档自行查阅: apscheduler.readthedocs.io/en/latest/u… 定时发送消息的代码示例以下:
import itchat
from apscheduler.schedulers.blocking import BlockingScheduler
import time
# 发送信息
def send_msg():
user_info = itchat.search_friends(name='培杰')
if len(user_info) > 0:
user_name = user_info[0]['UserName']
itchat.send_msg('生日快乐哦!', toUserName=user_name)
def after_login():
sched.add_job(send_msg, 'cron', year=2018, month=7, day=28, hour=16, minute=5, second=30)
sched.start()
def after_logout():
sched.shutdown()
if __name__ == '__main__':
sched = BlockingScheduler()
itchat.auto_login(loginCallback=after_login, exitCallback=after_login)
itchat.run()
复制代码
代码执行结果以下:
图灵机器人官网:http://www.tuling123.com/member/robot/index.jhtml 注册一个帐号后,点击建立机器人,会弹出如图所示的面板,按需配置下便可。
普通帐户能够建立5个机器人,天天有5000次的免费调用机会。点击新建立好的机器人, 会进入如图所示的界面,咱们只须要保存下apikey,调用接口用的秘钥。
点击底下的api使用文档,或者直接打开 https://www.kancloud.cn/turing/web_api/522992,进入接口文档页,在这里咱们能够看到接口调用相关的信息,包括接口地址:http://openapi.tuling123.com/openapi/api/v2,请求方式:POST,请求数据格式:JSON,请求数据示例:
{
"reqType":0,
"perception": {
"inputText": {
"text": "附近的酒店"
},
"inputImage": {
"url": "imageUrl"
},
"selfInfo": {
"location": {
"city": "北京",
"province": "北京",
"street": "信息路"
}
}
},
"userInfo": {
"apiKey": "",
"userId": ""
}
}
复制代码
咱们能够利用Postman模拟下请求,试试接口是否可用,先设下请求头:
Content-Type:application/json
Host:openapi.tuling123.com
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3486.0 Safari/537.36
复制代码
接着是提交数据:
{
"reqType":0,
"perception": {
"inputText": {
"text": "你好"
}
},
"userInfo": {
"apiKey": "7e9377d760274b3499f6dec8eed37bbb",
"userId": "123"
}
}
复制代码
看下返回结果:
{
"emotion": {
"robotEmotion": {
"a": 0,
"d": 0,
"emotionId": 0,
"p": 0
},
"userEmotion": {
"a": 0,
"d": 0,
"emotionId": 0,
"p": 0
}
},
"intent": {
"actionName": "",
"code": 10004,
"intentName": ""
},
"results": [
{
"groupType": 1,
"resultType": "text",
"values": {
"text": "我很好,你也要好好的"
}
}
]
}
复制代码
返回结果里的text明显就是咱们想要的东西,整个过程了解了,接着咱们来编写代码,流程以下:
(1)监听微信信息。 (2)接收到信息,获取信息内容。 (3)调用接口,获取请求结果,提取返回的text。 (4)把提取到的text返回给发送信息的人。
具体代码实现以下:
import itchat
import requests as rq
@itchat.msg_register(itchat.content.TEXT)
def reply_msg(msg):
info = msg['Content'].encode('utf8')
# 图灵API接口
api_url = 'http://openapi.tuling123.com/openapi/api/v2'
# 接口请求数据
data = {
"reqType": 0,
"perception": {
"inputText": {
"text": str(info)
}
},
"userInfo": {
"apiKey": "7e9377d76fc7ee9499f6dec8eed37bbb",
"userId": "123"
}
}
headers = {
'Content-Type': 'application/json',
'Host': 'openapi.tuling123.com',
'User-Agent': 'Mozilla/5.0 (Wi`ndows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3486.0 '
'Safari/537.36 '
}
# 请求接口
result = rq.post(api_url, headers=headers, json=data).json()
# 提取text,发送给发信息的人
itchat.send_msg(result['results'][0]['values']['text'], msg['FromUserName'])
print()
if __name__ == '__main__':
itchat.auto_login()
itchat.run()
复制代码
代码执行结果以下图所示:
上面的图灵机器人有时回答得牛头不对马嘴,特别是在多轮问答的时候,闲聊玩玩仍是不错的。 接着的咱们要利用itchat来编写一个微信信息防撤回的脚本。当监控到用户或者群聊发送信息 撤回的话,把撤回的内容经过文件传输助手发送给咱们,说下大致的思路流程。
(1)监听全部聊天记录,包括群聊,把信息都存入到一个字典里,资源类文件下载到本地。 (2)监听到撤回信息后,根据撤回的信息id,查找字典里对应的信息,发送给文件助手。 (3)每隔五分钟清理缓存数据。
流程看上去是挺简单,接着咱们一点点来摸索实现。
先是监控信息,信息又分为好友聊天和群聊,咱们编写代码来监控下收到的数据是怎么样的?
import itchat
from itchat.content import *
# 好友信息监听
@itchat.msg_register([TEXT, PICTURE, RECORDING, ATTACHMENT, VIDEO], isFriendChat=True)
def handle_friend_msg(msg):
print("好友信息: ", msg)
# 群聊信息监听
@itchat.msg_register([TEXT, PICTURE, RECORDING, ATTACHMENT, VIDEO], isGroupChat=True)
def information(msg):
print("群聊信息: ", msg)
if __name__ == '__main__':
itchat.auto_login()
itchat.run()
复制代码
给机器人发送一条信息,还有往群聊里发送一条信息,查看打印的信息内容,先是好友信息
好友信息: {'MsgId': '5500935424291030814', 'FromUserName': '@8fd8b5b2bd0862ed5d0d573bc6c08362', 'ToUserName': '@913c3124d973db6ae25924bd0598b48a0028e0c2d01e18d8095cc6fd58db116b', 'MsgType': 1, 'Content': '123', 'Status': 3, 'ImgStatus': 1, 'CreateTime': 1533010285, 'VoiceLength': 0, 'PlayLength': 0, 'FileName': '', 'FileSize': '', 'MediaId': '', 'Url': '', 'AppMsgType': 0, 'StatusNotifyCode': 0, 'StatusNotifyUserName': '', 'RecommendInfo': {'UserName': '', 'NickName': '', 'QQNum': 0, 'Province': '', 'City': '', 'Content': '', 'Signature': '', 'Alias': '', 'Scene': 0, 'VerifyFlag': 0, 'AttrStatus': 0, 'Sex': 0, 'Ticket': '', 'OpCode': 0}, 'ForwardFlag': 0, 'AppInfo': {'AppID': '', 'Type': 0}, 'HasProductId': 0, 'Ticket': '', 'ImgHeight': 0, 'ImgWidth': 0, 'SubMsgType': 0, 'NewMsgId': 5500935424291030814, 'OriContent': '', 'EncryFileName': '', 'User': <User: {'MemberList': <ContactList: []>, 'Uin': 0, 'UserName': '@8fd8b5b2bd0862ed5d0d573bc6c08362', 'NickName': 'CoderPig', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=625711027&username=@8fd8b5b2bd0862ed5d0d573bc6c08362&skey=@crypt_2d4a1972_26dc3be99a177455b82518b3ca6e6cc5', 'ContactFlag': 3, 'MemberCount': 0, 'RemarkName': '', 'HideInputBarFlag': 0, 'Sex': 1, 'Signature': '不服气,就用行动去证实,少说多作...2018.7.29', 'VerifyFlag': 0, 'OwnerUin': 0, 'PYInitial': 'CODERPIG', 'PYQuanPin': 'CoderPig', 'RemarkPYInitial': '', 'RemarkPYQuanPin': '', 'StarFriend': 0, 'AppAccountFlag': 0, 'Statues': 0, 'AttrStatus': 33783847, 'Province': '广东', 'City': '江门', 'Alias': '', 'SnsFlag': 17, 'UniFriend': 0, 'DisplayName': '', 'ChatRoomId': 0, 'KeyWord': 'zpj', 'EncryChatRoomId': '', 'IsOwner': 0}>, 'Type': 'Text', 'Text': '123'}
复制代码
分析下要采集的数据,MsgId(微信信息的标识,用来做为键),NickName(发送者的用户名),Content(信息内容),CreateTime(建立时间), Type(信息类型)。接着是群聊信息:
群聊信息: {'MsgId': '3177606925001563512', 'FromUserName': '@@16521484d35b2fe9c953282d98ec4f11456607924b3a7cc6d7fb671fe7e3081c', 'ToUserName': '@913c3124d973db6ae25924bd0598b48a0028e0c2d01e18d8095cc6fd58db116b', 'MsgType': 1, 'Content': '嘿嘿', 'Status': 3, 'ImgStatus': 1, 'CreateTime': 1533010298, 'VoiceLength': 0, 'PlayLength': 0, 'FileName': '', 'FileSize': '', 'MediaId': '', 'Url': '', 'AppMsgType': 0, 'StatusNotifyCode': 0, 'StatusNotifyUserName': '', 'RecommendInfo': {'UserName': '', 'NickName': '', 'QQNum': 0, 'Province': '', 'City': '', 'Content': '', 'Signature': '', 'Alias': '', 'Scene': 0, 'VerifyFlag': 0, 'AttrStatus': 0, 'Sex': 0, 'Ticket': '', 'OpCode': 0}, 'ForwardFlag': 0, 'AppInfo': {'AppID': '', 'Type': 0}, 'HasProductId': 0, 'Ticket': '', 'ImgHeight': 0, 'ImgWidth': 0, 'SubMsgType': 0, 'NewMsgId': 3177606925001563512, 'OriContent': '', 'EncryFileName': '', 'ActualNickName': '易♂建♂联', 'IsAt': False, 'ActualUserName': '@8fd8b5b2bd0862ed5d0d573bc6c08362', 'User':
复制代码
一样分析下要采集的数据,MsgId(微信信息的标识),ActualNickName(发送者群名称),Content(信息内容),CreateTime(建立时间), Type(信息类型)。改下咱们的程序,把这些都提取打印出来。
import itchat
from itchat.content import *
# 好友信息监听
@itchat.msg_register([TEXT, PICTURE, RECORDING, ATTACHMENT, VIDEO], isFriendChat=True)
def handle_friend_msg(msg):
msg_id = msg['MsgId']
msg_from_user = msg['User']['NickName']
msg_content = msg['Content']
msg_create_time = msg['CreateTime']
msg_type = msg['Type']
print("收到信息: ", msg_id, msg_from_user, msg_content, msg_create_time,msg_type)
# 群聊信息监听
@itchat.msg_register([TEXT, PICTURE, RECORDING, ATTACHMENT, VIDEO], isGroupChat=True)
def information(msg):
msg_id = msg['MsgId']
msg_from_user = msg['ActualNickName']
msg_content = msg['Content']
msg_create_time = msg['CreateTime']
msg_type = msg['Type']
print("群聊信息: ",msg_id, msg_from_user, msg_content, msg_create_time,msg_type)
if __name__ == '__main__':
itchat.auto_login()
itchat.run()
复制代码
代码执行结果以下:
群聊信息: 2254622820807367335 胡小韬 对手公司 1533023277 Text
群聊信息: 1765614482944449471 xia_ang 还有自干五 1533023285 Text
好友信息: 615083621872361432 CoderPig 哈哈 1533023293 Text
好友信息: 7292909308782687092 CoderPig 你好哦 1533023302 Text
复制代码
嗯,信息提取成功,接下来要验证的是不一样的信息类型和对应的处理方式,文字,图片(表情),音频,视频,文件五种,后面四种都须要下载到本地,itchat中提供了一个下载文件的方法**msg['Text'](文件存储路径)
**,调用这个方法便可完成文件下载,修改后的代码以下:
import itchat
from itchat.content import *
import os
import time
# 文件临时存储页
rec_tmp_dir = os.path.join(os.getcwd(), 'tmp/')
# 存储数据的字典
rec_msg_dict = {}
# 好友信息监听
@itchat.msg_register([TEXT, PICTURE, RECORDING, ATTACHMENT, VIDEO], isFriendChat=True)
def handle_friend_msg(msg):
msg_id = msg['MsgId']
msg_from_user = msg['User']['NickName']
msg_content = ''
# 收到信息的时间
msg_time_rec = time.strftime("%Y-%m-%d %H:%M%S", time.localtime())
msg_create_time = msg['CreateTime']
msg_type = msg['Type']
if msg['Type'] == 'Text':
msg_content = msg['Content']
elif msg['Type'] == 'Picture' \
or msg['Type'] == 'Recording' \
or msg['Type'] == 'Video' \
or msg['Type'] == 'Attachment':
msg_content = r"" + msg['FileName']
msg['Text'](rec_tmp_dir + msg['FileName'])
rec_msg_dict.update({
msg_id: {
'msg_from_user': msg_from_user,
'msg_time_rec': msg_time_rec,
'msg_create_time': msg_create_time,
'msg_type': msg_type,
'msg_content': msg_content
}
})
print(msg)
# 群聊信息监听
@itchat.msg_register([TEXT, PICTURE, RECORDING, ATTACHMENT, VIDEO], isGroupChat=True)
def information(msg):
msg_id = msg['MsgId']
msg_from_user = msg['ActualNickName']
msg_content = ''
# 收到信息的时间
msg_time_rec = time.strftime("%Y-%m-%d %H:%M%S", time.localtime())
msg_create_time = msg['CreateTime']
msg_type = msg['Type']
if msg['Type'] == 'Text':
msg_content = msg['Content']
elif msg['Type'] == 'Picture' \
or msg['Type'] == 'Recording' \
or msg['Type'] == 'Video' \
or msg['Type'] == 'Attachment':
msg_content = r"" + msg['FileName']
msg['Text'](rec_tmp_dir + msg['FileName'])
rec_msg_dict.update({
msg_id: {
'msg_from_user': msg_from_user,
'msg_time_rec': msg_time_rec,
'msg_create_time': msg_create_time,
'msg_type': msg_type,
'msg_content': msg_content
}
})
print(msg)
if __name__ == '__main__':
if not os.path.exists(rec_tmp_dir):
os.mkdir(rec_tmp_dir)
itchat.auto_login()
itchat.run()
复制代码
代码执行后,分别测试下发送各类文件,看是否都缓存下来,如图所示
接着到撤回信息的监控,撤回的信息类型是NOTE,咱们监听下看看,看看撤回的信息具体内容。
{'MsgId': '7399110162640182490', 'FromUserName': '@9c1a8bf4e28771a6b3ab635991dea2a1', 'ToUserName': '@49d1d90b90371099297a08da1009f3cdd042f21194239ef47b60e8f0b52e4553', 'MsgType': 10002, 'Content': '<sysmsg type="revokemsg"><revokemsg><session>zpj779878443</session><oldmsgid>1625723544</oldmsgid><msgid>3154925139554625499</msgid><replacemsg><![CDATA["CoderPig" 撤回了一条消息]]></replacemsg></revokemsg></sysmsg>', 'Status': 4, 'ImgStatus': 1, 'CreateTime': 1533103679, 'VoiceLength': 0, 'PlayLength': 0, 'FileName': '', 'FileSize': '', 'MediaId': '', 'Url': '', 'AppMsgType': 0, 'StatusNotifyCode': 0, 'StatusNotifyUserName': '', 'RecommendInfo': {'UserName': '', 'NickName': '', 'QQNum': 0, 'Province': '', 'City': '', 'Content': '', 'Signature': '', 'Alias': '', 'Scene': 0, 'VerifyFlag': 0, 'AttrStatus': 0, 'Sex': 0, 'Ticket': '', 'OpCode': 0}, 'ForwardFlag': 0, 'AppInfo': {'AppID': '', 'Type': 0}, 'HasProductId': 0, 'Ticket': '', 'ImgHeight': 0, 'ImgWidth': 0, 'SubMsgType': 0, 'NewMsgId': 7399110162640182490, 'OriContent': '', 'EncryFileName': '', 'User': <User: {'MemberList': <ContactList: []>, 'Uin': 0, 'UserName': '@9c1a8bf4e28771a6b3ab635991dea2a1', 'NickName': 'CoderPig', 'HeadImgUrl': '/cgi-bin/mmwebwx-bin/webwxgeticon?seq=625711027&username=@9c1a8bf4e28771a6b3ab635991dea2a1&skey=@crypt_2d4a1972_e0963a9b961045c2e06293043f1c98a8', 'ContactFlag': 3, 'MemberCount': 0, 'RemarkName': '', 'HideInputBarFlag': 0, 'Sex': 1, 'Signature': '不服气,就用行动去证实,少说多作...2018.7.29', 'VerifyFlag': 0, 'OwnerUin': 0, 'PYInitial': 'CODERPIG', 'PYQuanPin': 'CoderPig', 'RemarkPYInitial': '', 'RemarkPYQuanPin': '', 'StarFriend': 0, 'AppAccountFlag': 0, 'Statues': 0, 'AttrStatus': 33783847, 'Province': '广东', 'City': '江门', 'Alias': '', 'SnsFlag': 17, 'UniFriend': 0, 'DisplayName': '', 'ChatRoomId': 0, 'KeyWord': 'zpj', 'EncryChatRoomId': '', 'IsOwner': 0}>, 'Type': 'Note', 'Text': '"CoderPig" 撤回了一条消息'}
复制代码
首先是判断系统信息是默认撤回了一条信息,内容是: 显示判断是不是撤回的信息,从上面能够看到这样的串字符串:<![CDATA["CoderPig" 撤回了一条消息]]>
,咱们只须要写个正则判断是否有这样的内容,有说明是撤回的信息提醒,接着找撤回的信息MsgId,在上面这串信息的前面就是了:<msgid>3154925139554625499</msgid>
,一样用正则提取。接着要作的就是拿着MsgId去查存消息的字典,根据信息类型拼接文字或文字加文件,而后发送给文件传输助手。具体代码以下:
@itchat.msg_register([NOTE], isFriendChat=True, isGroupChat=True)
def revoke_msg(msg):
if revoke_msg_compile.search(msg['Content']) is not None:
old_msg_id = extract_msgid_compile.search(msg['Content']).group(1)
old_msg = rec_msg_dict.get(old_msg_id, {})
# 先发送一条文字信息
itchat.send_msg(str(old_msg.get('msg_from_user') + "撤回了一条信息:"
+ old_msg.get('msg_content')), toUserName="filehelper")
# 判断文msg_content是否存在,不存在说明多是
if os.path.exists(os.path.join(rec_tmp_dir, old_msg.get('msg_content'))):
if old_msg.get('msg_type') == 'Picture':
itchat.send_image(os.path.join(rec_tmp_dir, old_msg.get('msg_content')),
toUserName="filehelper")
elif old_msg.get('msg_type') == 'Video':
itchat.send_video(os.path.join(rec_tmp_dir, old_msg.get('msg_content')),
toUserName="filehelper")
elif old_msg.get('msg_type') == 'Attachment' \
or old_msg.get('msg_type') == 'Recording':
itchat.send_file(os.path.join(rec_tmp_dir, old_msg.get('msg_content')),
toUserName="filehelper")
复制代码
运行后测试下发送信息后撤回,看下是否生效,测试结果如图所示。
另外,咱们的信息都是用一个字典存着的,时间长了的话,数据会不少,并且图片文件这些会越攒越多,咱们能够添加一个定时任务,好比每隔五分钟清理一下建立时长超过2分钟的信息和对应的文件。相关代码以下:
# 每隔五种分钟执行一次清理任务
def clear_cache():
# 当前时间
cur_time = time.time()
# 遍历字典,若是有建立时间超过2分钟(120s)的记录,删除,非文本的话,连文件也删除
for key in list(rec_msg_dict.keys()):
if int(cur_time) - int(rec_msg_dict.get(key).get('msg_create_time')) > 120:
if not rec_msg_dict.get(key).get('msg_type') == 'Text':
file_path = os.path.join(rec_tmp_dir, rec_msg_dict.get(key).get('msg_content'))
print(file_path)
if os.path.exists(file_path):
os.remove(file_path)
rec_msg_dict.pop(key)
# 开始轮询任务
def start_schedule():
sched.add_job(clear_cache, 'interval', minutes=2)
sched.start()
# 退出中止全部任务并清空缓存文件夹
def after_logout():
sched.shutdown()
shutil.rmtree(rec_tmp_dir)
if __name__ == '__main__':
sched = BlockingScheduler()
if not os.path.exists(rec_tmp_dir):
os.mkdir(rec_tmp_dir)
itchat.auto_login(exitCallback=after_logout)
itchat.run(blockThread=False)
start_schedule()
复制代码
本章咱们对微信网页接口开源库itchat库进行了学习,经过三个实用的代码示例,相信你对这个库已经有个大概的了解了,你也能够根据本身的需求来定制一个本身的机器人,好比添加自动回复,特定信息监控转发等。另外,若是你想让本身的机器人一直运行,能够把脚本部署到服务器上运行,具体怎么运行能够参见爬虫部分的章节。
Tips:
若是在查看本文的时候有什么问题,能够在评论区留言,或者加我微信(不闲聊),拉你进群一块儿讨论: