用Python做個微信自動回復機器人
- 2019 年 10 月 7 日
- 筆記
今天我們來玩轉一下微信,微信有關的第三方框架很多,比如wxpy,wxBot等。今天要使用的是其中著名的itchat Python模組來做兩件有趣的事情。
一個自動回復的機器人
微信自上線以來,一直沒有自動回復的功能,想必是有他們的理念。但是有些人群,確實對此功能有一定需求,我舉兩個栗子:
- 不願時刻被消息打擾的人
- 消息需要批量處理的人們(比如微商)
功能列表:
- 收到消息立即自動回復
- 收到消息延遲指定時間回復
- 對不同好友訂製不同的回復內容
- 在手機端隨時進行控制
1.啟用itchat模組
itchat的原理是通過掃碼進行遠程微信網頁端的登錄,然後通過在移動端進行操作,網頁端進行響應,來實現一些功能,雖然似乎繞了個彎子,但是在微信的限制下,這似乎已經是一種最佳的方式了。
首先我們需要考慮別的問題是:程式如何在微信端接收到你的指令。此時出現了一個非常重要的角色:文件管理器。(當網頁端微信登陸後,消息列表會出現)此時,文件管理器充當了移動端和web端的橋樑。
我們可以先通過設定幾個全局變數來做作為功能的開關和保存數據的容器。

然後通過判斷web端在」文件管理器「中接收到的字元串指令來進行不同操作,假如此時我們收到了朋友的消息,需要程式給出自動回復。

收到朋友消息即時進行自動回復是很簡單的,但是如何去做延時發送回復消息呢?我先談一談我的想法,拋磚引玉:
- 一般發送消息需要用到隊列,進行入隊和出隊,我在這裡設置了一個字典來保存消息發送者的數據。
- 鍵為消息發送者的昵稱,值是一個長度為2的數組,分別保存消息發送者的微信id和接收消息時的時間戳。
- 這樣我將每條發送過來的朋友資訊保存在這個字典中,再通過將設定延遲時間同消息時間戳求和與當前時間戳進行對比,若當前時間戳較大,那麼執行發送消息的操作。
- 此時再開啟一個執行緒作為定時任務,定時去檢測字典中每條數據是否到達了發送的臨界要求(當前時間戳>=消息時間戳+設定的延遲時間)。
- Python中有個專門做定時任務的模組叫sched,但是我嘗試了一下,sched會阻塞當前主執行緒,也會阻塞itchat的執行緒,所以並不合適。
- 這裡我還是採用了threading的Timer來充當定時器,不過要注意使用遞歸,否則將會出現運行一次就結束的情況。

到此為止,主要的功能已經實現了,我用一個測試帳號對我的微信進行了各種測試,看一下以下截圖:


2.增強功能
這時功能基本已經完成了,這就結束了嗎?別著急,再想想有沒有需要完善一下的地方?用過微信web端的同學應該知道,當web端長期處於未操作的狀態下會失去連接。
在我們這個情況下,假如你長時間未收到微信消息,後台程式將會與微信失去連接,再次開啟需要登上伺服器重啟程式,這顯然非常麻煩。有沒有什麼簡單的解決辦法呢?
我想到一些應用的後台通常會做一道心跳檢測機制,那我就模仿這個思路,定時給我的」文件管理器「發一個字元串,來保持連接。
def keep_alive(): text="保持登錄" itchat.send(text, toUserName="filehelper") global timer2 timer2 = threading.Timer(60*60,keep_alive) timer2.start()
最後,我們需要將這個程式發布在伺服器上,讓它全天候為我的微信服務。
這裡需要注意,如果僅用python xxxx.py來運行的話,關閉shell會導致進程結束,所以我們需要使用nohup python xxxx.py &來全方位守護進程,這裡啰嗦一句,nohup和&的功能是不一樣的,很多人容易混淆,感興趣的話可以去查下資料區分一下。
簡單分析微信好友資訊
上文提到,既然我們能通過itchat來獲取好友的資訊,那讓我們看看都有哪些好玩的資訊。這是以json形式返回的我的資訊,同理我的好友的這些公開資訊我也能獲取到。

我們就來進行一些簡單的的數據抓取,清洗與呈現。我看中的欄位是:Sex、City、Province、Signature。我想做的是通過圖表來直觀地展示我微信好友中的性別比例,家鄉分布(當然不一定準確,很多人都是胡亂設置的),我的江蘇朋友的市級分布,以及好友個性簽名的詞雲。
這部分內容主要是需要熟悉諸如pyecharts、jieba、wordcloud模組的API調取,難度不大,但需要細心調試。我這裡就不詳細贅述了。
1).性別比例

用餅圖可視化一下:

2).好友省級分布
def get_data(type): result=[] my_friends = itchat.get_friends(update=True)[0:] for item in my_friends: result.append(item[type]) return result def friends_province(): # 獲取好友省份 province= get_data("Province") # 分類 province_distribution = {} for item in province: #刪除英文省份,因為中國地圖表中沒有 if bool(re.search('[a-z]',item)): continue elif not province_distribution.__contains__(item): province_distribution[item] = 1 else: province_distribution[item] += 1 #將省份名為空的刪除 province_distribution.pop('') #提取地圖介面需要的數據格式 province_keys=province_distribution.keys() province_values=province_distribution.values() return province_keys,province_values if __name__ == '__main__': itchat.auto_login(True) 微信好友省份分布 attr,value=friends_province() map = Map("我的微信好友分布", "@寒食君",width=1200, height=600) map.add("", attr, value, maptype='china', is_visualmap=True, visual_text_color='#000') map.render()
用地圖來顯示一下:

3).個性簽名詞雲
def friends_signature(): signature = get_data("Signature") wash_signature=[] for item in signature: #去除emoji表情等非文字 if "emoji" in item: continue rep = re.compile("1fd+w*|[<>/=【】『』♂ω]") item=rep.sub("", item) wash_signature.append(item) words="".join(wash_signature) wordlist = jieba.cut(words, cut_all=True) word_space_split = " ".join(wordlist) coloring = np.array(Image.open("C:/Users/casua/Desktop/test1.JPG")) my_wordcloud = WordCloud(background_color="white", max_words=800, mask=coloring, max_font_size=80, random_state=30, scale=2,font_path="C:/Windows/Fonts/STKAITI.ttf").generate(word_space_split) image_colors = ImageColorGenerator(coloring) plt.imshow(my_wordcloud.recolor(color_func=image_colors)) plt.imshow(my_wordcloud) plt.axis("off") plt.show()
看一下詞雲圖:


Python真的非常有趣,可以做很多事情,細心的發現生活裡面的一些點點滴滴,用技術去改變生活。也許這個小腳本並不是很複雜,但是通過這樣的練習,你會有極大的成就感。感謝寒食君的投稿,他是一個非常具有工匠精神的程式設計師,加油!
Python玩微信是不是很酷,歡迎留言討論!