基于UI自动化的51vv聊天信息获取方案

基于UI自动化的51vv聊天信息获取方案

。既然51vv只有客户端没有网页版,我们可以用UI自动化方案来模拟人工操作。

🖥️ 方案1:Python + OpenCV图像识别(免Hook)

这是最安全的方式,完全模拟真人操作,不触碰内存或网络层:

import cv2
import numpy as np
import pyautogui
import pytesseract
import time
import os
from PIL import Image
import win32gui
import win32con
import win32api

class VVMonitor:
    def __init__(self, window_title="51vv"):
        self.window_title = window_title
        self.hwnd = None
        self.chat_log = []
        
    def find_window(self):
        """找到51vv聊天窗口"""
        def callback(hwnd, windows):
            if win32gui.IsWindowVisible(hwnd) and self.window_title in win32gui.GetWindowText(hwnd):
                windows.append(hwnd)
            return True
        
        windows = []
        win32gui.EnumWindows(callback, windows)
        if windows:
            self.hwnd = windows[0]
            return True
        return False
    
    def capture_chat_area(self):
        """截取聊天区域"""
        if not self.hwnd:
            return None
        
        # 获取窗口位置和大小
        rect = win32gui.GetWindowRect(self.hwnd)
        x, y, w, h = rect[0], rect[1], rect[2] - rect[0], rect[3] - rect[1]
        
        # 聊天区域大致位置(需要根据实际窗口调整)
        chat_x = x + int(w * 0.6)  # 聊天区域可能在右侧
        chat_y = y + int(h * 0.2)
        chat_w = int(w * 0.35)
        chat_h = int(h * 0.6)
        
        # 截图
        screenshot = pyautogui.screenshot(region=(chat_x, chat_y, chat_w, chat_h))
        return np.array(screenshot)
    
    def extract_text_from_image(self, image):
        """OCR识别图片中的文字"""
        # 转换为灰度图
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        
        # 图像预处理,提高OCR准确率
        _, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)
        
        # OCR识别
        text = pytesseract.image_to_string(thresh, lang='chi_sim')  # 中文语言包
        return text
    
    def parse_chat_messages(self, text):
        """解析聊天消息,提取用户ID和内容"""
        lines = text.split('\n')
        for line in lines:
            # 假设消息格式是 "[ID] 用户名: 消息内容"
            # 需要根据实际显示格式调整正则表达式
            import re
            match = re.search(r'\[(\d+)\]\s*([^:]+):\s*(.+)', line)
            if match:
                user_id = match.group(1)
                username = match.group(2)
                content = match.group(3)
                
                if content not in [msg['content'] for msg in self.chat_log[-10:]]:
                    message = {
                        'user_id': user_id,
                        'username': username,
                        'content': content,
                        'time': time.time()
                    }
                    self.chat_log.append(message)
                    print(f"[{user_id}] {username}: {content}")
                    return message
        return None
    
    def monitor_loop(self, interval=2):
        """持续监控"""
        if not self.find_window():
            print("未找到51vv窗口")
            return
        
        print("开始监控聊天消息...")
        last_text = ""
        
        while True:
            try:
                # 截图并识别
                chat_img = self.capture_chat_area()
                if chat_img is not None:
                    text = self.extract_text_from_image(chat_img)
                    
                    # 如果文本有变化,说明有新消息
                    if text != last_text:
                        self.parse_chat_messages(text)
                        last_text = text
                
                time.sleep(interval)
                
            except KeyboardInterrupt:
                print("监控结束")
                break
            except Exception as e:
                print(f"错误: {e}")
                time.sleep(5)

🖱️ 方案2:PyAutoGUI + 剪贴板操作(更精准)

利用复制粘贴功能获取精准文本:

import pyautogui
import pyperclip
import time
import re

class VVChatMonitor:
    def __init__(self):
        self.messages = []
        
    def select_and_copy(self, x, y):
        """在指定位置点击并复制文本"""
        # 移动到聊天区域
        pyautogui.moveTo(x, y)
        
        # 双击选中文本
        pyautogui.doubleClick()
        time.sleep(0.2)
        
        # 右键复制
        pyautogui.rightClick()
        time.sleep(0.2)
        # 需要根据右键菜单的实际位置调整
        pyautogui.move(0, 40)  # 向下移动到"复制"选项
        pyautogui.click()
        time.sleep(0.2)
        
        # 获取剪贴板内容
        return pyperclip.paste()
    
    def scan_chat_area(self, start_x, start_y, end_x, end_y, step=20):
        """扫描聊天区域,逐行复制"""
        messages = []
        for y in range(start_y, end_y, step):
            try:
                text = self.select_and_copy(start_x + 10, y)
                if text and self.is_valid_message(text):
                    messages.append(text)
            except:
                pass
        return messages
    
    def is_valid_message(self, text):
        """判断是否是有效的聊天消息"""
        # 根据实际格式调整
        patterns = [
            r'\[\d+\]',  # 包含[数字]
            r'\d{4,10}',  # 包含4-10位数字(可能是ID)
            r'.{2,20}:',  # 包含冒号(可能是用户名和内容的分隔)
        ]
        
        return any(re.search(p, text) for p in patterns)
    
    def monitor_realtime(self, chat_area_rect):
        """实时监控(需要找到聊天区域的最新消息位置)"""
        last_message = ""
        x, y, w, h = chat_area_rect
        
        while True:
            # 移动到聊天区域底部(最新消息)
            latest_y = y + h - 30
            text = self.select_and_copy(x + 50, latest_y)
            
            if text and text != last_message:
                print(f"新消息: {text}")
                self.messages.append(text)
                last_message = text
            
            time.sleep(3)

🔧 方案3:AutoHotkey + Python混合(最稳定)

AutoHotkey处理UI交互,Python处理数据分析:

AutoHotkey脚本 (vv_chat.ahk)

#Persistent
CoordMode, Mouse, Window

; 获取聊天文本的函数
GetChatText(x, y) {
    MouseMove, x, y
    Click, 2  ; 双击选中
    Sleep, 100
    Send, ^c  ; 复制
    Sleep, 100
    return Clipboard
}

; 持续监控
Loop {
    ; 假设聊天区域底部位置
    text := GetChatText(800, 500)
    FileAppend, %text%`n, chat_log.txt
    Sleep, 3000
}

Python端处理

import time
import re
import subprocess
from pathlib import Path

class AHKChatProcessor:
    def __init__(self):
        self.ahk_process = None
        self.log_file = Path("chat_log.txt")
        
    def start_ahk_script(self, script_path):
        """启动AutoHotkey脚本"""
        self.ahk_process = subprocess.Popen(["AutoHotkey.exe", script_path])
        
    def process_log(self):
        """处理AutoHotkey生成的日志"""
        while True:
            if self.log_file.exists():
                with open(self.log_file, 'r', encoding='utf-8') as f:
                    lines = f.readlines()
                    
                for line in lines[-10:]:  # 只处理最新的10行
                    self.parse_chat_line(line)
                    
            time.sleep(2)
            
    def parse_chat_line(self, line):
        """解析聊天行"""
        # 根据实际格式调整
        pattern = r'(\d{6,12})\s*([^:]+):\s*(.+)'
        match = re.search(pattern, line)
        if match:
            user_id, username, content = match.groups()
            print(f"用户 {username}({user_id}): {content}")
            return {
                'user_id': user_id,
                'username': username,
                'content': content,
                'time': time.time()
            }
        return None

📊 实际部署步骤

  1. 准备工作

    # 安装必要的库
    pip install opencv-python pytesseract pyautogui pyperclip pillow numpy
    # 安装Tesseract OCR(用于中文识别)
    # Windows: https://github.com/UB-Mannheim/tesseract/wiki
    # 需要下载中文语言包 chi_sim
  2. 获取窗口坐标

    # 先用这个脚本找出聊天区域坐标
    import pyautogui
    import time
    
    print("将鼠标移到聊天区域左上角,5秒后获取坐标...")
    time.sleep(5)
    x1, y1 = pyautogui.position()
    print(f"左上角: ({x1}, {y1})")
    
    time.sleep(2)
    print("将鼠标移到聊天区域右下角,5秒后获取坐标...")
    time.sleep(5)
    x2, y2 = pyautogui.position()
    print(f"右下角: ({x2}, {y2})")
    print(f"聊天区域: x={x1}, y={y1}, w={x2-x1}, h={y2-y1}")
  3. 根据实际界面调整参数
  4. 51vv的聊天区域位置可能因皮肤、窗口大小而异
  5. 消息格式可能是:[用户ID] 昵称: 消息内容
  6. 或者:时间 [ID] 昵称: 内容

⚠️ 注意事项

  1. 准确性限制

    • OCR识别中文可能出错,特别是特殊字体
    • 截图区域需要精确定位
    • 动态滚动时可能漏掉消息
  2. 性能影响

    • 频繁截图会占用CPU
    • 建议设置2-5秒的监控间隔
  3. 稳定性

    • 确保51vv窗口不被遮挡
    • 避免鼠标键盘被其他操作干扰

💡 替代思路:模拟登录客户端

如果你想更稳定地获取数据,可以尝试:

# 用pywinauto控制客户端
from pywinauto.application import Application

app = Application().start(r"C:\Program Files\51vv\51vv.exe")
# 等待登录界面
# 自动输入账号密码
# 进入房间后抓取聊天控件文本

这个方案需要逆向分析客户端的UI控件结构,但一旦成功,比图像识别更稳定。

最推荐方案1(OCR识别)或方案3(AutoHotkey+Python),因为它们在法律上最安全(只是模拟人工操作),并且能实现你的核心需求:获取公开的聊天内容和用户ID。