本文簡介
好久沒更新文章啦,因為最近在趕一本Py的入門書,碰巧今天把這篇文章趕出來了。 而很多加群的小朋友很多都是諮詢如何搭建微信機器人的,所以就把這一章放出來了, 取需,三個實用示例:定時發資訊,整合圖靈API實現聊天機器人,微信防撤回實現,基本夠玩了。 另外,微信改版了網頁端,很多介面都開始用不了,比如拉人進群,可以通過無障礙服務或者 Xposed來解決,具體怎麼玩可以參見前面的章節,謝謝。
2011年1月21日,微信推出第一個正式版本,到現在已有7個年頭。從一開始的不被看到好,到現在的使用者量超10億,大眾的日常生活越來越離不開微信。人生苦短我用Python,有沒有辦法通過Python來對我們使用微信提供一些便利呢? 答案肯定是有的,在Github上有一個基於微信網頁版介面微信開源庫:itchat,通過幾十行的程式碼就能輕鬆實現一個微信機器人。本章我們就來了解學習這個庫,然後通過三個實用案例來幫大家玩轉這個庫。
19.1 itchat庫詳解
我們跟著文件來解讀下itchat這個庫的用法。
19.1.1 文件與安裝
itchat的倉庫地址:github.com/littlecoder… 官方文件:itchat.readthedocs.io
安裝也很簡單,直接通過pip命令安裝即可,命令如下:
pip install itchat
複製程式碼
19.1.2 簡單的使用示例
通過一個簡單的例子來讓讀者體會下通過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()
複製程式碼
程式碼執行結果:
先會彈出一個二維碼圖片,掃描後會登陸網頁端微信,間隔一會兒後檔案助手收到如圖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行有效程式碼就實現了一個簡單的技巧人,酷不酷,帶著這樣的思路,我們可以進行擴充套件,比如新增一個自動回覆的功能,比如在忙的時候,別人給你發資訊,自動回覆:"在忙,晚點給你回覆資訊"等。
19.2 使用itchat的注意事項
在學習itchat的詳細用法前,先和讀者說一些要注意的東西。
(1)itchat不是微信官方提供的庫,意味使用這個庫會有風險,筆者的小號就曾被微信封過一段時間,禁止網頁端登入微信,移動端和電腦客戶端還是能正常使用的,微信此舉旨在封殺氾濫的微商機器人。 (2)如何減少被封概率:訊息傳送不要過於頻繁;不要傳送過多重複資訊;儘量少呼叫加人的介面; (3)被封如何解封:被封后是無法找到申述入口,只能隨緣解封,筆者在堅持了一週用手機聊天和朋友圈點贊留言後突然就解封了。 (4)微信正在慢慢收窄網頁端的功能,意味著一些介面會慢慢失效,比如說拉人進群聊的介面,以前還能用,現在就不行了。在呼叫某個介面沒有得到意料中的結果,可能就是介面失效了,可以到官方倉庫查詢相關的issues。 (5)微信只支援雙端登入,不使用黑科技的話,移動端加上Web網頁端或PC客戶端。 (6)新註冊的微訊號是無法使用網頁版登入的。
最後,還是要感謝開源作者的無私奉獻。
19.3 itchat詳細用法
巧婦難為無米之炊,在擴充套件前先跟筆者把文件過一過,理解得差不多了,再開始去擴充套件,這樣效率會高很多。
19.3.1 登陸
登陸時通過itchat.auto_login()這個函式來完成的,不帶引數的話會生成一個二維碼圖片檔案供你掃描登陸。一般的話我們的電腦都會關機,如果機器人有需要持久線上的需求,我們可以把指令碼掛到伺服器上,24小時跑,但是一般的雲伺服器是沒有介面的,都是通過終端命令列進行操作,這個時候可以新增enableCmdQR=True引數,讓二維碼顯示到命令列上,另外部分系統可能字元寬度有出入,如圖19.2所示,可以通過把enableCmdQR賦值為特定的倍數進行調整。
圖19.2 命令列二維碼錯位
比如enableCmdQR=2後,二維碼圖片如圖19.3所示
圖19.3 調整後正常的二維碼圖片
掃碼登入後,如果想退出程式以後還暫存登入狀態,重新執行程式也不用掃碼可以新增引數hotReload=True。
19.3.2 退出
如果在啟動時沒有設定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.
登入後呼叫
退出後呼叫
複製程式碼
19.3.3 查詢使用者
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}>]
複製程式碼
19.3.4 傳送資訊
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.4 監聽資訊
除了主動傳送資訊外,還可以對資訊進行監控,支援對多種型別的資訊進行監控,型別如表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()
複製程式碼
程式碼執行結果如下:
19.2.5 群聊
在微信網頁端改版後,建立群聊、拉人進群和刪除群聊這幾個介面都用不了,現在利用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欄位,可用於判斷是否被人@了。
19.2.6 公眾號
使用方式和群聊的非常類似,搜尋公眾號方法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
複製程式碼
聊天記錄截圖:
19.3 實用示例:定時傳送訊息
定時傳送資訊這個操作在日常生活中非常實用,比如給別人發生日或者節日祝福,晚上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()
複製程式碼
程式碼執行結果如下:
19.4 實用示例:整合圖靈API製作聊天機器人
圖靈機器人官網: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()
複製程式碼
程式碼執行結果如下圖所示:
19.5 實用示例:實現微信資訊防撤回
上面的圖靈機器人有時回答得牛頭不對馬嘴,特別是在多輪問答的時候,閒聊玩玩還是不錯的。 接著的我們要利用itchat來編寫一個微信資訊防撤回的指令碼。當監控到使用者或者群聊傳送資訊 撤回的話,把撤回的內容通過檔案傳輸助手傳送給我們,說下大體的思路流程。
(1)監聽所有聊天記錄,包括群聊,把資訊都存入到一個字典裡,資源類檔案下載到本地。 (2)監聽到撤回資訊後,根據撤回的資訊id,查詢字典裡對應的資訊,傳送給檔案助手。 (3)每隔五分鐘清理快取資料。
流程看上去是挺簡單,接著我們一點點來摸索實現。
19.5.1 監控接收到的資料
先是監控資訊,資訊又分為好友聊天和群聊,我們編寫程式碼來監控下收到的資料是怎麼樣的?
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
複製程式碼
19.5.2 驗證不同資訊型別和對應處理方式
嗯,資訊提取成功,接下來要驗證的是不同的資訊型別和對應的處理方式,文字,圖片(表情),音訊,視訊,檔案五種,後面四種都需要下載到本地,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()
複製程式碼
程式碼執行後,分別測試下傳送各種檔案,看是否都快取下來,如圖所示
19.5.3 監控撤回資訊和資料提取
接著到撤回資訊的監控,撤回的資訊型別是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")
複製程式碼
執行後測試下傳送資訊後撤回,看下是否生效,測試結果如圖所示。
19.5.4 定時清理快取
另外,我們的資訊都是用一個字典存著的,時間長了的話,資料會很多,而且圖片檔案這些會越攢越多,我們可以新增一個定時任務,比如每隔五分鐘清理一下建立時長超過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()
複製程式碼
19.6 小結
本章我們對微信網頁介面開源庫itchat庫進行了學習,通過三個實用的程式碼示例,相信你對這個庫已經有個大概的瞭解了,你也可以根據自己的需求來定製一個自己的機器人,比如新增自動回覆,特定資訊監控轉發等。另外,如果你想讓自己的機器人一直執行,可以把指令碼部署到伺服器上執行,具體怎麼執行可以參見爬蟲部分的章節。
Tips:
如果在檢視本文的時候有什麼問題,可以在評論區留言,或者加我微信(不閒聊),拉你進群一起討論: