利用itchat搭建微信機器人詳解(附三個實用示例)

本文簡介html

很久沒更新文章啦,由於最近在趕一本Py的入門書,碰巧今天把這篇文章趕出來了。 而不少加羣的小朋友不少都是諮詢如何搭建微信機器人的,因此就把這一章放出來了, 取需,三個實用示例:定時發信息,集成圖靈API實現聊天機器人,微信防撤回實現,基本夠玩了。 另外,微信改版了網頁端,不少接口都開始用不了,好比拉人進羣,能夠經過無障礙服務或者 Xposed來解決,具體怎麼玩能夠參見前面的章節,謝謝。git


2011年1月21日,微信推出第一個正式版本,到如今已有7個年頭。從一開始的不被看到好,到如今的用戶量超10億,大衆的平常生活愈來愈離不開微信。人生苦短我用Python,有沒有辦法經過Python來對咱們使用微信提供一些便利呢? 答案確定是有的,在Github上有一個基於微信網頁版接口微信開源庫:itchat,經過幾十行的代碼就能輕鬆實現一個微信機器人。本章咱們就來了解學習這個庫,而後經過三個實用案例來幫你們玩轉這個庫。github


19.1 itchat庫詳解

咱們跟着文檔來解讀下itchat這個庫的用法。web

19.1.1 文檔與安裝

itchat的倉庫地址github.com/littlecoder… 官方文檔itchat.readthedocs.iojson

安裝也很簡單,直接經過pip命令安裝便可,命令以下:api

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()
複製代碼

代碼執行結果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行有效代碼就實現了一個簡單的技巧人,酷不酷,帶着這樣的思路,咱們能夠進行擴展,好比添加一個自動回覆的功能,好比在忙的時候,別人給你發信息,自動回覆:"在忙,晚點給你回覆信息"等。


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:

若是在查看本文的時候有什麼問題,能夠在評論區留言,或者加我微信(不閒聊),拉你進羣一塊兒討論:

相關文章
相關標籤/搜索