本文簡介
好久沒更新文章啦,因為最近在趕一本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 itchatimport 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 PigStart 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 itchatimport timedef 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 itchatimport timedef 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 itchatimport 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 itchatfrom apscheduler.schedulers.blocking import BlockingSchedulerimport 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/jsonHost:openapi.tuling123.comUser-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 itchatimport 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 itchatfrom 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 itchatfrom 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 itchatfrom itchat.content import *import osimport 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" 撤回了一條訊息'
}複製程式碼
首先是判斷系統資訊是預設撤回了一條資訊,內容是:顯示判斷是否是撤回的資訊,從上面可以看到這樣的串字串:<
,我們只需要寫個正則判斷是否有這樣的內容,有說明是撤回的資訊提醒,接著找撤回的資訊MsgId,在上面這串資訊的前面就是了:
![CDATA["CoderPig" 撤回了一條訊息]]><
,同樣用正則提取。接著要做的就是拿著MsgId去查存訊息的字典,根據資訊型別拼接文字或文字加檔案,然後傳送給檔案傳輸助手。具體程式碼如下:
msgid>
3154925139554625499<
/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:
如果在檢視本文的時候有什麼問題,可以在評論區留言,或者加我微信(不閒聊),拉你進群一起討論: