使用Python監聽並下載微信聊天表情包

實現的功能

只要有人給你發了表情包,不管是羣聊還是個人發的,都將它保存到本地。也許某天鬥圖的時候就能用到,不過即使有了表情包,還需要一個檢索功能,不然這一張一張看也太費眼睛了。

檢索表情包

檢索表情包的功能實現比較麻煩,至少需要兩個模型:ocr和圖片描述生成,如果更復雜點的話還需要分詞算法、數據庫等。

需要ocr應該很容易理解,表情包裏面包含文字信息,使用ocr將文字提取出來,這個文字基本就可以作爲檢索的信息了。

如果表情沒有文字,那隻能使用一些模型,爲圖片生成一個簡單的描述,然後將這個描述作爲檢索的信息。

搜了一下目前開源的模型裏面沒看到比較合適的。後面如果遇到了再做一個簡單的表情包檢索程序。

開始實現

效果圖

github代碼

https://github.com/kanadeblisst00/WeChat-PyRobot

http://www.pygrower.cn:21180/kanadeblisst/WeChat-PyRobot

實現原理

使用Python來監聽微信消息,如果收到表情包消息就提取裏面的鏈接並下載,因爲表情包xml消息裏有一個未加密的鏈接。

監聽消息的原理和代碼可以看之前的一篇文章: 【Python微信機器人】第八篇: 實戰32位和64位接收消息和消息防撤回

代碼在上篇文章的基礎上做了如下優化:

  1. 使用隊列存儲監聽到的消息
  2. 支持加載消息插件來處理消息
  3. 支持注入後就自動監聽消息

待實現插件列表

  • 監聽羣聊中的羣二維碼
  • 監聽並實時採集關注的公衆號文章
  • 自動下載並解密聊天中的圖片
  • chatgpt自動回覆
  • 羣消息關鍵詞提醒
  • 消息保存到數據庫,如sqlite、postgresql等
  • 自動接收轉賬
  • 監聽收款信息對接髮卡平臺,目前可以用v免籤+獨角數卡

開始監聽並下載表情包

準備工作

  1. 安裝支持的版本微信(目前只寫了3.9.8.123.9.8.15的代碼)
  2. 安裝32位或64位Python(取決於你安裝的微信是32位還是64位),Python版本需大於等於3.8
  3. pip install wechat_pyrobot==1.1.1

如果國內源還沒有同步最新版本,可以指定-i https://pypi.org/simple/選項使用pip官方庫

開始監聽消息

先啓動並登錄微信,隨便創建一個文件夾,然後創建一個文件main.py(名稱隨意)寫入以下代碼:

from py_process_hooker import inject_python_and_monitor_dir
from wechat_pyrobot import get_on_startup
from wechat_pyrobot.msg_plugins import PrintMsg, DownLoadEmotion


if __name__ == "__main__":
    process_name = "WeChat.exe"
    open_console = True
    on_startup = get_on_startup(msg_plugins=[PrintMsg, DownLoadEmotion])
    
    inject_python_and_monitor_dir(process_name, __file__, open_console=open_console, on_startup=on_startup)

使用Python運行這段代碼,就會將Python注入到微信,並且開始監聽微信收到的消息,然後將監聽到的消息依次傳遞給msg_plugins指定的插件列表。

DownLoadEmotion插件就是用來下載表情包的,裏面的代碼很簡單:

class DownLoadEmotion(MsgPluginTemplate):
    def __init__(self, **kwargs) -> None:
        self.name = os.path.basename(__file__)[:-3]
        super().__init__(**kwargs)
        self.emotion_save_path = os.path.join(kwargs["pwd"], "emotion")
        os.makedirs(self.emotion_save_path, exist_ok=True)

    def deal_msg(self, msg_dict):
        if msg_dict["msg_type"] != 0x2F:
            return
        xml = msg_dict["content"]
        root = ET.fromstring(xml) 
        datas = dict(root.find('.//emoji').items())
        cdnurl = datas["cdnurl"].replace('&', '&')
        filename = msg_dict["file_path"]
        if not filename:
            filename = msg_dict["msgid"]
        save_path = f"{self.emotion_save_path}{os.sep}{filename}.gif"
        with open(save_path, 'wb') as f:
            f.write(self.download_file(cdnurl))
    
    def download_file(self, url, retry=0):
        if retry > 2:
            return
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.183"
        }
        try:
            resp = requests.get(url, headers=headers, timeout=6)
        except:
            traceback.print_exc()
            time.sleep(2)
            return self.download_file(url, retry+1)
        return resp.content

先判斷一下消息類型是不是0x2F,也就是表情包的消息類型,然後提取xml數據裏的cdnurl,用requests下載下來保存到本地

編寫自己的插件

可以先參考目前已有的插件例子,代碼在wechat_pyrobot/msg_plugins, 在github或者pip本地目錄都可以看到

編寫一個消息保存到文件的插件

插件需要繼承MsgPluginTemplate,然後實現deal_msg方法,方法只有一個參數:字典類型的消息

my_msg_plugin/save_to_file.py

import os
import json
from wechat_pyrobot.plugin_class import MsgPluginTemplate


class SaveToFile(MsgPluginTemplate):
    def __init__(self, **kwargs) -> None:
        self.name = os.path.basename(__file__)[:-3]
        super().__init__(**kwargs)
        # kwargs["pwd"]是main.py所在路徑
        self.msg_save_path = os.path.join(kwargs["pwd"], "msg_save_path")
        os.makedirs(self.msg_save_path, exist_ok=True)
    
    def deal_msg(self, msg_dict):
        path = os.path.join(self.msg_save_path, f'{msg_dict["msgid"]}.json')
        with open(path, 'w', encoding='utf-8') as f:
            f.write(json.dumps(msg_dict)) 

然後在注入的代碼(main.py)里加載它,需要重新啓動並注入微信

from py_process_hooker import inject_python_and_monitor_dir
from wechat_pyrobot import get_on_startup
from wechat_pyrobot.msg_plugins import PrintMsg, DownLoadEmotion
from my_msg_plugin.save_to_file import SaveToFile

if __name__ == "__main__":
    process_name = "WeChat.exe"
    open_console = True
    on_startup = get_on_startup(msg_plugins=[PrintMsg, DownLoadEmotion, SaveToFile])
    
    inject_python_and_monitor_dir(process_name, __file__, open_console=open_console, on_startup=on_startup)

這樣收到的消息都會保存到文件,當然這個只是示例。實際應該按時間來分類文件,或者保存到數據庫中。

插件列表是有順序的,在執行時會依次執行,如果之前的插件修改了消息字典,那麼之後的插件得到的消息字典就是修改後的

本文由博客一文多發平臺 OpenWrite 發佈!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章