如何在discord.py中编写可搜索wiki的archive命令?
discord.py实现wiki搜索archive命令完整指南
核心实现逻辑
整个功能的执行流程非常清晰:
- 接收用户输入的
/archive命令+搜索关键词参数 - 后端异步调用目标wiki的公开搜索API获取结果(大部分wiki站都有原生公开API,无需写爬虫爬页面)
- 解析API返回的搜索结果,格式化discord兼容的内容格式
- 可以选择直接用bot回复用户,或者通过提前配置的webhook发送到指定归档频道
前置准备
- 确保使用discord.py v2.0及以上版本,支持原生斜杠命令
- 提前确认目标wiki的API请求格式,主流MediaWiki架构的wiki通用搜索接口参数可直接复用下方示例
- 如果需要使用webhook归档,提前在目标discord频道创建webhook,拿到对应的webhook URL
具体代码实现
第一步:导入依赖
import discord from discord import app_commands import aiohttp # 异步发起网络请求,不阻塞bot主进程
第二步:初始化配置与bot实例
# 自定义配置项 BOT_TOKEN = "你的discord bot令牌" WIKI_API_URL = "目标wiki的API地址,例:https://你的wiki域名/api.php" # 不需要webhook可以不填下面这行 ARCHIVE_WEBHOOK_URL = "你创建的discord频道webhook地址" intents = discord.Intents.default() bot = discord.Client(intents=intents) command_tree = app_commands.CommandTree(bot)
第三步:编写wiki搜索工具函数
async def search_wiki_content(keyword: str): # MediaWiki架构wiki的通用搜索参数,非该架构可根据对应wiki文档调整 request_params = { "action": "query", "list": "search", "srsearch": keyword, "format": "json", "srlimit": 3 # 单次最多返回3条结果,可自定义调整 } async with aiohttp.ClientSession() as session: async with session.get(WIKI_API_URL, params=request_params) as resp: if resp.status != 200: return None result_json = await resp.json() return result_json.get("query", {}).get("search", [])
第四步:编写archive命令逻辑
版本1:直接回复触发命令的用户
@command_tree.command(name="archive", description="搜索指定wiki并返回相关结果") async def archive(interaction: discord.Interaction, keyword: str): # 先发送思考状态,避免discord 3秒超时判定 await interaction.response.defer(thinking=True) search_results = await search_wiki_content(keyword) if not search_results: await interaction.followup.send(f"未找到和 *{keyword}* 相关的wiki内容") return # 格式化返回内容 reply_content = f"## *{keyword}* 的wiki搜索结果:\n" for idx, item in enumerate(search_results, 1): # 替换掉返回结果里的html高亮标签,换成discord兼容的加粗格式 snippet = item.get("snippet", "无简介").replace('<span class="searchmatch">', "**").replace('</span>', "**") reply_content += f"- {idx}. **{item.get('title')}**:{snippet}...\n" await interaction.followup.send(reply_content)
版本2:通过webhook归档到指定频道
@command_tree.command(name="archive", description="搜索wiki并将结果归档到指定频道") async def archive(interaction: discord.Interaction, keyword: str): await interaction.response.defer(thinking=True) search_results = await search_wiki_content(keyword) if not search_results: await interaction.followup.send(f"未找到和 *{keyword}* 相关的wiki内容") return # 构造embed格式的归档内容 archive_embed = discord.Embed(title=f"Wiki归档:{keyword}", color=discord.Color.blue()) for idx, item in enumerate(search_results, 1): snippet = item.get("snippet", "无简介").replace('<span class="searchmatch">', "**").replace('</span>', "**") archive_embed.add_field( name=f"{idx}. {item.get('title')}", value=f"{snippet}...", inline=False ) # 通过webhook发送内容 async with aiohttp.ClientSession() as session: webhook = discord.Webhook.from_url(ARCHIVE_WEBHOOK_URL, session=session) # 可自定义webhook发送的用户名、头像 await webhook.send(embed=archive_embed, username="Wiki归档机器人") await interaction.followup.send(f"已将 *{keyword}* 的搜索结果成功归档")
第五步:启动bot同步命令
@bot.event async def on_ready(): # 全局同步命令首次运行可能需要最长1小时生效,测试可以指定guild参数秒同步 await command_tree.sync() print(f"Bot已登录,当前账号:{bot.user}") bot.run(BOT_TOKEN)
注意事项
- 非MediaWiki架构的wiki,根据对应站点的官方文档调整
search_wiki_content函数的请求参数和结果解析逻辑即可 - 如果需要返回完整的wiki页面链接,拼接wiki的页面访问前缀+结果标题即可
- webhook发送支持自定义头像、添加附件、@指定用户/角色,可根据需求自行调整参数
内容的提问来源于stack exchange,提问作者Commander Purple
相关产品推荐
相关产品推荐

