101 lines
3.3 KiB
Python
101 lines
3.3 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""表情包截图示例 —— 遇到「动画表情」消息时截取其图片
|
||
|
||
背景:微信 4.x 表情消息在本地数据库中的 content 为加密数据,无法直接
|
||
提取原图。因此采用「打开会话 → 滚动到底 → 对最后一条消息区域截图」的
|
||
屏幕截图方案(EmojiMessage.capture()),返回 PNG 路径。
|
||
|
||
用法:
|
||
python demo_emoji_capture.py # 默认会话:文件传输助手
|
||
python demo_emoji_capture.py 某个群 # 指定会话
|
||
python demo_emoji_capture.py --listen 某个群 # 监听模式:收到表情自动截图
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
import sys
|
||
import time
|
||
|
||
try:
|
||
os.system("chcp 65001 >nul 2>&1")
|
||
except Exception:
|
||
pass
|
||
try:
|
||
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||
except AttributeError:
|
||
pass
|
||
|
||
from wechatauto import WeChat
|
||
|
||
SAVE_DIR = os.path.join(os.path.expanduser("~"), "emoji_capture")
|
||
|
||
|
||
def capture_emoji(msg) -> str | None:
|
||
"""对一条表情消息截图,返回 PNG 路径;失败返回 None。
|
||
|
||
截图位置根据消息方向自动判断:
|
||
- msg.attr == 'self' → 右对齐(自己发的)
|
||
- 否则 → 左对齐(对方发的)
|
||
"""
|
||
path = msg.capture(save_dir=SAVE_DIR)
|
||
return path
|
||
|
||
|
||
def capture_latest_emoji(wx: WeChat, who: str) -> None:
|
||
"""打开会话,截取最新一条表情消息的气泡图片。
|
||
|
||
说明:capture() 截图的是屏幕上「最新一条消息」的位置,因此表情
|
||
必须是该会话的最新一条消息才能截到它;否则请用 --listen 模式,
|
||
收到表情时它即为最新一条,可自动截图。
|
||
"""
|
||
wx.ChatWith(who)
|
||
time.sleep(0.5)
|
||
msgs = wx.GetAllMessage() # 新→旧排列,msgs[0] 是会话最新一条
|
||
if not msgs:
|
||
print(f"会话「{who}」没有消息")
|
||
return
|
||
if getattr(msgs[0], "type", None) != "emotion":
|
||
print(f"会话「{who}」最新一条不是表情(是 {msgs[0].type})")
|
||
print("提示:capture() 只截取最新一条消息,请用 --listen 模式在收到表情时自动截图")
|
||
return
|
||
msg = msgs[0]
|
||
path = capture_emoji(msg)
|
||
if path:
|
||
print(f"[表情截图] 方向={msg.attr} 路径={path}")
|
||
else:
|
||
print("[表情截图] 截图失败(微信窗口是否可见?会话是否在最前?)")
|
||
|
||
|
||
def listen_emoji(wx: WeChat, who: str) -> None:
|
||
"""监听模式:实时收到表情消息时自动截图。"""
|
||
def callback(msg, chat):
|
||
if getattr(msg, "type", None) == "emotion":
|
||
path = capture_emoji(msg)
|
||
if path:
|
||
print(f"[收到表情 {msg.attr}] 截图成功 -> {path}")
|
||
else:
|
||
print("[收到表情] 截图失败")
|
||
|
||
wx.AddListenChat(who, callback=callback)
|
||
print(f"监听中,Ctrl+C 退出:{who}")
|
||
wx.KeepRunning()
|
||
|
||
|
||
def main():
|
||
args = [a for a in sys.argv[1:]]
|
||
listen = "--listen" in args
|
||
names = [a for a in args if not a.startswith("--")]
|
||
who = names[0] if names else "送你挖银子"
|
||
|
||
wx = WeChat()
|
||
print(f"当前登录:{wx.nickname}")
|
||
|
||
if listen:
|
||
listen_emoji(wx, who)
|
||
else:
|
||
capture_latest_emoji(wx, who)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|