You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Python开发的Discord机器人每周日自动发送课程表截图?

Discord机器人定时发送课程表问题解决方案

问题根源

  1. 事件循环阻塞:原代码中while True的schedule轮询循环会完全阻塞discord.py的异步事件循环,导致机器人无法处理任何Discord事件(包括消息发送、指令响应)。
  2. 异步函数调用错误:continuation是异步函数,在同步的job函数中直接调用不会执行,必须通过事件循环调度。
  3. 频道对象获取失败:bot.get_channel()未传入具体的频道ID,无法获取有效频道对象。
  4. 周数未实时更新:my_date在程序启动时初始化,定时任务运行时不会自动更新为当前周数。

修正后的完整代码

import discord
from discord.ext import commands, tasks
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import time
import pyautogui
import datetime
from datetime import date

# 配置参数
BOT_TOKEN = "你的机器人令牌"
TARGET_CHANNEL_ID = 123456789012345678  # 替换为目标频道ID
DEFAULT_CLASS_ID = "myclassname"

bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())

@bot.event
async def on_ready():
    print("Bot is alive")
    try:
        synced = await bot.tree.sync()
        print(f"同步了 {len(synced)} 条命令")
    except Exception as e:
        print(e)
    # 启动定时任务
    weekly_schedule_task.start()

# 复用的课程表生成与发送函数
async def generate_and_send_schedule(channel, classid=DEFAULT_CLASS_ID):
    # 获取当前周数
    my_date = date.today()
    year, week_num, day_of_week = my_date.isocalendar()
    
    driver = webdriver.Chrome()
    try:
        driver.get('school.com') 
        driver.set_window_size(1024, 768)
        time.sleep(3)
        pyautogui.moveTo(1000, 440, duration=1)
        pyautogui.click(1000, 440)                
        pyautogui.typewrite(classid)             
        pyautogui.typewrite(["enter"])
        time.sleep(3)
        driver.execute_script("window.scrollTo(0,document.body.scrollHeight)") 
        time.sleep(2)
        
        driver.save_screenshot('screenshot.png')
        await channel.send(f"第 {week_num} 周 {classid} 的课程表")
        await channel.send(file=discord.File('screenshot.png'))
    finally:
        driver.quit()  # 确保浏览器关闭

# 指令触发的功能
@bot.command()
async def schema1(ctx, classid=DEFAULT_CLASS_ID):
    await generate_and_send_schedule(ctx.channel, classid)

# 定时任务:每周日15:00执行
@tasks.loop(time=datetime.time(hour=15, minute=0, tzinfo=datetime.timezone.utc))  # 注意时区,根据你的地区调整
async def weekly_schedule_task():
    # 检查当前是否是周日(isocalendar的day_of_week=7代表周日)
    if date.today().isocalendar()[2] == 7:
        channel = bot.get_channel(TARGET_CHANNEL_ID)
        if channel:
            await generate_and_send_schedule(channel)
            print("定时任务执行完成")
        else:
            print("无法获取目标频道,请检查频道ID是否正确")

bot.run(BOT_TOKEN)

关键修改说明

  • 使用discord.py tasks扩展:替代schedule库,基于异步事件循环运行定时任务,不会阻塞机器人的正常运行。
  • 复用核心逻辑:把课程表生成和发送的逻辑封装成generate_and_send_schedule函数,指令触发和定时任务都调用这个函数,减少重复代码。
  • 实时更新周数:在每次生成课程表时重新获取当前日期,确保周数是最新的。
  • 正确处理异步调用:所有Discord相关操作都通过await执行,确保在事件循环中处理。
  • 时区处理:定时任务的time参数需要设置正确的时区,避免时间偏差(示例用UTC,根据你的实际时区调整,比如东八区可以用datetime.timezone(datetime.timedelta(hours=8)))。
  • 资源清理:使用try-finally确保浏览器驱动在任务完成后关闭,避免资源泄漏。

内容的提问来源于stack exchange,提问作者ullman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 20:57:30