【开源神器】只需3分钟,教你打造属于自己的微信自动化发送工具!

【开源神器】只需3分钟,教你打造属于自己的微信自动化发送工具!

🚀彻底解放双手!微信消息自动化发送脚本工具实战教程

🌈 个人主页:创客白泽 - ZEEKLOG博客
🔥 系列专栏:🐍《Python开源项目实战》
💡 热爱不止于代码,热情源自每一个灵感闪现的夜晚。愿以开源之火,点亮前行之路。
👍 如果觉得这篇文章有帮助,欢迎您一键三连,分享给更多人哦
请添加图片描述
在这里插入图片描述

📌 概述

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

技术栈亮点

  • PyQt5构建美观的GUI界面
  • uiautomation实现Windows UI自动化
  • psutil进行进程管理
  • 多线程处理保持UI响应
  • 完整的异常处理机制

🛠️ 功能全景

1. 核心功能模块

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

2. 特色功能

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

🎥 效果展示

1. 主界面概览

在这里插入图片描述

2. 定时任务配置

在这里插入图片描述

3. 操作日志演示

在这里插入图片描述


在这里插入图片描述

🔧 实现步骤详解

1. 环境准备

pip install pyqt5 psutil uiautomation 

2. 工程结构设计

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

3. 核心实现流程

  1. GUI框架搭建:采用QMainWindow+TabWidget布局
  2. 工作线程封装:WorkerThread类继承QThread
  3. 定时任务调度:QTimer秒级轮询检查
  4. UI自动化控制:uiautomation操作微信窗口
  5. 异常处理体系:三级错误捕获机制

💻 代码深度解析

1. 多线程任务处理

classWorkerThread(QThread): finished = pyqtSignal(str,bool)# 信号参数:消息内容, 是否成功defrun(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. 微信窗口控制核心

defwechat_active():# 超时设置优化 uiautomation.uiautomation.TIME_OUT_SECOND =2if 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. 定时任务调度系统

defcheck_scheduled_tasks(self): now = datetime.now()for task in self.scheduled_tasks:ifnot 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"]=Falseelse: 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, QSpinBox)from PyQt5.QtCore import Qt, QThread, pyqtSignal, QTimer from PyQt5.QtGui import QIcon, QFont classWorkerThread(QThread): finished = pyqtSignal(str,bool)# message, successdef__init__(self, func,*args,**kwargs):super().__init__() self.func = func self.args = args self.kwargs = kwargs defrun(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)classWeChatAutomationApp(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()defset_style(self): self.setStyleSheet(""" QMainWindow { background-color: #f5f5f5; } QTabWidget::pane { border: 1px solid #d3d3d3; border-radius: 5px; padding: 5px; background: white; } QTabBar::tab { padding: 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 { 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; } """)defcreate_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)defcreate_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)defcreate_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)defbrowse_file(self): file_path, _ = QFileDialog.getOpenFileName(self,"选择文件","","所有文件 (*.*)")if file_path: self.file_input.setText(file_path)defbrowse_schedule_file(self): file_path, _ = QFileDialog.getOpenFileName(self,"选择文件","","所有文件 (*.*)")if file_path: self.schedule_file_input.setText(file_path)defbrowse_wechat_path(self): file_path, _ = QFileDialog.getOpenFileName( self,"选择微信程序","","可执行文件 (*.exe)")if file_path: self.wechat_path_input.setText(file_path)deflog_message(self, message):"""添加日志消息""" self.log_output.append(f"[{datetime.now().strftime('%H:%M:%S')}] {message}")defupdate_status(self, message, is_success=True):"""更新状态栏""" emoji ="🟢"if is_success else"🔴" self.status_bar.showMessage(f"{emoji}{message}")defsend_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()ifnot recipient: QMessageBox.warning(self,"警告","请输入收件人")returnFalseifnot message andnot file_path: QMessageBox.warning(self,"警告","请输入消息内容或选择文件")returnFalse# 检查文件是否存在if file_path andnot os.path.exists(file_path): QMessageBox.warning(self,"警告",f"文件不存在: {file_path}")returnFalseif immediate: self.send_button.setEnabled(False) self.status_bar.showMessage("🟡 正在发送消息...")defsend():try:if message: wechat_send_msg(recipient, message) self.log_message(f"文本消息已发送给: {recipient}")if file_path:# 确保文件路径是绝对路径 abs_file_path = os.path.abspath(file_path)ifnot 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(msg, success,"send")) self.worker.start()else:try: send()returnTrueexcept Exception as e: self.log_message(f"定时发送失败: {str(e)}")returnFalsedefadd_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()ifnot recipient: QMessageBox.warning(self,"警告","请输入收件人")returnifnot message andnot file_path: QMessageBox.warning(self,"警告","请输入消息内容或选择文件")return# 检查文件是否存在if file_path andnot 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,"成功","定时任务已添加")defupdate_tasks_list(self):"""更新任务列表显示""" self.tasks_list.clear() now = datetime.now()for i, task inenumerate(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]}{'...'iflen(task['message'])>30else''}\n"f"附件: {task['file_path']if task['file_path']else'无'}\n"f"发送时间: {task['send_time'].strftime('%Y-%m-%d %H:%M:%S')}\n""─"*50)defcheck_scheduled_tasks(self):"""检查并执行定时任务""" now = datetime.now() any_task_executed =Falsefor task in self.scheduled_tasks:ifnot 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 =Trueif any_task_executed: self.update_tasks_list()defclear_completed_tasks(self):"""清除已完成的任务""" self.scheduled_tasks =[task for task in self.scheduled_tasks ifnot task["completed"]] self.update_tasks_list() QMessageBox.information(self,"提示","已清除所有已完成任务")defstart_wechat(self): wechat_path = self.wechat_path_input.text().strip()ifnot os.path.exists(wechat_path): QMessageBox.warning(self,"警告","微信路径无效,请重新选择")return self.start_button.setEnabled(False) self.status_bar.showMessage("🟡 正在启动微信...")defstart():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()defactive_wechat(self): self.active_button.setEnabled(False) self.status_bar.showMessage("🟡 正在激活微信窗口...")defactive():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()defquit_wechat(self): self.quit_button.setEnabled(False) self.status_bar.showMessage("🟡 正在退出微信...")defquit():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()defon_operation_finished(self, message, success, operation_type):"""操作完成后的回调""" self.update_status(message, success) self.log_message(message)ifnot 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)defifProcessRunning(process_name='WeChat.exe'): pl = psutil.pids() result ="PROCESS_IS_NOT_RUNNING"for pid in pl:try:if psutil.Process(pid).name()== process_name:ifisinstance(pid,int): result ="PROCESS_IS_RUNNING"except(psutil.NoSuchProcess, psutil.AccessDenied):continuereturn result defwechat_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()defwechat_active(): uiautomation.uiautomation.TIME_OUT_SECOND =2if 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('未能成功激活微信窗口')defwechat_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) time.sleep(1)# 等待搜索结果# 按回车键选择联系人 search_edit.SendKeys('{enter}') time.sleep(2)# 增加等待时间确保聊天窗口加载if msg[:7]!='全路径文件名:':# 查找消息输入框 - 使用更可靠的方法 chat_input =Nonefor _ inrange(5):# 增加重试次数try:# 尝试多种方式查找输入框 chat_input = wechatWindow.EditControl(Name="输入")ifnot chat_input.Exists(): chat_input = wechatWindow.EditControl(automationId="editArea")ifnot chat_input.Exists(): chat_input = wechatWindow.EditControl(ClassName="Edit")if chat_input and chat_input.Exists():breakexcept Exception as e:print(f"查找输入框时出错: {str(e)}") time.sleep(1)ifnot chat_input ornot chat_input.Exists():raise Exception("找不到消息输入框,请确保已打开正确的聊天窗口") chat_input.SendKeys(msg,0.03)# 查找发送按钮 - 使用更可靠的方法 send_button =Nonefor _ inrange(5):# 增加重试次数try: send_button = wechatWindow.ButtonControl(Name="发送(S)")ifnot send_button.Exists(): send_button = wechatWindow.ButtonControl(automationId="sendBtn")ifnot send_button.Exists(): send_button = wechatWindow.ButtonControl(ClassName="Button", foundIndex=1)if send_button and send_button.Exists():breakexcept Exception as e:print(f"查找发送按钮时出错: {str(e)}") time.sleep(1)ifnot send_button ornot send_button.Exists():raise Exception("找不到发送按钮") send_button.Click()else: file_path = msg[7:]ifnot os.path.exists(file_path):raise Exception(f"文件不存在: {file_path}")# 查找文件发送按钮 - 使用更可靠的方法 file_button =Nonefor _ inrange(5):# 增加重试次数try: file_button = wechatWindow.ButtonControl(Name="发送文件")ifnot file_button.Exists(): file_button = wechatWindow.ButtonControl(automationId="fileBtn")if file_button and file_button.Exists():breakexcept Exception as e:print(f"查找文件发送按钮时出错: {str(e)}") time.sleep(1)ifnot file_button ornot file_button.Exists():raise Exception("找不到文件发送按钮") file_button.Click()# 等待文件选择对话框出现 time.sleep(2) file_dialog = uiautomation.WindowControl(Name="打开")ifnot 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 =Nonefor _ inrange(5):# 增加重试次数try: final_send_button = wechatWindow.ButtonControl(Name="发送(1)")ifnot final_send_button.Exists(): final_send_button = wechatWindow.ButtonControl(automationId="sendBtn")if final_send_button and final_send_button.Exists():breakexcept Exception as e:print(f"查找最终发送按钮时出错: {str(e)}") time.sleep(1)ifnot final_send_button ornot final_send_button.Exists():raise Exception("找不到最终发送按钮") final_send_button.Click() wechatWindow.SetTopmost(False) wechatWindow.Minimize()defwechat_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 =Nonefor 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. 企业级优化建议

  1. 加入配置文件:使用config.ini保存常用设置
  2. 增加日志系统:采用logging模块实现分级日志
  3. 打包发布:使用PyInstaller生成exe
  4. 添加单元测试:确保核心功能稳定性

✨ 总结

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

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

未来优化方向

  • 增加联系人自动补全功能
  • 实现消息模板管理
  • 加入多账号支持
  • 开发插件系统
作者:创客白泽
版权声明:本文采用CC BY-NC-SA 4.0协议
最后更新:2025年05月27日

Read more

基于C++构建DeepSeek大模型推理SDK:从架构设计到工程落地

基于C++构建DeepSeek大模型推理SDK:从架构设计到工程落地

这里写目录标题 * 前言 * 一、 云端环境配置与鉴权机制 * 二、 C++ SDK 核心数据结构设计 * 1. 消息与配置实体 * 2. 模型信息与会话管理 * 三、 抽象接口层设计:策略模式的应用 * 四、 DeepSeek 适配器实现 * 1. 初始化逻辑 * 2. 信息查询接口 * 五、 单元测试与质量保证 * 1. 测试环境构建 * 2. 日志系统 * 六、 CMake 构建系统配置 * 1. 依赖管理 * 2. 编译目标与链接 * 七、 编译与调试过程 前言 在高性能计算与大模型(LLM)应用开发的浪潮中,C++凭借其卓越的内存管理能力和运行时效率,成为了构建底层推理SDK的首选语言。本文将深入剖析如何从零开始,设计并实现一个能够调用DeepSeek模型的C++ SDK。全通过程涵盖了云端鉴权、面向对象架构设计、多态接口封装、

By Ne0inhk
同名成员到底调用谁?C++ 隐藏规则你真的会吗?

同名成员到底调用谁?C++ 隐藏规则你真的会吗?

欢迎来到 s a y − f a l l 的文章 欢迎来到say-fall的文章 欢迎来到say−fall的文章 🌈say-fall:个人主页🚀专栏:《手把手教你学会C++》 | 《C语言从零开始到精通》 | 《数据结构与算法》 | 《小游戏与项目》💪格言:做好你自己,才能吸引更多人,与他们共赢,这才是最好的成长方式。 前言: 对于c++来说,有三大核心特性,是面向对象编程(OOP)的经典三要素:封装、继承、多态。这三个特性是 C++ 区别于纯面向过程语言(如 C)的核心,也是理解 C++ 面向对象思想的关键。之前利用类和对象的思想和STL中的适配器:queue和stack了解过封装,本篇文章就详细介绍一下继承这个特性 文章目录 * 前言: * 正文: * 一、

By Ne0inhk
Java新手入门:从零开始安装JDK并配置环境变量

Java新手入门:从零开始安装JDK并配置环境变量

作者:默语佬 ZEEKLOG技术博主 原创文章,转载请注明出处 前言 作为一名Java程序员,相信很多小伙伴都经历过刚入门时的迷茫:“Java到底怎么学?从哪里开始?”,而安装JDK并配置环境变量就是迈向Java世界的第一步。 今天这篇文章,我就来手把手教大家从零开始安装JDK并配置环境变量。文章会配有详细的截图和步骤说明,即使你是完全的小白,也能轻松搞定! 阅读对象:Java新手、编程入门者、对Java感兴趣的同学 难度等级:⭐(入门级) 预计时间:30分钟 目录 1. JDK是什么?为什么要安装JDK? 2. JDK下载:选择合适的版本 3. JDK安装:一步步图形化安装 4. 环境变量配置:Windows系统配置 5. 验证安装:确认JDK安装成功 6. 常见问题及解决方案 7. 总结与下一步学习建议 JDK是什么?为什么要安装JDK? JDK的概念 JDK是Java Development Kit的缩写,

By Ne0inhk
Java 大视界 -- Java 大数据在智能物流仓储货位优化与库存周转率提升中的应用实战

Java 大视界 -- Java 大数据在智能物流仓储货位优化与库存周转率提升中的应用实战

Java 大视界 -- Java 大数据在智能物流仓储货位优化与库存周转率提升中的应用实战 * 引言: * 正文: * 一、传统智能物流仓储的困境与挑战 * 1.1 货位管理:无序中的效率瓶颈 * 1.2 库存管理:积压与缺货并存的矛盾 * 二、Java 大数据:智能物流仓储的破局之道 * 2.1 全链路数据采集与处理:构建仓储数字孪生体 * 2.2 智能货位优化:算法驱动的空间革命 * 2.3 库存周转率提升:精准预测与智能协同 * 三、实战案例:京东亚洲一号智能仓的数字化转型 * 3.1 货位优化实践 * 3.2 库存管理创新 * 四、技术挑战与未来展望 * 结束语: * 🗳️参与投票和联系我: 引言: 嘿,亲爱的 Java

By Ne0inhk