【Python】如何给你的 kook 机器人添加上翻译功能
翻译功能实现
打开 code/endpoints/translate.py,这便是本仓库中翻译代码的实现。
其中第一部分有道翻译的代码来自 Many-Translaters 项目,该项目上一次维护是在 4 年前,且里面的部分代码已经无法使用。该代码属于一个白嫖产物,稳定性未知。
为了不让我的 bot 在有道翻译接口失效后直接没有了翻译功能,这里我使用了彩云小译来作 “备胎”
你可以在彩云小译 的官网上找到 api 文档,内部包含了一个 Python 代码示例,开箱即用!免费用户申请的
api-key
,每月有 100w 字符的免费额度,对于我们的 bot 算是够用了。
1. 关于 aiohttp 和 requests 的优劣
在 khl.py
一众大佬的建议下,我简单学习了 aiohttp
的代码,并将彩云小译的 requests
修改为了 aiohttp
1 | #原有requests代码 |
这里简单说一下 aiohttp
和 requests
的区别
requests
途中,程序会挂起,bot 将不会响应其他命令aiohttp
作为异步框架,bot 在使用它的同时,可以同步处理其他命令
举个栗子:假设有用户每 1 分钟调用一次 bot 的翻译接口,彩云小译的服务器用了 3 秒钟(实际肯定没那么久)响应了我们的 requests
。这 3 秒钟内,如果有其他用户调用了 bot 的另外一个指令,我们的 bot 就跟假死了一样,不会响应该用户的指令
这样看来,优势就很明显了:虽然在网络稳定的时候,requests
和 aiohttp
不会形成鲜明的效率差距,但在 KOOK 或者彩云小译服务器拥堵期间,我们的 bot 也能做到不会因为 requests
时间太长而影响用户的使用体验。
2. 利用抛异常机制更改翻译引擎
看到 main.py 中的 translate
部分,这里我 import
了 translate.py
中的相关函数,随后使用 bot.command
来调用这两个函数。那么如何让 bot 在有道翻译接口寄了的时候,自动去找备胎彩云小译呢?
- 简单了解抛异常
在 python 中,基本的抛异常机制如下:
1 | try: |
上面这个代码就是一个简单的抛异常机制。编译器会先尝试运行 try
后面的代码,如果该部分报错,则会转而执行 except
后的代码。
转换倒我们这里的例子,我们只需要在 try 后面写入有道翻译的代码,在 except 后写入彩云小译的代码,编译器就能在有道的接口出错的时候,自动找备胎
1 | try: |
3. 关于带空格英文句子传参问题
当我们翻译一个句子的时候,中文内容往往没有空格,但英文句子极其依赖于空格
进行单词的分割。
如果我们简单地使用 str 来接受传参,就会导致用户需要翻译的英文内容,只有第一个单词传了过来
1 | async def translate(msg: Message,txt:str): |
比如当用户打出:/TL I LOVE YOU
时,bot 实际接收到的只有首单词 I
,它会翻译该单词,可后面的 LOVE YOU
直接被无情抛弃了!
这里我们就需要使用 python 中牛逼的不定传参 *arg
了!
1 | async def translate(msg: Message,*arg): |
*arg
是 python 中支持的不定参数传参,即函数先前不知道用户会传入多少个参数。我们可以在传参完毕后,再对这些参数进行操作。
利用 *arg
的特性,我们可以一次性把所有单词都接收过来,再在函数中将它们拼成一个完整的字符串,传入到 translate
函数中。
1 | async def translate(msg: Message,*arg): |
这里的 " ".jion(arg)
代表用空格来分隔每一个参数,这样才能拼出一个完整的英文句子!

好了,基本的单句翻译已经写好了,但我们还可以整点花活,让 bot 可以实时翻译某一个文字频道内的所有消息!
4. 实时翻译(全局变量)
见 main.py
中的 ListTL
,这里我为实时翻译创建了一个全局数组,用来存放需要实时翻译的文字频道 id。
注意:ListTL
作为全局变量,在函数中调用的时候,需要先用 global ListTL
进行全局变量声明。否侧程序会在该函数中创建临时变量!
- 当用户需要实时翻译时,利用
/TLON
功能在他所在的文字频道开启该功能
bot 可以在 msg.ctx.channel.id
中获取到用户所在文字频道的 id,并将其写入 List 中
- 使用
@bot.command(regex=r'(.+)')
正则表达式获取文字频道的所有内容,再通过判断该文字频道 id 是否存于 List 之中,来确认是否要进行实时翻译并返回结果
这种正则方法也是让 bot 监看文字频道的一个非常好的办法,比如发现关键词之后,自动发送对应消息提示。
- 当用户使用
/TLOFF
关闭实时翻译后,将对应位置的 List 置零,空出栏位
具体的代码实现可以查看 main.py
中 translate
相关部分的函数
5. 处理 met 和 rol 消息
为了避免冲突,机器人不应该翻译 @xx用户
和 @xx角色
的消息,在 kook 的后台,机器人会接收到 (met)user_id(met)/(rol)role_id(rol)
格式的文字;
用下面的代码处理,可以将这两个串替换成空串,不进行翻译
1 | # 单独处理met和rol消息,不翻译这部分内容 |
结语
使用实时翻译可以实现一些好玩的事情:比如把一句话来回翻译 N 遍进行 “提纯”
(非常无聊了属于是)
- 最新
- 最热
- 最早
- 作者
点击重新获取 | 打开控制台