python实现微信定时自动群聊发送消息

python实现微信定时自动群聊发送消息

这篇教程将教你如何使用 Python 的 tkinter 库构建一个简单的定时任务发送工具,允许用户上传 Excel 文件,选择发送周期、发送时间,以及设置提醒类型(逾期提醒和快到期提醒)。此外,工具会在指定的时间根据 Excel 数据自动发送微信消息。
在这里插入图片描述

一、项目概述

该项目的核心功能是通过 Python 创建一个图形用户界面 (GUI),用户可以在其中设置定时任务,基于 Excel 文件中的任务信息,按照设置的时间周期自动发送消息。这些消息会包含任务的相关信息,并且提醒用户任务是否即将到期或已逾期。

二、项目需求

Python 3.x
安装以下依赖包:
tkinter:用于创建 GUI 界面。
schedule:用于定时任务的调度。
wxauto:用于发送微信消息。
pandas:用于读取和处理 Excel 数据。
datetime:用于处理日期时间。
安装依赖包:

pip install schedule wxauto pandas

三、代码结构解析

  1. GUI 设计部分
    使用 tkinter 来设计图形界面,界面包含文件上传、发送周期选择、任务发送时间设置、群聊名称输入以及选择提醒类型的复选框。
    用户可以通过上传 Excel 文件、选择时间周期(每天或每周)、输入任务发送时间和群聊名称,来设置自动发送的任务。

  2. 主要函数解释
    2.1 read_data(file_path):读取 Excel 文件
    此函数使用 pandas 库读取 Excel 文件,并且填充空缺的字段(通过前向填充)。读取的内容包括工作任务、类别、责任人等信息。

def read_data(file_path):
    file_path = file_path.lstrip()
    df = pd.read_excel(file_path, usecols="A:J", nrows=75, skiprows=1)
    df['工作任务'] = df['工作任务'].fillna(method='ffill')
    df['类别'] = df['类别'].fillna(method='ffill')
    df['责任人'] = df['责任人'].fillna(method='ffill')
    return df

2.2 convert_to_month(plan_date):转换计划日期为月份差
此函数将 Excel 文件中的计划完成时间转换为当前月份的差值,判断任务是否逾期或接近到期

def convert_to_month(plan_date):
    current_date = datetime.now()
    current_month = current_date.month
    current_year = current_date.year
    plan_date = str(plan_date)

    if '年' in plan_date:
        year_month = plan_date.replace('年', '-').replace('月', '')
        plan_date_obj = datetime.strptime(year_month, "%Y-%m")
        diff = (current_year - plan_date_obj.year) * 12 + current_month - plan_date_obj.month
        return diff
    elif '-' in plan_date:
        month = plan_date.split('-')[1].replace('月', '')
        diff = current_month - int(month)
    else:
        diff = current_month - int(plan_date.replace('月', ''))
    return diff

2.3 filter_rows(row):过滤任务
此函数用于根据任务的备注、进展和责任人等字段过滤数据,排除掉已完成、取消或没有设置完成时间的任务。

def filter_rows(row):
    if '已完成' in str(row['备注']):
        return False
    if '已完成' in str(row['进展及存在问题']):
        return False
    if '取消' in str(row['责任人']):
        return False
    if '按规定' in str(row['计划完成时间']):
        return False
    return True

2.4 send_message(message):发送微信消息
此函数通过 wxauto 库发送微信消息。消息内容由任务的相关信息和提醒类型组成

def send_message(message):
    wx = WeChat()
    who = who_entry.get()  # 获取用户输入的群聊名称
    wx.SendMsg(message, who)

2.5 schedule_task(send_overdue, send_due_soon, file_path):定时任务处理
此函数是定时任务的核心部分,读取 Excel 数据,过滤符合条件的任务,生成任务消息,并根据设置的提醒类型(逾期提醒和快到期提醒)发送消息。

def schedule_task(send_overdue, send_due_soon, file_path):
    df = read_data(file_path)
    filtered_df = df[df.apply(filter_rows, axis=1)].reset_index(drop=True)

    for i in range(len(filtered_df)):
        overdue_months = convert_to_month(filtered_df.at[i, '计划完成时间'])
        out_txt = f"@{filtered_df.at[i, '责任人']}\n"
        out_txt += f"工作任务:{filtered_df.at[i, '工作任务']}\n"
        out_txt += f"任务分解:{filtered_df.at[i, '任务分解']}\n"
        out_txt += f"计划完成时间:{filtered_df.at[i, '计划完成时间']}\n"

        if send_due_soon and overdue_months <= 0 and overdue_months >= -1:
            out_txt += "\n=== 【快到期提醒】 ===\n"
            out_txt += "该任务距离计划完成时间不足 1 个月,请尽快确认完成进度!\n"
            send_message(out_txt)

        if send_overdue and overdue_months > 0:
            out_txt += "\n=== 【逾期警告】 ===\n"
            out_txt += f"该任务已逾期 {overdue_months} 个月,请尽快处理!\n"
            send_message(out_txt)

2.6 set_schedule(file_path):设置定时任务
根据用户选择的周期(每天或每周)、发送时间、提醒类型等设置定时任务。使用 schedule 库来执行定时任务。

def set_schedule(file_path):
    time_str = time_entry.get()
    send_overdue = overdue_check.get()
    send_due_soon = due_soon_check.get()

    try:
        if time_period.get() == '每天':
            # 设置每天发送任务
            schedule.every().day.at(time_str).do(schedule_task, send_overdue=send_overdue, send_due_soon=send_due_soon,
                                                 file_path=file_path)
        elif time_period.get() == '每周' and weekday_var.get():
            # 设置每周发送任务,确保使用英语星期几(如 "Monday")
            selected_day = weekday_var.get()
            schedule.every(1).weeks.at(time_str).do(schedule_task, send_overdue=send_overdue,
                                                    send_due_soon=send_due_soon, file_path=file_path).day(selected_day)
        else:
            messagebox.showerror("错误", "请确保选择了合适的选项。")

        messagebox.showinfo("设置成功", f"定时任务已设置为:{time_period.get()} {time_str}")

    except Exception as e:
        messagebox.showerror("设置失败", f"设置任务时出错:{str(e)}")

2.7 run_schedule():运行定时任务
此函数启动一个无限循环,持续检查并执行定时任务

def run_schedule():
    while True:
        schedule.run_pending()
        time.sleep(1)

3. 完整的 GUI 设置

创建界面并处理用户交互,上传文件、设置定时任务、输入群聊名称等

# 创建 GUI 界面
root = tk.Tk()
root.title("定时任务发送设置")
root.geometry("600x600")  # 增大窗口大小
root.resizable(True, True)  # 允许调整大小

# 设置上传文件功能
tk.Label(root, text="上传 Excel 文件", font=('Arial', 12)).pack(pady=20)
upload_button = tk.Button(root, text="选择文件", command=lambda: upload_file(), font=('Arial', 12), width=20)
upload_button.pack()

file_label = tk.Label(root, text="尚未选择文件", font=('Arial', 12))
file_label.pack(pady=10)

# 设置发送周期选择框
tk.Label(root, text="选择发送周期", font=('Arial', 12)).pack(pady=20)
time_period = tk.StringVar(value='每天')
daily_radiobutton = tk.Radiobutton(root, text="每天", variable=time_period, value="每天", font=('Arial', 12),
                                   command=update_mode)
weekly_radiobutton = tk.Radiobutton(root, text="每周", variable=time_period, value="每周", font=('Arial', 12),
                                    command=update_mode)
daily_radiobutton.pack()
weekly_radiobutton.pack()

# 选择星期几(每周模式)
weekday_label = tk.Label(root, text="选择星期几发送任务", font=('Arial', 12))
weekday_var = tk.StringVar()
weekday_options = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', '

4. 完整代码

import tkinter as tk
from tkinter import messagebox, filedialog
import schedule
import time
import threading
from wxauto import *
import pandas as pd
from datetime import datetime


# 读取 Excel 数据
def read_data(file_path):
    file_path = file_path.lstrip()
    df = pd.read_excel(file_path, usecols="A:J", nrows=75, skiprows=1)
    df['工作任务'] = df['工作任务'].fillna(method='ffill')
    df['类别'] = df['类别'].fillna(method='ffill')
    df['责任人'] = df['责任人'].fillna(method='ffill')
    return df


# 转换日期
def convert_to_month(plan_date):
    current_date = datetime.now()
    current_month = current_date.month
    current_year = current_date.year
    plan_date = str(plan_date)

    if '年' in plan_date:
        year_month = plan_date.replace('年', '-').replace('月', '')
        plan_date_obj = datetime.strptime(year_month, "%Y-%m")
        diff = (current_year - plan_date_obj.year) * 12 + current_month - plan_date_obj.month
        return diff
    elif '-' in plan_date:
        month = plan_date.split('-')[1].replace('月', '')
        diff = current_month - int(month)
    else:
        diff = current_month - int(plan_date.replace('月', ''))
    return diff


# 过滤数据
def filter_rows(row):
    if '已完成' in str(row['备注']):
        return False
    if '已完成' in str(row['进展及存在问题']):
        return False
    if '取消' in str(row['责任人']):
        return False
    if '按规定' in str(row['计划完成时间']):
        return False
    return True


# 发送微信消息
def send_message(message):
    wx = WeChat()
    who = who_entry.get()  # 获取用户输入的群聊名称
    wx.SendMsg(message, who)


# 定义定时任务
def schedule_task(send_overdue, send_due_soon, file_path):
    df = read_data(file_path)
    filtered_df = df[df.apply(filter_rows, axis=1)].reset_index(drop=True)

    for i in range(len(filtered_df)):
        overdue_months = convert_to_month(filtered_df.at[i, '计划完成时间'])
        out_txt = f"@{filtered_df.at[i, '责任人']}\n"
        out_txt += f"工作任务:{filtered_df.at[i, '工作任务']}\n"
        out_txt += f"任务分解:{filtered_df.at[i, '任务分解']}\n"
        out_txt += f"计划完成时间:{filtered_df.at[i, '计划完成时间']}\n"

        if send_due_soon and overdue_months <= 0 and overdue_months >= -1:
            out_txt += "\n=== 【快到期提醒】 ===\n"
            out_txt += "该任务距离计划完成时间不足 1 个月,请尽快确认完成进度!\n"
            send_message(out_txt)

        if send_overdue and overdue_months > 0:
            out_txt += "\n=== 【逾期警告】 ===\n"
            out_txt += f"该任务已逾期 {overdue_months} 个月,请尽快处理!\n"
            send_message(out_txt)


# 设置定时任务
def set_schedule(file_path):
    time_str = time_entry.get()
    send_overdue = overdue_check.get()
    send_due_soon = due_soon_check.get()

    try:
        if time_period.get() == '每天':
            # 设置每天发送任务
            schedule.every().day.at(time_str).do(schedule_task, send_overdue=send_overdue, send_due_soon=send_due_soon,
                                                 file_path=file_path)
        elif time_period.get() == '每周' and weekday_var.get():
            # 设置每周发送任务,确保使用英语星期几(如 "Monday")
            selected_day = weekday_var.get()
            schedule.every(1).weeks.at(time_str).do(schedule_task, send_overdue=send_overdue,
                                                    send_due_soon=send_due_soon, file_path=file_path).day(selected_day)
        else:
            messagebox.showerror("错误", "请确保选择了合适的选项。")

        messagebox.showinfo("设置成功", f"定时任务已设置为:{time_period.get()} {time_str}")

    except Exception as e:
        messagebox.showerror("设置失败", f"设置任务时出错:{str(e)}")


# 运行任务
def run_schedule():
    while True:
        schedule.run_pending()
        time.sleep(1)


# 更新 GUI,控制"选择星期几"下拉框的显示/隐藏
def update_mode():
    if time_period.get() == '每天':
        weekday_label.pack_forget()
        weekday_dropdown.pack_forget()
    elif time_period.get() == '每周':
        weekday_label.pack(pady=10)
        weekday_dropdown.pack()


# 文件上传功能
def upload_file():
    file_path = filedialog.askopenfilename(filetypes=[("Excel Files", "*.xlsx")])
    if file_path:
        file_label.config(text="已选择文件: " + file_path)
        return file_path
    else:
        messagebox.showwarning("未选择文件", "请上传一个有效的 Excel 文件。")
        return None


# 创建 GUI 界面
root = tk.Tk()
root.title("定时任务发送设置")
root.geometry("600x600")  # 增大窗口大小
root.resizable(True, True)  # 允许调整大小

# 设置上传文件功能
tk.Label(root, text="上传 Excel 文件", font=('Arial', 12)).pack(pady=20)
upload_button = tk.Button(root, text="选择文件", command=lambda: upload_file(), font=('Arial', 12), width=20)
upload_button.pack()

file_label = tk.Label(root, text="尚未选择文件", font=('Arial', 12))
file_label.pack(pady=10)

# 设置发送周期选择框
tk.Label(root, text="选择发送周期", font=('Arial', 12)).pack(pady=20)
time_period = tk.StringVar(value='每天')
daily_radiobutton = tk.Radiobutton(root, text="每天", variable=time_period, value="每天", font=('Arial', 12),
                                   command=update_mode)
weekly_radiobutton = tk.Radiobutton(root, text="每周", variable=time_period, value="每周", font=('Arial', 12),
                                    command=update_mode)
daily_radiobutton.pack()
weekly_radiobutton.pack()

# 选择星期几(每周模式)
weekday_label = tk.Label(root, text="选择星期几发送任务", font=('Arial', 12))
weekday_var = tk.StringVar()
weekday_options = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
weekday_dropdown = tk.OptionMenu(root, weekday_var, *weekday_options)
weekday_dropdown.config(font=('Arial', 12))

# 设置发送时间输入框
tk.Label(root, text="请输入发送时间 (HH:MM)", font=('Arial', 12)).pack(pady=10)
time_entry = tk.Entry(root, font=('Arial', 12))
time_entry.pack(pady=5)
# 添加输入群聊名称的标签和输入框
tk.Label(root, text="输入群聊名称", font=('Arial', 12)).pack(pady=10)
who_entry = tk.Entry(root, font=('Arial', 12))
who_entry.pack(pady=5)

# 设置发送提醒类型复选框
overdue_check = tk.BooleanVar(value=True)
due_soon_check = tk.BooleanVar(value=True)

tk.Checkbutton(root, text="发送逾期提醒", variable=overdue_check, font=('Arial', 12)).pack(pady=5)
tk.Checkbutton(root, text="发送快到期提醒", variable=due_soon_check, font=('Arial', 12)).pack(pady=5)

# 设置开始按钮
tk.Button(root, text="设置定时任务", command=lambda: set_schedule(
    file_label.cget("text")[6:] if file_label.cget("text").startswith("已选择文件") else None), font=('Arial', 14), width=20,
          height=2).pack(pady=20)

# 启动定时任务线程
threading.Thread(target=run_schedule, daemon=True).start()

# 启动 GUI
root.mainloop()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VIT19980106

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值