You need to enable JavaScript to run this app. Discord.py 为Urban Dictionary、OpenWeatherMap API命令添加用户输入参数的求助
优惠活动
大模型
产品
解决方案
定价
更多

Discord.py 为Urban Dictionary、OpenWeatherMap API命令添加用户输入参数的求助

修复Discord.py第三方API命令的参数传递问题

你现在写的$urban命令没法正常响应带搜索词的调用,核心问题有三个:

  • 函数签名没留接收位,用户输在命令后面的搜索词根本没被框架捕获到
  • 发起API请求的时候没把搜索词作为查询参数传出去,相当于一直给接口发空请求
  • 解析接口返回JSON的时候字典键名是空字符串,根本取不到有效数据

第一步:让框架捕获用户输入的完整搜索词

Discord.py 扩展的命令解析规则是:会把用户在命令名后输入的文本按空格拆分,依次匹配函数签名里的位置参数。
因为网络词条经常带空格(比如“hot dog”“zero click”),没必要拆成多个参数,只需要在ctx参数后面加一个带*标记的字符串参数,就能把命令后面的所有剩余文本整合成一个完整字符串传给函数。
比如把原来的函数定义:
async def urban(self, ctx):
改成:
async def urban(self, ctx, *, search_term: str):
这里的*是关键标记,作用是告诉框架:从这个位置开始,不管后面的输入有没有空格,全部合并成一个字符串赋值给search_term。哪怕用户输入$urban fluffy cat wearing hat,整段fluffy cat wearing hat都会被完整捕获作为搜索词,不会被拆成单个单词。
如果用户没输任何搜索词直接发命令,框架会自动触发缺参报错,你也可以后续加错误处理自定义提示文案,比如引导用户“请输入要查询的词条,格式为$urban 要搜的词”。

第二步:把捕获的搜索词传给第三方API

你之前的代码里,session.get只传了URL和请求头,没有传查询参数,Urban Dictionary的接口自然不知道你要搜什么。
按照接口要求,需要传入的查询参数是term,对应的值就是刚才捕获到的search_term。你不需要手动拼URL的查询串,只要把参数组装成字典,传给get方法的params参数就行,库会自动帮你拼接到请求URL后面,还会自动处理空格、特殊符号的转义,避免请求出错。
这部分的代码修改:

# 组装接口需要的查询参数字典
querystring = {"term": search_term}
# 发请求的时候把params传进去
async with session.get(url, headers=headers, params=querystring) as response:

第三步:修正接口返回值的解析逻辑

原来的代码里写r['']是完全取不到值的——这个Urban Dictionary接口返回的JSON结构里,所有匹配的词条结果都存在list字段下,是一个列表,最相关的结果在列表的第一个位置。
你需要先判断接口有没有返回有效结果,避免空结果触发KeyError报错,再从结果里取对应字段构建embed:

r = await response.json()
# 先检查有没有匹配的结果
if not r.get("list"):
    await ctx.send(f"没找到和「{search_term}」相关的释义哦")
    return
# 取最相关的第一条结果
top_result = r["list"][0]

原来的embed里空的取值,全部替换成对应字段:标题用top_result["word"]做词条名,释义用top_result["definition"],还可以加上接口返回的示例、点赞数这类信息让内容更完整。另外提醒一句,新版Discord.py里作者头像的属性是ctx.author.avatar.url,原来的avatar_url已经是弃用的写法了,写上去会报属性不存在的错。

改完的可运行代码

@commands.command(
        name="urban",
        description="Allows the user to get a definition from Urban Dictionary",
        aliases=['urbandict']
    )
    async def urban(self, ctx, *, search_term: str):
        url = "https://mashape-community-urban-dictionary.p.rapidapi.com/define"

        headers = {
            'x-rapidapi-key': self.bot.quote_api_key,
            'x-rapidapi-host': "mashape-community-urban-dictionary.p.rapidapi.com"
        }
        querystring = {"term": search_term}

        async with ClientSession() as session:
            async with session.get(url, headers=headers, params=querystring) as response:
                r = await response.json()
                if not r.get("list"):
                    await ctx.send(f"没有找到关于「{search_term}」的网络释义~")
                    return
                top_result = r["list"][0]
                embed = discord.Embed(
                    title=f"搜索词条:{top_result['word']}",
                    description=top_result["definition"]
                )
                if top_result.get("example"):
                    # 截断过长的示例文本,避免超出embed的字符限制
                    embed.add_field(
                        name="用法示例",
                        value=top_result["example"][:1024],
                        inline=False
                    )
                embed.add_field(name="点赞数", value=top_result["thumbs_up"])
                embed.set_author(
                    name=ctx.author.display_name,
                    icon_url=ctx.author.avatar.url
                )
                await ctx.send(embed=embed)

通用逻辑参考:这套写法完全可以复用在OpenWeatherMap这类其他第三方API上——只需要在命令参数位把用户输入的地点名捕获下来,组装成接口要求的参数字典(比如OpenWeatherMap需要的q=地点名、appid=你的密钥),传给请求方法的params参数就行,不用手动拼接复杂的URL。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.09 21:45:06