如何基于Python开发一个微信自动化工具

2025-05-28 03:50

本文主要是介绍如何基于Python开发一个微信自动化工具,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《如何基于Python开发一个微信自动化工具》在当今数字化办公场景中,自动化工具已成为提升工作效率的利器,本文将深入剖析一个基于Python的微信自动化工具开发全过程,有需要的小伙伴可以了解下...

概述

在当今数字化办公场景中,自动化工具已成为提升工作效率的利器。本文将深入剖析一个基于python的微信自动化工具开发全过程,该工具集成了即时消息发送、定时任务管理和微信进程控制三大核心功能模块。

技术栈亮点:

PyQt5构建美观的GUI界面

uiautomation实现Windows UI自动化

psutil进行进程管理

多线程处理保持UI响应

完整的异常处理机制

功能全景

1. 核心功能模块

模块名称功能描述
即时消息发送支持文本+文件混合发送,智能识别联系人
定时任务管理精确到秒的定时发送,支持循环任务配置
微信进程控制启动/激活/退出微信的一键操作

2. 特色功能

  • 智能窗口激活:自动置顶微信窗口并居中显示
  • 文件绝对路径处理:自动转换相对路径为绝对路径
  • 任务持久化:运行时任务列表维护
  • 健壮性设计:多重异常处理+操作状态反馈

效果展示

1. 主界面概览

如何基于Python开发一个微信自动化工具

2. 定时任务配置

如何基于Python开发一个微信自动化工具

3. 操作日志演示

如何基于Python开发一个微信自动化工具

如何基于Python开发一个微信自动化工具

实现步骤详解

1. 环境准备

pip install pyqt5 psutil uiautomation

2. 工程结构设计

WeChatAutomation/
├── main.py            # 主程序入口
├── wechat.ico         # 程序图标
└── README.md          # 使用说明

3. 核心实现流程

GUI框架搭建:采用QMainWindow+TabWidget布局

工作线程封装:WorkerThread类继承QThread

定时任务调度:QTimer秒级轮询检查

UI自动化控制:uiautomation操作微信窗口

异常处理体系:三级错误捕获机制

代码深度解析

1. 多线程任务处理

class WorkerThread(QThread):
    finished = pyqtSignal(str, bool)  # 信号参数:消息内容, 是否成功
    
    def run(self):
        try:
            result = self.func(*self.args, **self.kwargs)
            self.finished.emit(result or "操作成功", True)
        except Exception as e:
            self.finished.emit(f"错误: {str(e)}", False)

设计要点:

  • 采用信号槽机制实现线程间通信
  • 统一错误处理接口
  • 支持任意函数的多线程执行

2. 微信窗口控制核心

def wechat_active():
    # 超时设置优化
    uiautomation.uiautomation.TIME_OUT_SECOND = 2  
    if ifProcessRunning():
        try:
            # 快捷键激活方案
            desktop = uiautomation.PaneControl(Name='任务栏')
            desktop.SendKeys('{Ctrl}{Alt}w')
        except:
            # 异常后备方案
            os.system('taskkill /F /im "WeChat.exe"')
            wechat_start()
    else:
        wechat_start()
    
    # 恢复默认超时
    uiautomation.uiautomation.TIME_OUT_SECOND = 20  
    wechatWindow = uiautomation.WindowControl(
        searchDepth=1, 
        className='WeChatMainWndForPC', 
        Name='微信'
    )

优化策略:

动态调整UI查找超时时间

多方案组合提高成功率

异常后的自动恢复机制

3. 定时任务调度系统

def check_scheduled_tasks(self):
    now = datetime.now()
    for task in self.scheduled_tasks:
        if not task["completed"] and now >= task["send_time"]:
            success = self.send_message(
                recipient=task["recipient"],
                message=task["message"],
                file_path=task["file_path"]
            )
            
            if success and task["repeat"]:  # 重复任务处理
                task["send_time"] = now + timedelta(
                    minutes=task["interval"]
                )
                task["completed"] = False
            else:
                task["completed"] = True

算法特点:

低精度定时检查(1秒间隔)

支持单次/循环任务模式

非阻塞式任务执行

源码获取

# -*- coding:utf-8 -*-
import sys
import psutil
import uiautomation
import os
import time
from datetime import datetime, timedelta
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QvboxLayout, QHBoxLayout, 
                            QTabWidget, QLabel, QLineEdit, QTextEdit, QPushButton, 
                            QFileDialog, QMessageBox, QStatusBar, QGroupBox,
                            QDateTimeEdit, QCheckBox, QSpiphpnBox)
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer
from PyQt5.QtGui import QIcon, QFont

class WorkerThread(QThread):
    finished = pyqtSignal(str, bool)  # message, success
    
    def __init__(self, func, *args, **kwargs):
        super().__init__()
        self.func = func
        self.args = args
        self.kwargs = kwargs
    
    def run(self):
        try:
            result = self.func(*self.args, **self.kwargs)
            self.finished.emit(result or "操作成功", True)
        except Exception as e:
            self.finished.emit(f"错误: {str(e)}", False)

class WeChatAutomationApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("微信自动化发送工具---BY 白泽")
        self.setGeometry(100, 100, 787, 639)
        self.setWindowIcon(QIcon("wechat.ico"))  # 替换为你的图标文件
        
        # 定时任务列表
        self.scheduled_tasks = []
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.check_scheduled_tasks)
        self.timer.start(1000)  # 每秒检查一次
        
        # 设置全局字体
        font = QFont("Microsoft YaHei", 10)
        QApplication.setFont(font)
        
        # 主控件
        self.main_widget = QWidget()
        self.setCentralWidget(self.main_widget)
        
        # 主布局
        self.main_layout = QVBoxLayout(self.main_widget)
        self.main_layout.setContentsMargins(15, 15, 15, 15)
        self.main_layout.setSpacing(15)
        
        # 创建标签页
        self.tabs = QTabWidget()
        self.main_layout.addwidget(self.tabs)
        
        # 创建各个标签页
        self.create_send_tab()
        self.create_schedule_tab()
        self.create_control_tab()
        
        # 状态栏
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        self.status_bar.showMessage(" 就绪")
        
        # 样式设置
        self.set_style()
    
    def set_style(self):
        self.setStyleSheet("""
            QMainWindow {
                background-color: #f5f5f5;
            }
            QTabWidget::pane {
                border: 1px solid #d3d3d3;
                border-radius: 5px;
                padding: 5px;
                background: white;
            }
            QTabBar::tab {
                pawww.chinasem.cndding: 8px 15px;
                border: 1px solid #d3d3d3;
                border-bottom: none;
                border-top-left-radius: 5px;
                border-top-right-radius: 5px;
                background: #e9e9e9;
                margin-right: 2px;
            }
            QTabBar::tab:selected {
                background: white;
                border-bottom: 1px solid white;
                margin-bottom: -1px;
            }
            QPushButton {
                background-color: #4CAF50;
                color: white;
                border: none;
                padding: 8px 15px;
                border-radius: 4px;
                min-width: 80px;
            }
            QPushButton:hover {
                background-color: #45a049;
            }
            QPushButton:pressed js{
                background-color: #3d8b40;
            }
            QPushButton:disabled {
                background-color: #cccccc;
            }
            QLineEdit, QTextEdit {
                border: 1px solid #d3d3d3;
                border-radius: 4px;
                padding: 5px;
            }
            QLabel {
                color: #333333;
            }
            QStatusBar {
                background-color: #e9e9e9;
                color: #333333;
            }
            QGroupBox {
                border: 1px solid #d3d3d3;
                border-radius: 5px;
                margin-top: 10px;
                padding-top: 15px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                left: 10px;
                padding: 0 3px;
            }
            QDateTimeEdit {
                padding: 5px;
            }
        """)
    
    def create_send_tab(self):
        """创建发送消息标签页"""
        self.send_tab = QWidget()
        self.tabs.addTab(self.send_tab, " 即时发送")
        
        layout = QVBoxLayout(self.send_tab)
        layout.setSpacing(15)
        
        # 收件人
        recipient_layout = QHBoxLayout()
        recipient_layout.addWidget(QLabel(" 收件人:"))
        self.recipient_input = QLineEdit()
        self.recipient_input.setPlaceholderText("输入微信用户名或备注名")
        recipient_layout.addWidget(self.recipient_input)
        layout.addLayout(recipient_layout)
        
        # 消息内容
        layout.addWidget(QLabel(" 消息内容:"))
        self.message_input = QTextEdit()
        self.message_input.setPlaceholderText("输入要发送的消息...")
        layout.addWidget(self.message_input)
        
        # 文件附件
        file_layout = QHBoxLayout()
        file_layout.addWidget(QLabel(" 附件文件:"))
        self.file_input = QLineEdit()
        self.file_input.setReadOnly(True)
        file_layout.addWidget(self.file_input)
        
        self.browse_button = QPushButton("浏览...")
        self.browse_button.clicked.connect(self.browse_file)
        file_layout.addWidget(self.browse_button)
        layout.addLayout(file_layout)
        
        # 发送按钮
        self.send_button = QPushButton(" 发送消息")
        self.send_button.clicked.connect(lambda: self.send_message(immediate=True))
        layout.addWidget(self.send_button, alignment=Qt.AlignRight)
    
    def create_schedule_tab(self):
        """创建定时发送标签页"""
        self.schedule_tab = QWidget()
        self.tabs.addTab(self.schedule_tab, "⏰ 定时发送")
        
        layout = QVBoxLayout(self.schedule_tab)
        layout.setSpacing(15)
        
        # 定时任务设置组
        schedule_group = QGroupBox("新建定时任务")
        schedule_layout = QVBoxLayout()
        
        # 收件人
        recipient_layout = QHBoxLayout()
        recipient_layout.addWidget(QLabel(" 收件人:"))
        self.schedule_recipient_input = QLineEdit()
        self.schedule_recipient_input.setPlaceholderText("输入微信用户名或备注名")
        recipient_layout.addWidget(self.schedule_recipient_input)
        schedule_layout.addLayout(recipient_layout)
        
        # 消息内容
        schedule_layout.addWidget(QLabel(" 消息内容:"))
        self.schedule_message_input = QTextEdit()
        self.schedule_message_input.setPlaceholderText("输入要发送的消息...")
        schedule_layout.addWidget(self.schedule_message_input)
        
        # 文件附件
        file_layout = QHBoxLayout()
        file_layout.addWidget(QLabel(" 附件文件:"))
        self.schedule_file_input = QLineEdit()
        self.schedule_file_input.setReadOnly(True)
        file_layout.addWidget(self.schedule_file_input)
        
        self.schedule_browse_button = QPushButton("浏览...")
        self.schedule_browse_button.clicked.connect(self.browse_schedule_file)
        file_layout.addWidget(self.schedule_browse_button)
        schedule_layout.addLayout(file_layout)
        
        # 定时设置
        time_layout = QHBoxLayout()
        time_layout.addWidget(QLabel("⏰ 发送时间:"))
        self.datetime_input = QDateTimeEdit()
        self.datetime_input.setDisplayFormat("yyyy-MM-dd HH:mm:ss")
        self.datetime_input.setDateTime(datetime.now())
        time_layout.addWidget(self.datetime_input)
        
        self.repeat_checkbox = QCheckBox("重复发送")
        time_layout.addWidget(self.repeat_checkbox)
        
        self.repeat_interval = QSpinBox()
        self.repeat_interval.setRange(1, 1440)
        self.repeat_interval.setValue(60)
        self.repeat_interval.setSuffix("分钟")
        time_layout.addWidget(self.repeat_interval)
        schedule_layout.addLayout(time_layout)
        
        # 添加任务按钮
        self.add_task_button = QPushButton("➕ 添加定时任务")
        self.add_task_button.clicked.connect(self.add_scheduled_task)
        schedule_layout.addWidget(self.add_task_button)
        
        schedule_group.setLayout(schedule_layout)
        layout.addWidget(schedule_group)
        
        # 任务列表组
        tasks_group = QGroupBox("定时任务列表")
        tasks_layout = QVBoxLayout()
        
        self.tasks_list = QTextEdit()
        self.tasks_list.setReadOnly(True)
        tasks_layout.addWidget(self.tasks_list)
        
        self.clear_tasks_button = QPushButton("️ 清除已完成任务")
        self.clear_tasks_button.clicked.connect(self.clear_completed_tasks)
        tasks_layout.addWidget(self.clear_tasks_button)
        
        tasks_group.setLayout(tasks_layout)
        layout.addWidget(tasks_group)
    
    def create_control_tab(self):
        """创建控制标签页"""
        self.control_tab = QWidget()
        self.tabs.addTab(self.control_tab, "⚙️ 微信控制")
        
        layout = QVBoxLayout(self.control_tab)
        layout.setSpacing(15)
        
        # 微信路径
        path_layout = QHBoxLayout()
        path_layout.addWidget(QLabel(" 微信路径:"))
        self.wechat_path_input = QLineEdit(r'C:\Program Files (x86)\Tencent\WeChat\WeChat.exe')
        path_layout.addWidget(self.wechat_path_input)
        
        self.path_browse_button = QPushButton("浏览...")
        self.path_browse_button.clicked.connect(self.browse_wechat_path)
        path_layout.addWidget(self.path_browse_button)
        layout.addLayout(path_layout)
        
        # 控制按钮
        button_layout = QHBoxLayout()
        self.start_button = QPushButton(" 启动微信")
        self.start_button.clicked.connect(self.start_wechat)
        button_layout.addWidget(self.start_button)
        
        self.active_button = QPushButton(" 激活窗口")
        self.active_button.clicked.connect(self.active_wechat)
        button_layout.addWidget(self.active_button)
        
        self.quit_button = QPushButton("❌ 退出微信")
        self.quit_button.clicked.connect(self.quit_wechat)
        button_layout.addWidget(self.quit_button)
        layout.addLayout(button_layout)
        
        # 日志区域
        layout.addWidget(QLabel(" 操作日志:"))
        self.log_output = QTextEdit()
        self.log_output.setReadOnly(True)
        layout.addWidget(self.log_output)
    
    def browse_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "所有文件 (*.*)")
        if file_path:
            self.file_input.setText(file_path)
    
    def browse_schedule_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "所有文件 (*.*)")
        if file_path:
            self.schedule_file_input.setText(file_path)
    
    def browse_wechat_path(self):
        file_path, _ = QFileDialog.getOpenFileName(
            self, "选择微信程序", "", "可执行文件 (*.exe)")
        if file_path:
            self.wechat_path_input.setText(file_path)
    
    def log_message(self, message):
        """添加日志消息"""
        self.log_output.append(f"[{datetime.now().strftime('%H:%M:%S')}] {message}")
    
    def update_status(self, message, is_success=True):
        """更新状态栏"""
        emoji = "" if is_success else ""
        self.status_bar.showMessage(f"{emoji} {message}")
    
    def send_message(self, recipient=None, message=None, file_path=None, immediate=False):
        """发送消息的核心方法"""
        if immediate:
            recipient = self.recipient_input.text().strip()
            message = self.message_input.toPlainText().strip()
            file_path = self.file_input.text().strip()
        
        if not recipient:
            QMessageBox.warning(self, "警告", "请输入收件人")
            return False
        
        if not message and not file_path:
            QMessageBox.warning(self, "警告", "请输入消息内容或选择文件")
            return False
        
        # 检查文件是否存在
        if file_path and not os.path.exists(file_path):
            QMessageBox.warning(self, "警告", f"文件不存在: {file_path}")
            return False
        
        if immediate:
            self.send_button.setEnabled(False)
            self.status_bar.showMessage(" 正在发送消息...")
        
        def send():
            try:
                if message:
                    wechat_send_msg(recipient, message)
                    self.log_message(f"文本消息已发送给: {recipient}")
                
                if file_path:
                    # 确保文件路径是绝对路径
                    abs_file_path = os.path.abspath(file_path)
                    if not os.path.exists(abs_file_path):
                        raise Exception(f"文件不存在: {abs_file_path}")
                    
                    msg = f"全路径文件名:{abs_file_path}"
                    wechat_send_msg(recipient, msg)
                    self.log_message(f"文件已发送: {abs_file_path}")
                
                return "消息发送成功"
            except Exception as e:
                raise Exception(f"发送失败: {str(e)}")
        
        if immediate:
            self.worker = WorkerThread(send)
            self.worker.finished.connect(lambda msg, success: self.on_operation_finished(mwww.chinasem.cnsg, success, "send"))
            self.worker.start()
        else:
            try:
                send()
                return True
            except Exception as e:
                self.log_message(f"定时发送失败: {str(e)}")
                return False
    
    def add_scheduled_task(self):
        """添加定时任务"""
        recipient = self.schedule_recipient_input.text().strip()
        message = self.schedule_message_input.toPlainText().strip()
        file_path = self.schedule_file_input.text().strip()
        send_time = self.datetime_input.dateTime().toPyDateTime()
        repeat = self.repeat_checkbox.isChecked()
        interval = self.repeat_interval.value()
        
        if not recipient:
            QMessageBox.warning(self, "警告", "请输入收件人")
            return
        
        if not message and not file_path:
            QMessageBox.warning(self, "警告", "请输入消息内容或选择文件")
            return
        
        # 检查文件是否存在
        if file_path and not os.path.exists(file_path):
            QMessageBox.warning(self, "警告", f"文件不存在: {file_path}")
            return
        
        task = {
            "recipient": recipient,
            "message": message,
            "file_path": os.path.abspath(file_path) if file_path else "",
            "send_time": send_time,
            "repeat": repeat,
            "interval": interval,
            "completed": False
        }
        
        self.scheduled_tasks.append(task)
        self.update_tasks_list()
        QMessageBox.information(self, "成功", "定时任务已添加")
    
    def update_tasks_list(self):
        """更新任务列表显示"""
        self.tasks_list.clear()
        now = datetime.now()
        
        for i, task in enumerate(self.scheduled_tasks, 1):
            status = "✅ 已完成" if task["completed"] else "⏳ 等待中"
            time_left = (task["send_time"] - now).total_seconds()
            
            if time_left > 0:
                time_str = f"剩余: {int(time_left//3600)}小时{int((time_left%3600)//60)}分钟"
            else:
                time_str = "已到时间"
            
            repeat_str = f", 每{task['interval']}分钟重复" if task["repeat"] else ""
            
            self.tasks_list.append(
                f"{i}. {status} | {time_str}{repeat_str}\n"
                f"收件人: {task['recipient']}\n"
                f"内容: {task['message'][:30]}{'...' if len(task['message'])>30 else ''}\n"
                f"附件: {task['file_path'] if task['file_path'] else '无'}\n"
                f"发送时间: {task['send_time'].strftime('%Y-%m-%d %H:%M:%S')}\n"
                "─" * 50
            )
    
    def check_scheduled_tasks(self):
        """检查并执行定时任务"""
        now = datetime.now()
        any_task_executed = False
        
        for task in self.scheduled_tasks:
            if not task["completed"] and now >= task["send_time"]:
                # 执行任务
                success = self.send_message(
                    recipient=task["recipient"],
                    message=task["message"],
                    file_path=task["file_path"]
                )
                
                if success:
                    task["completed"] = True
                    self.log_message(f"定时任务执行成功: 发送给 {task['recipient']}")
                    
                    # 如果是重复任务,重新设置下次执行时间
                    if task["repeat"]:
                        task["send_time"] = now + timedelta(minutes=task["interval"])
                        task["completed"] = False
                
                any_task_executed = True
        
        if any_task_executed:
            self.update_tasks_list()
    
    def clear_completed_tasks(self):
        """清除已完成的任务"""
        self.scheduled_tasks = [task for task in self.scheduled_tasks if not task["completed"]]
        self.update_tasks_list()
        QMessageBox.information(self, "提示", "已清除所有已完成任务")
    
    def start_wechat(self):
        wechat_path = self.wechat_path_input.text().strip()
        
        if not os.path.exists(wechat_path):
            QMessageBox.warning(self, "警告", "微信路径无效,请重新选择")
            return
        
        self.start_button.setEnabled(False)
        self.status_bar.showMessage(" 正在启动微信...")
        
        def start():
            try:
                wechat_start(wechat_path)
                return "微信启动成功"
            except Exception as e:
                raise Exception(f"启动失败: {str(e)}")
        
        self.worker = WorkerThread(start)
        self.worker.finished.connect(lambda msg, success: self.on_operation_finished(msg, success, "start"))
        self.worker.start()
    
    def active_wechat(self):
        self.active_button.setEnabled(False)
        self.status_bar.showMessage(" 正在激活微信窗口...")
        
        def active():
            try:
                wechat_active()
                return "微信窗口已激活"
            except Exception as e:
                raise Exception(f"激活失败: {str(e)}")
        
        self.worker = WorkerThread(active)
        self.worker.finished.connect(lambda msg, success: self.on_operation_finished(msg, success, "active"))
        self.worker.start()
    
    def quit_wechat(self):
        self.quit_button.setEnabled(False)
        self.status_bar.showMessage(" 正在退出微信...")
        
        def quit():
            try:
                wechat_quit()
                return "微信已退出"
            except Exception as e:
                raise Exception(f"退出失败: {str(e)}")
        
        self.worker = WorkerThread(quit)
        self.worker.finished.connect(lambda msg, success: self.on_operation_finished(msg, success, "quit"))
        self.worker.start()
    
    def on_operation_finished(self, message, success, operation_type):
        """操作完成后的回调"""
        self.update_status(message, success)
        self.log_message(message)
        
        if not success:
            QMessageBox.critical(self, "错误", message)
        
        # 重新启用按钮
        if operation_type == "send":
            self.send_button.setEnabled(True)
        elif operation_type == "start":
            self.start_button.setEnabled(True)
        elif operation_type == "active":
            self.active_button.setEnabled(True)
        elif operation_type == "quit":
            self.quit_button.setEnabled(True)

def ifProcessRunning(process_name='WeChat.exe'):
    pl = psutil.pids()
    result = "PROCESS_IS_NOT_RUNNING"
    for pid in pl:
        try:
            if psutil.Process(pid).name() == process_name:
                if isinstance(pid, int):
                    result = "PROCESS_IS_RUNNING"
        except (psutil.NoSuchProcess, psutil.AccessDenied):
            continue
    return result

def wechat_start(wechat_path):
    os.startfile(wechat_path)
    loginwin = uiautomation.PaneControl(searchDepth=1, ClassName='WeChatLoginWndForPC', Name='微信')
    try:
        loginwin.ButtonControl(Name='进入微信').Click()
    except:
        loginwin.ButtonControl(Name='登录').Click()

def wechat_active():
    uiautomation.uiautomation.TIME_OUT_SECOND = 2
    if ifProcessRunning() == "PROCESS_IS_RUNNING":
        try:
            desktop = uiautomation.PaneControl(Name='任务栏')
            desktop.SendKeys('{Ctrl}{Alt}w')
        except:
            os.system('taskkill /F /im "WeChat.exe" >nul')
            wechat_start(r'C:\Program Files (x86)\Tencent\WeChat\WeChat.exe')
    else:
        wechat_start(r'C:\Program Files (x86)\Tencent\WeChat\WeChat.exe')
    uiautomation.uiautomation.TIME_OUT_SECOND = 20
    wechatWindow = uiautomation.WindowControl(searchDepth=1, className='WeChatMainWndForPC', Name='微信')
    try:
        wechatWindow.Restore()
        wechatWindow.MoveToCenter()
        wechatWindow.SetTopmost(True)
    except:
        print('未能成功激活微信窗口')

def wechat_send_msg(send_to='微信用户名', msg='要发送的消息'):
    wechat_active()
    wechatWindow = uiautomation.WindowControl(searchDepth=1, className='WeChatMainWndForPC', Name='微信')
    
    # 搜索联系人
    search_edit = wechatWindow.EditControl(Name="搜索")
    search_edit.Click()
    search_edit.SendKeys(send_to, 0.5)
 www.chinasem.cn   time.sleep(1)  # 等待搜索结果
    
    # 按回车键选择联系人
    search_edit.SendKeys('{enter}')
    time.sleep(2)  # 增加等待时间确保聊天窗口加载
    
    if msg[:7] != '全路径文件名:':
        # 查找消息输入框 - 使用更可靠的方法
        chat_input = None
        for _ in range(5):  # 增加重试次数
            try:
                # 尝试多种方式查找输入框
                chat_input = wechatWindow.EditControl(Name="输入")
                if not chat_input.Exists():
                    chat_input = wechatWindow.EditControl(automationId="editArea")
                if not chat_input.Exists():
                    chat_input = wechatWindow.EditControl(ClassName="Edit")
                
                if chat_input and chat_input.Exists():
                    break
            except Exception as e:
                print(f"查找输入框时出错: {str(e)}")
            time.sleep(1)
        
        if not chat_input or not chat_input.Exists():
            raise Exception("找不到消息输入框,请确保已打开正确的聊天窗口")
        
        chat_input.SendKeys(msg, 0.03)
        
        # 查找发送按钮 - 使用更可靠的方法
        send_button = None
        for _ in range(5):  # 增加重试次数
            try:
                send_button = wechatWindow.ButtonControl(Name="发送(S)")
                if not send_button.Exists():
                    send_button = wechatWindow.ButtonControl(automationId="sendBtn")
                if not send_button.Exists():
                    send_button = wechatWindow.ButtonControl(ClassName="Button", foundIndex=1)
                
                if send_button and send_button.Exists():
                    break
            except Exception as e:
                print(f"查找发送按钮时出错: {str(e)}")
            time.sleep(1)
        
        if not send_button or not send_button.Exists():
            raise Exception("找不到发送按钮")
        
        send_button.Click()
    else:
        file_path = msg[7:]
        if not os.path.exists(file_path):
            raise Exception(f"文件不存在: {file_path}")
            
        # 查找文件发送按钮 - 使用更可靠的方法
        file_button = None
        for _ in range(5):  # 增加重试次数
            try:
                file_button = wechatWindow.ButtonControl(Name="发送文件")
                if not file_button.Exists():
                    file_button = wechatWindow.ButtonControl(automationId="fileBtn")
                
                if file_button and file_button.Exists():
                    break
            except Exception as e:
                print(f"查找文件发送按钮时出错: {str(e)}")
            time.sleep(1)
        
        if not file_button or not file_button.Exists():
            raise Exception("找不到文件发送按钮")
        
        file_button.Click()
        
        # 等待文件选择对话框出现
        time.sleep(2)
        file_dialog = uiautomation.WindowControl(Name="打开")
        if not file_dialog.Exists():
            raise Exception("文件选择对话框未出现")
            
        # 输入文件路径
        filename_edit = file_dialog.EditControl(Name="文件名(N):")
        filename_edit.SendKeys(file_path)
        time.sleep(0.5)
        filename_edit.SendKeys('{enter}')
        
        # 等待文件上传
        time.sleep(3)
        
        # 查找最终发送按钮 - 使用更可靠的方法
        final_send_button = None
        for _ in range(5):  # 增加重试次数
            try:
                final_send_button = wechatWindow.ButtonControl(Name="发送(1)")
                if not final_send_button.Exists():
                    final_send_button = wechatWindow.ButtonControl(automationId="sendBtn")
                
                if final_send_button and final_send_button.Exists():
                    break
            except Exception as e:
                print(f"查找最终发送按钮时出错: {str(e)}")
            time.sleep(1)
        
        if not final_send_button or not final_send_button.Exists():
            raise Exception("找不到最终发送按钮")
        
        final_send_button.Click()
    
    wechatWindow.SetTopmost(False)
    wechatWindow.Minimize()

def wechat_quit():
    if ifProcessRunning() == "PROCESS_IS_RUNNING":
        os.system('taskkill /F /im "WeChat.exe" >nul')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = WeChatAutomationApp()
    window.show()
    sys.exit(app.exec_())

技术难点与解决方案

1. 窗口控件定位问题

问题现象:微信版本更新导致自动化失效

解决方案:

# 多重定位策略
chat_input = None
for control_type in [("Name","输入"), ("automationId","editArea"), ("ClassName","Edit")]:
    chat_input = wechatWindow.EditControl(**{control_type[0]: control_type[1]})
    if chat_input.Exists():
        break

2. 定时任务精度问题

对比方案:

方案精度CPU占用可靠性
QTimer轮询1秒
Python threading0.1秒
Windows定时器毫秒级

选择依据:综合业务需求选择QTimer方案

扩展知识

1. UI自动化技术对比

技术方案优点缺点
uiautomation微软官方,支持Win32文档较少
PyAutoGUI跨平台,简单易用无法处理复杂控件
Selenium支持Web自动化不适用桌面应用

2. 企业级优化建议

加入配置文件:使用config.ini保存常用设置

增加日志系统:采用logging模块实现分级日志

打包发布:使用PyInstaller生成exe

添加单元测试:确保核心功能稳定性

总结

本文详细剖析了一个功能完备的微信自动化工具的开发全过程,关键技术要点包括:

  • PyQt5的MVC架构实践:实现界面与逻辑分离
  • 防御式编程思想:完善的异常处理体系
  • 自动化测试思维:控件查找的重试机制
  • 用户体验优化:状态反馈+日志系统

未来优化方向:

  • 增加联系人自动补全功能
  • 实现消息模板管理
  • 加入多账号支持
  • 开发插件系统

到此这篇关于如何基于Python开发一个微信自动化工具的文章就介绍到这了,更多相关Python微信自动化内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持China编程(www.chinasem.cn)!

这篇关于如何基于Python开发一个微信自动化工具的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1154818

相关文章

VSCode开发中有哪些好用的插件和快捷键

《VSCode开发中有哪些好用的插件和快捷键》作为全球最受欢迎的编程工具,VSCode的快捷键体系是提升开发效率的核心密码,:本文主要介绍VSCode开发中有哪些好用的插件和快捷键的相关资料,文中... 目录前言1、vscode插件1.1 Live-server1.2 Auto Rename Tag1.3

Python自动化提取多个Word文档的文本

《Python自动化提取多个Word文档的文本》在日常工作和学习中,我们经常需要处理大量的Word文档,本文将深入探讨如何利用Python批量提取Word文档中的文本内容,帮助你解放生产力,感兴趣的小... 目录为什么需要批量提取Word文档文本批量提取Word文本的核心技术与工具安装 Spire.Doc

C#高效实现在Word文档中自动化创建图表的可视化方案

《C#高效实现在Word文档中自动化创建图表的可视化方案》本文将深入探讨如何利用C#,结合一款功能强大的第三方库,实现在Word文档中自动化创建图表,为你的数据呈现和报告生成提供一套实用且高效的解决方... 目录Word文档图表自动化:为什么选择C#?从零开始:C#实现Word文档图表的基本步骤深度优化:C

Python中Request的安装以及简单的使用方法图文教程

《Python中Request的安装以及简单的使用方法图文教程》python里的request库经常被用于进行网络爬虫,想要学习网络爬虫的同学必须得安装request这个第三方库,:本文主要介绍P... 目录1.Requests 安装cmd 窗口安装为pycharm安装在pycharm设置中为项目安装req

Python容器转换与共有函数举例详解

《Python容器转换与共有函数举例详解》Python容器是Python编程语言中非常基础且重要的概念,它们提供了数据的存储和组织方式,下面:本文主要介绍Python容器转换与共有函数的相关资料,... 目录python容器转换与共有函数详解一、容器类型概览二、容器类型转换1. 基本容器转换2. 高级转换示

使用Python将PDF表格自动提取并写入Word文档表格

《使用Python将PDF表格自动提取并写入Word文档表格》在实际办公与数据处理场景中,PDF文件里的表格往往无法直接复制到Word中,本文将介绍如何使用Python从PDF文件中提取表格数据,并将... 目录引言1. 加载 PDF 文件并准备 Word 文档2. 提取 PDF 表格并创建 Word 表格

使用Python实现局域网远程监控电脑屏幕的方法

《使用Python实现局域网远程监控电脑屏幕的方法》文章介绍了两种使用Python在局域网内实现远程监控电脑屏幕的方法,方法一使用mss和socket,方法二使用PyAutoGUI和Flask,每种方... 目录方法一:使用mss和socket实现屏幕共享服务端(被监控端)客户端(监控端)方法二:使用PyA

Python列表的创建与删除的操作指南

《Python列表的创建与删除的操作指南》列表(list)是Python中最常用、最灵活的内置数据结构之一,它支持动态扩容、混合类型、嵌套结构,几乎无处不在,但你真的会创建和删除列表吗,本文给大家介绍... 目录一、前言二、列表的创建方式1. 字面量语法(最常用)2. 使用list()构造器3. 列表推导式

Python使用Matplotlib和Seaborn绘制常用图表的技巧

《Python使用Matplotlib和Seaborn绘制常用图表的技巧》Python作为数据科学领域的明星语言,拥有强大且丰富的可视化库,其中最著名的莫过于Matplotlib和Seaborn,本篇... 目录1. 引言:数据可视化的力量2. 前置知识与环境准备2.1. 必备知识2.2. 安装所需库2.3

Agent开发核心技术解析以及现代Agent架构设计

《Agent开发核心技术解析以及现代Agent架构设计》在人工智能领域,Agent并非一个全新的概念,但在大模型时代,它被赋予了全新的生命力,简单来说,Agent是一个能够自主感知环境、理解任务、制定... 目录一、回归本源:到底什么是Agent?二、核心链路拆解:Agent的"大脑"与"四肢"1. 规划模