最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何基于Python開發(fā)一個微信自動化工具

 更新時間:2025年05月27日 14:35:43   作者:創(chuàng)客白澤  
在當(dāng)今數(shù)字化辦公場景中,自動化工具已成為提升工作效率的利器,本文將深入剖析一個基于Python的微信自動化工具開發(fā)全過程,有需要的小伙伴可以了解下

概述

在當(dāng)今數(shù)字化辦公場景中,自動化工具已成為提升工作效率的利器。本文將深入剖析一個基于Python的微信自動化工具開發(fā)全過程,該工具集成了即時消息發(fā)送、定時任務(wù)管理和微信進程控制三大核心功能模塊。

技術(shù)棧亮點:

PyQt5構(gòu)建美觀的GUI界面

uiautomation實現(xiàn)Windows UI自動化

psutil進行進程管理

多線程處理保持UI響應(yīng)

完整的異常處理機制

功能全景

1. 核心功能模塊

模塊名稱功能描述
即時消息發(fā)送支持文本+文件混合發(fā)送,智能識別聯(lián)系人
定時任務(wù)管理精確到秒的定時發(fā)送,支持循環(huán)任務(wù)配置
微信進程控制啟動/激活/退出微信的一鍵操作

2. 特色功能

  • 智能窗口激活:自動置頂微信窗口并居中顯示
  • 文件絕對路徑處理:自動轉(zhuǎn)換相對路徑為絕對路徑
  • 任務(wù)持久化:運行時任務(wù)列表維護
  • 健壯性設(shè)計:多重異常處理+操作狀態(tài)反饋

效果展示

1. 主界面概覽

2. 定時任務(wù)配置

3. 操作日志演示

實現(xiàn)步驟詳解

1. 環(huán)境準備

pip install pyqt5 psutil uiautomation

2. 工程結(jié)構(gòu)設(shè)計

WeChatAutomation/
├── main.py            # 主程序入口
├── wechat.ico         # 程序圖標
└── README.md          # 使用說明

3. 核心實現(xiàn)流程

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

工作線程封裝:WorkerThread類繼承QThread

定時任務(wù)調(diào)度:QTimer秒級輪詢檢查

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

異常處理體系:三級錯誤捕獲機制

代碼深度解析

1. 多線程任務(wù)處理

class WorkerThread(QThread):
    finished = pyqtSignal(str, bool)  # 信號參數(shù):消息內(nèi)容, 是否成功
    
    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)

設(shè)計要點:

  • 采用信號槽機制實現(xiàn)線程間通信
  • 統(tǒng)一錯誤處理接口
  • 支持任意函數(shù)的多線程執(zhí)行

2. 微信窗口控制核心

def wechat_active():
    # 超時設(shè)置優(yōu)化
    uiautomation.uiautomation.TIME_OUT_SECOND = 2  
    if ifProcessRunning():
        try:
            # 快捷鍵激活方案
            desktop = uiautomation.PaneControl(Name='任務(wù)欄')
            desktop.SendKeys('{Ctrl}{Alt}w')
        except:
            # 異常后備方案
            os.system('taskkill /F /im "WeChat.exe"')
            wechat_start()
    else:
        wechat_start()
    
    # 恢復(fù)默認超時
    uiautomation.uiautomation.TIME_OUT_SECOND = 20  
    wechatWindow = uiautomation.WindowControl(
        searchDepth=1, 
        className='WeChatMainWndForPC', 
        Name='微信'
    )

優(yōu)化策略:

動態(tài)調(diào)整UI查找超時時間

多方案組合提高成功率

異常后的自動恢復(fù)機制

3. 定時任務(wù)調(diào)度系統(tǒng)

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"]:  # 重復(fù)任務(wù)處理
                task["send_time"] = now + timedelta(
                    minutes=task["interval"]
                )
                task["completed"] = False
            else:
                task["completed"] = True

算法特點:

低精度定時檢查(1秒間隔)

支持單次/循環(huán)任務(wù)模式

非阻塞式任務(wù)執(zhí)行

源碼獲取

# -*- 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

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("微信自動化發(fā)送工具---BY 白澤")
        self.setGeometry(100, 100, 787, 639)
        self.setWindowIcon(QIcon("wechat.ico"))  # 替換為你的圖標文件
        
        # 定時任務(wù)列表
        self.scheduled_tasks = []
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.check_scheduled_tasks)
        self.timer.start(1000)  # 每秒檢查一次
        
        # 設(shè)置全局字體
        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)
        
        # 創(chuàng)建標簽頁
        self.tabs = QTabWidget()
        self.main_layout.addWidget(self.tabs)
        
        # 創(chuàng)建各個標簽頁
        self.create_send_tab()
        self.create_schedule_tab()
        self.create_control_tab()
        
        # 狀態(tài)欄
        self.status_bar = QStatusBar()
        self.setStatusBar(self.status_bar)
        self.status_bar.showMessage("?? 就緒")
        
        # 樣式設(shè)置
        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 {
                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;
            }
        """)
    
    def create_send_tab(self):
        """創(chuàng)建發(fā)送消息標簽頁"""
        self.send_tab = QWidget()
        self.tabs.addTab(self.send_tab, "?? 即時發(fā)送")
        
        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)
        
        # 消息內(nèi)容
        layout.addWidget(QLabel("?? 消息內(nèi)容:"))
        self.message_input = QTextEdit()
        self.message_input.setPlaceholderText("輸入要發(fā)送的消息...")
        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)
        
        # 發(fā)送按鈕
        self.send_button = QPushButton("?? 發(fā)送消息")
        self.send_button.clicked.connect(lambda: self.send_message(immediate=True))
        layout.addWidget(self.send_button, alignment=Qt.AlignRight)
    
    def create_schedule_tab(self):
        """創(chuàng)建定時發(fā)送標簽頁"""
        self.schedule_tab = QWidget()
        self.tabs.addTab(self.schedule_tab, "? 定時發(fā)送")
        
        layout = QVBoxLayout(self.schedule_tab)
        layout.setSpacing(15)
        
        # 定時任務(wù)設(shè)置組
        schedule_group = QGroupBox("新建定時任務(wù)")
        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)
        
        # 消息內(nèi)容
        schedule_layout.addWidget(QLabel("?? 消息內(nèi)容:"))
        self.schedule_message_input = QTextEdit()
        self.schedule_message_input.setPlaceholderText("輸入要發(fā)送的消息...")
        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)
        
        # 定時設(shè)置
        time_layout = QHBoxLayout()
        time_layout.addWidget(QLabel("? 發(fā)送時間:"))
        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("重復(fù)發(fā)送")
        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)
        
        # 添加任務(wù)按鈕
        self.add_task_button = QPushButton("? 添加定時任務(wù)")
        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)
        
        # 任務(wù)列表組
        tasks_group = QGroupBox("定時任務(wù)列表")
        tasks_layout = QVBoxLayout()
        
        self.tasks_list = QTextEdit()
        self.tasks_list.setReadOnly(True)
        tasks_layout.addWidget(self.tasks_list)
        
        self.clear_tasks_button = QPushButton("??? 清除已完成任務(wù)")
        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):
        """創(chuàng)建控制標簽頁"""
        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)
        
        # 日志區(qū)域
        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, "選擇微信程序", "", "可執(zhí)行文件 (*.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):
        """更新狀態(tài)欄"""
        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):
        """發(fā)送消息的核心方法"""
        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, "警告", "請輸入消息內(nèi)容或選擇文件")
            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("?? 正在發(fā)送消息...")
        
        def send():
            try:
                if message:
                    wechat_send_msg(recipient, message)
                    self.log_message(f"文本消息已發(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"文件已發(fā)送: {abs_file_path}")
                
                return "消息發(fā)送成功"
            except Exception as e:
                raise Exception(f"發(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()
                return True
            except Exception as e:
                self.log_message(f"定時發(fā)送失敗: {str(e)}")
                return False
    
    def add_scheduled_task(self):
        """添加定時任務(wù)"""
        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, "警告", "請輸入消息內(nèi)容或選擇文件")
            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, "成功", "定時任務(wù)已添加")
    
    def update_tasks_list(self):
        """更新任務(wù)列表顯示"""
        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']}分鐘重復(fù)" if task["repeat"] else ""
            
            self.tasks_list.append(
                f"{i}. {status} | {time_str}{repeat_str}\n"
                f"收件人: {task['recipient']}\n"
                f"內(nèi)容: {task['message'][:30]}{'...' if len(task['message'])>30 else ''}\n"
                f"附件: {task['file_path'] if task['file_path'] else '無'}\n"
                f"發(fā)送時間: {task['send_time'].strftime('%Y-%m-%d %H:%M:%S')}\n"
                "─" * 50
            )
    
    def check_scheduled_tasks(self):
        """檢查并執(zhí)行定時任務(wù)"""
        now = datetime.now()
        any_task_executed = False
        
        for task in self.scheduled_tasks:
            if not task["completed"] and now >= task["send_time"]:
                # 執(zhí)行任務(wù)
                success = self.send_message(
                    recipient=task["recipient"],
                    message=task["message"],
                    file_path=task["file_path"]
                )
                
                if success:
                    task["completed"] = True
                    self.log_message(f"定時任務(wù)執(zhí)行成功: 發(fā)送給 {task['recipient']}")
                    
                    # 如果是重復(fù)任務(wù),重新設(shè)置下次執(zhí)行時間
                    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):
        """清除已完成的任務(wù)"""
        self.scheduled_tasks = [task for task in self.scheduled_tasks if not task["completed"]]
        self.update_tasks_list()
        QMessageBox.information(self, "提示", "已清除所有已完成任務(wù)")
    
    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):
        """操作完成后的回調(diào)"""
        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='任務(wù)欄')
            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='要發(fā)送的消息'):
    wechat_active()
    wechatWindow = uiautomation.WindowControl(searchDepth=1, className='WeChatMainWndForPC', Name='微信')
    
    # 搜索聯(lián)系人
    search_edit = wechatWindow.EditControl(Name="搜索")
    search_edit.Click()
    search_edit.SendKeys(send_to, 0.5)
    time.sleep(1)  # 等待搜索結(jié)果
    
    # 按回車鍵選擇聯(lián)系人
    search_edit.SendKeys('{enter}')
    time.sleep(2)  # 增加等待時間確保聊天窗口加載
    
    if msg[:7] != '全路徑文件名:':
        # 查找消息輸入框 - 使用更可靠的方法
        chat_input = None
        for _ in range(5):  # 增加重試次數(shù)
            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)
        
        # 查找發(fā)送按鈕 - 使用更可靠的方法
        send_button = None
        for _ in range(5):  # 增加重試次數(shù)
            try:
                send_button = wechatWindow.ButtonControl(Name="發(fā)送(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"查找發(fā)送按鈕時出錯: {str(e)}")
            time.sleep(1)
        
        if not send_button or not send_button.Exists():
            raise Exception("找不到發(fā)送按鈕")
        
        send_button.Click()
    else:
        file_path = msg[7:]
        if not os.path.exists(file_path):
            raise Exception(f"文件不存在: {file_path}")
            
        # 查找文件發(fā)送按鈕 - 使用更可靠的方法
        file_button = None
        for _ in range(5):  # 增加重試次數(shù)
            try:
                file_button = wechatWindow.ButtonControl(Name="發(fā)送文件")
                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"查找文件發(fā)送按鈕時出錯: {str(e)}")
            time.sleep(1)
        
        if not file_button or not file_button.Exists():
            raise Exception("找不到文件發(fā)送按鈕")
        
        file_button.Click()
        
        # 等待文件選擇對話框出現(xiàn)
        time.sleep(2)
        file_dialog = uiautomation.WindowControl(Name="打開")
        if not file_dialog.Exists():
            raise Exception("文件選擇對話框未出現(xiàn)")
            
        # 輸入文件路徑
        filename_edit = file_dialog.EditControl(Name="文件名(N):")
        filename_edit.SendKeys(file_path)
        time.sleep(0.5)
        filename_edit.SendKeys('{enter}')
        
        # 等待文件上傳
        time.sleep(3)
        
        # 查找最終發(fā)送按鈕 - 使用更可靠的方法
        final_send_button = None
        for _ in range(5):  # 增加重試次數(shù)
            try:
                final_send_button = wechatWindow.ButtonControl(Name="發(fā)送(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"查找最終發(fā)送按鈕時出錯: {str(e)}")
            time.sleep(1)
        
        if not final_send_button or not final_send_button.Exists():
            raise Exception("找不到最終發(fā)送按鈕")
        
        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_())

技術(shù)難點與解決方案

1. 窗口控件定位問題

問題現(xiàn)象:微信版本更新導(dǎo)致自動化失效

解決方案:

# 多重定位策略
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. 定時任務(wù)精度問題

對比方案:

方案精度CPU占用可靠性
QTimer輪詢1秒
Python threading0.1秒
Windows定時器毫秒級

選擇依據(jù):綜合業(yè)務(wù)需求選擇QTimer方案

擴展知識

1. UI自動化技術(shù)對比

技術(shù)方案優(yōu)點缺點
uiautomation微軟官方,支持Win32文檔較少
PyAutoGUI跨平臺,簡單易用無法處理復(fù)雜控件
Selenium支持Web自動化不適用桌面應(yīng)用

2. 企業(yè)級優(yōu)化建議

加入配置文件:使用config.ini保存常用設(shè)置

增加日志系統(tǒng):采用logging模塊實現(xiàn)分級日志

打包發(fā)布:使用PyInstaller生成exe

添加單元測試:確保核心功能穩(wěn)定性

總結(jié)

本文詳細剖析了一個功能完備的微信自動化工具的開發(fā)全過程,關(guān)鍵技術(shù)要點包括:

  • PyQt5的MVC架構(gòu)實踐:實現(xiàn)界面與邏輯分離
  • 防御式編程思想:完善的異常處理體系
  • 自動化測試思維:控件查找的重試機制
  • 用戶體驗優(yōu)化:狀態(tài)反饋+日志系統(tǒng)

未來優(yōu)化方向:

  • 增加聯(lián)系人自動補全功能
  • 實現(xiàn)消息模板管理
  • 加入多賬號支持
  • 開發(fā)插件系統(tǒng)

到此這篇關(guān)于如何基于Python開發(fā)一個微信自動化工具的文章就介紹到這了,更多相關(guān)Python微信自動化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python使用matplotlib繪制圖形大全(曲線圖、條形圖、餅圖等)

    Python使用matplotlib繪制圖形大全(曲線圖、條形圖、餅圖等)

    matplotlib 是一個用于創(chuàng)建靜態(tài)、動態(tài)和交互式可視化圖形的 Python 庫,它被廣泛用于數(shù)據(jù)可視化,并且可以與多種操作系統(tǒng)和圖形后端一起工作,本文給大家介紹了Python使用matplotlib繪制圖形大全,需要的朋友可以參考下
    2024-06-06
  • Python高效生成requirements.txt的兩種方法

    Python高效生成requirements.txt的兩種方法

    Python項目依賴管理是開發(fā)流程中的關(guān)鍵環(huán)節(jié),requirements.txt文件作為記錄項目依賴的標準方式,能確保環(huán)境一致性并簡化協(xié)作部署流程,掌握其生成方法對開發(fā)者至關(guān)重要,本文給大家介紹了兩種高效生成requirements.txt的方法,需要的朋友可以參考下
    2025-12-12
  • python3 簡單實現(xiàn)組合設(shè)計模式

    python3 簡單實現(xiàn)組合設(shè)計模式

    這篇文章主要介紹了python3 簡單實現(xiàn)組合設(shè)計模式的方法,文中示例代碼非常詳細,幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-07-07
  • 淺談Python中的作用域規(guī)則和閉包

    淺談Python中的作用域規(guī)則和閉包

    本文簡單講解了PYTHON的閉包,作用域的基本知識配合實例簡單明了,適合初學(xué)者
    2018-03-03
  • 使用Python批量處理圖片的實戰(zhàn)指南

    使用Python批量處理圖片的實戰(zhàn)指南

    當(dāng)Word文檔里的圖片成了攔路虎,這種時候,Python就派上用場了,它不會抱怨重復(fù)勞動,也不會因為眼花點錯圖片,下面我們就來看看如何使用Python腳本實現(xiàn)批量處理圖片吧
    2026-03-03
  • python 爬取免費簡歷模板網(wǎng)站的示例

    python 爬取免費簡歷模板網(wǎng)站的示例

    這篇文章主要介紹了python 爬取免費簡歷模板網(wǎng)站的示例,幫助大家更好的理解和使用python 爬蟲,感興趣的朋友可以了解下
    2020-09-09
  • selenium自動化測試簡單準備

    selenium自動化測試簡單準備

    本文主要介紹了selenium自動化測試簡單準備,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 淺談python累加求和+奇偶數(shù)求和_break_continue

    淺談python累加求和+奇偶數(shù)求和_break_continue

    這篇文章主要介紹了淺談python累加求和+奇偶數(shù)求和_break_continue,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • 在matlab中創(chuàng)建類似字典的數(shù)據(jù)結(jié)構(gòu)方式

    在matlab中創(chuàng)建類似字典的數(shù)據(jù)結(jié)構(gòu)方式

    這篇文章主要介紹了在matlab中創(chuàng)建類似字典的數(shù)據(jù)結(jié)構(gòu)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • python字典中g(shù)et()函數(shù)的基本用法實例

    python字典中g(shù)et()函數(shù)的基本用法實例

    在字典內(nèi)置的方法中,想說的方法為get,這個方法是通過鍵來獲取相應(yīng)的值,但是如果相應(yīng)的鍵不存在則返回None,這篇文章主要給大家介紹了關(guān)于python字典中g(shù)et()函數(shù)的基本用法,需要的朋友可以參考下
    2022-03-03

最新評論

乐平市| 东乡县| 吉安县| 高陵县| 沙河市| 堆龙德庆县| 印江| 竹山县| 兴海县| 都昌县| 黄大仙区| 黔南| 永善县| 四川省| 铁岭县| 屯留县| 宜城市| 栾城县| 邻水| 洞头县| 青铜峡市| 大方县| 桦南县| 滦南县| 咸丰县| 张北县| 湘潭县| 晋城| 竹山县| 桃园县| 新田县| 澳门| 师宗县| 普陀区| 连州市| 安西县| 芮城县| 武城县| 靖州| 金华市| 清丰县|