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

Discord机器人如何下载聊天最新GIF/MP4?解决文件损坏问题

Discord机器人下载GIF文件损坏的修复方案

问题描述

我希望Discord机器人能下载聊天中最新发送的GIF,支持保存为GIF格式或可转换为GIF的MP4格式。现有代码能正常定位到目标GIF的URL,但下载生成的downloaded.gif文件始终损坏,无法正常使用。

现有代码:

@client.command()
async def giffy(ctx):
    channel = ctx.channel
    async for message in channel.history(limit=100):
        if message.attachments:
            for attachment in message.attachments:
                if attachment.filename.lower().endswith(('.gif', '.gifv')):
                    gif_url = attachment.url
                    response = requests.get(gif_url)
                    if response.status_code == 200:
                      with open("downloaded.gif", "wb") as f:
                        f.write(response.content)
                    else:
                      print("error")
                    return
        elif message.content:
            content = message.content.lower()
            if content.endswith(('.gif', '.gifv')) or content.startswith(('http://', 'https://')):
                  gif_url = content
                  response = requests.get(gif_url)
                  if response.status_code == 200:
                    with open("downloaded.gif", "wb") as f:
                      f.write(response.content)
                  else:
                    print("error")
                  return

    await ctx.send("No GIF found in the channel's history.")

问题原因及修复方案

1. Discord的GIF链接实际返回MP4格式

Discord上标记为.gif或.gifv的附件,很多时候实际返回的是MP4视频文件(为了节省带宽)。强行用.gif后缀保存MP4数据,会导致系统无法识别文件,看起来像是“损坏”。

2. 同步请求在异步环境下的风险

requests.get是同步阻塞请求,在Discord.py的异步运行环境中,可能导致数据未完全接收就写入文件,造成文件损坏。建议改用异步HTTP库aiohttp。

修复后的代码

import aiohttp
from discord.ext import commands

@client.command()
async def giffy(ctx):
    channel = ctx.channel
    async for message in channel.history(limit=100):
        # 处理附件中的GIF/GIFV
        if message.attachments:
            for attachment in message.attachments:
                if attachment.filename.lower().endswith(('.gif', '.gifv')):
                    await download_media(attachment.url)
                    await ctx.send("最新GIF/MP4已下载完成")
                    return
        # 处理消息内容中的链接
        elif message.content:
            content = message.content.strip()
            if (content.lower().endswith(('.gif', '.gifv')) 
                or content.startswith(('http://', 'https://'))):
                await download_media(content)
                await ctx.send("最新GIF/MP4已下载完成")
                return

    await ctx.send("频道历史中未找到GIF/MP4")

async def download_media(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            if response.status == 200:
                # 获取响应的内容类型,判断实际文件格式
                content_type = response.headers.get('Content-Type', '')
                if 'image/gif' in content_type:
                    filename = "downloaded.gif"
                elif 'video/mp4' in content_type:
                    filename = "downloaded.mp4"
                else:
                    # 默认按原链接后缀保存
                    filename = url.split('/')[-1]
                
                # 完整写入文件
                with open(filename, "wb") as f:
                    f.write(await response.read())
            else:
                print(f"下载失败,状态码:{response.status}")

额外优化:MP4转GIF(可选)

如果需要将下载的MP4转换为GIF,可以使用moviepy库,添加以下转换函数:

from moviepy.editor import VideoFileClip

def convert_mp4_to_gif(mp4_path, gif_path, fps=10):
    clip = VideoFileClip(mp4_path)
    clip.write_gif(gif_path, fps=fps)
    clip.close()

# 在download_media函数中添加调用:
# 当保存为mp4后,调用convert_mp4_to_gif("downloaded.mp4", "converted.gif")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 19:05:01