转载自编写 Albert 翻译插件,Mark住有时间自己也参照写一个
翻译接口 - 有道词典(有道智云)
翻译插件主要参考上文链接 2,作者使用了有道词典。为了了解发送查询到有道,再到数据返回形式,最终将该形式的数据如何通过 albert 接口读取后显示。所以我也注册了有道智云,然后使用 API 获取了一下查询单词的数据。
由于原先我已经注册过了百度的翻译 API,但是发现有道的返回结果更加丰富。所以我就不打算将源转为百度了。如果有一定编程经验的朋友,看过之后会发现编写这么一个 albert 插件还是很简单的,其中接口和显示等形式和用法都很直接易懂。但是,这篇博客还是比参考链接 2 中更精细地记录了实现一个 albert 翻译插件的过程(同时在代码上使用 Python3,和 Albert 提供的其它新接口),因为这样也方便我自己以后回顾查看。
1 使用查询翻译 API
在真正去实现 Albert 翻译插件之前,必须要了解清楚如何实现翻译,如何使用翻译接口。
如果之前没有使用过类似此种接口的经验的话,不妨花几十分钟到小几个小时实践一下。
这里 ? 有一篇我较早写的使用百度翻译 API 的博客。
1.1 注册以获得 ID 和 Key
参阅 有道智云帮助文档 ?
1.2 使用翻译API示例
n/a
查询结果
{
"tSpeakUrl":"http://openapi.youdao.com/ttsapi?q=%E8%8B%B9%E6%9E%9C&langType=zh-CHS&sign=n/a&salt=n/a&voice=4&format=mp3&appKey=n/a",
"returnPhrase":["apple"],
"web":[{"value":["苹果","苹果公司","苹果电脑","苹果汁"],"key":"Apple"},
{"value":["苹果公司","美国苹果公司","苹果"],"key":"apple inc"},
{"value":["韩版恶作之吻造型曝光"],"key":"Apple Daily"}],
"query":"apple",
"translation":["苹果"],
"errorCode":"0",
"dict":{"url":"yddict://m.youdao.com/dict?le=eng&q=apple"},
"webdict":{"url":"http://m.youdao.com/dict?le=eng&q=apple"},
"basic":{
"exam_type":["初中"], "us-phonetic":"\'æpl",
"phonetic":"\'æp(ə)l", "uk-phonetic":"\'æp(ə)l",
"uk-speech":"http://openapi.youdao.com/ttsapi?q=apple&langType=en&sign=n/a&salt=n/a&voice=5&format=mp3&appKey=n/a",
"explains":["n. 苹果,苹果树,苹果似的东西;[美俚]炸弹,手榴弹,(棒球的)球;[美俚]人,家伙。"],
"us-speech":"http://openapi.youdao.com/ttsapi?q=apple&langType=en&sign=n/a&salt=n/a&voice=6&format=mp3&appKey=n/a"
},
"l":"en2zh-CHS",
"speakUrl":"http://openapi.youdao.com/ttsapi?q=apple&langType=en&sign=n/a&salt=n/a&voice=4&format=mp3&appKey=n/a"
}
1.3 按条目提取结果用于显示
对结果一行一行显示,去除一些获取发音的链接等。
第一个显示读音(“phonetic”:"'æp(ə)l"):
>>> response_json2dict['basic']['phonetic']
'æp(ə)l
我们可以看到一个单词对应中文可以有多个“不同的”(非同义)释义和不同的词性,并且含有“网络释义”(上例只有一个,但是中返回的 json 中释义键对应的值使用的是列表(加上常识)可以推断出上述),
将每一个(不同的)“标准”释义起一行显示:
>>> for explain in response_json2dict['basic']['explains']:
print(explain)
n. 苹果,苹果树,苹果似的东西;[美俚]炸弹,手榴弹,(棒球的)球;[美俚]人,家伙。
将每一个(不同的)网络释义一行行显示:
>>> for web_expl in response_json2dict['web']:
print(web_expl)
{'key': 'Apple', 'value': ['苹果', '苹果公司', '苹果电脑', '苹果汁']}
{'key': 'apple inc', 'value': ['苹果公司', '美国苹果公司', '苹果']}
{'key': 'Apple Daily', 'value': ['韩版恶作之吻造型曝光']}
至此我们就按题目(行)提取出了发音、释义、网络释义的内容,对于一个单词的翻译有这些就足够了。
2 关于 Albert 插件
做一个“直接的”,最简单的 demo:
"""This is a simple python template extension.
Synopsis: spell word"""
from albertv0 import *
import os
__iid__ = "PythonInterface/v0.1"
__prettyname__ = "Speel Word"
__version__ = "1.0"
__trigger__ = "spell "
__author__ = "Joseph Lin"
__dependencies__ = []
ICON_PATH = iconLookup("albert")
def handleQuery(query):
if not query.isTriggered:
return
results = []
for letter in query.string:
item = Item(id="", icon=ICON_PATH,
text=letter, subtext="",
completion="", urgency=ItemBase.Notification, actions=[])
results.append(item)
return results
aGVpdGk,shadow_10,text_aHR0cHM6Ly9zaXhnb2xkZW4uYmxvZy5jc2RuLm5ldA==,size_16,color_FFFFFF,t_70)
安装方式:
将上面代码保存为 spell.py 文件。
然后复制到 python 模块目录下即完成安装:
$ cp spell.py ~/.local/share/albert/org.albert.extension.python/modules
注:如果没有特意配置过,albert 对结果显示 5 个条目,多出的条目需要使用上下键来查看。
2.1 激活“代码”
2.2 键入的查询
在 Ablert 搜索(查询)输入框中,输入了 "tr " + “word” 之后,回车,Albert 根据激活代码 "tr " 调用对应插件的 handleQuery 函数1,该函数执行期望的查询功能,并且最后通过构造一个含有 (Albert 接口提供的)Item 类2元素的列表返回以用于显示查询结果。
2.3 结果输出
3 使用翻译 API 编写 Albert 翻译插件
3.1 注册激活代码
__trigger__ = "tr " # 触发命令
3.2 发起查询
获取查询单词:word = query.string
生成 url:url = getUrl(‘auto’, ‘zh’, word)
发起查询:req = requests.get(url, headers={‘User-Agent’: ua})
将查询结果(json)转化为字典对象:response_json2dict = json.loads(req.text)
def get_result_from_API_as_dict(word):
url = getUrl('auto', 'zh', word)
req = requests.get(url, headers={'User-Agent': ua})
return json.loads(req.text)
data = get_result_from_API_as_dict(query.string)
3.3 从查询结果构建显示条目
初始化一个显示的条目对象: item = Item()
显示的内容:item.text = data[‘basic’][‘phonetic’]
小号的说明字段:item.subtext = “phonetic”
将条目对象加入用于显示的列表:results.append(item)
def generate_display_items(data):
results = []
item = Item() # 发音
item.text = data['basic']['phonetic']
item.subtext = "phonetic"
results.append(item)
for explain in data['basic']['explains']:
item = Item() # 释义
item.text = explain
item.subtext = 'explain'
results.append(item)
for web_expl in data['web']:
item = Item() # 网络释义
item.text = web_expl
item.subtext = 'web explain'
results.append(item)
return results
return generate_display_items(data)
3.4 拓展插件的信息
__iid__ = "PythonInterface/v0.1"
__prettyname__ = "Translation Word"
__version__ = "1.0"
__author__ = "Joseph Lin"
__dependencies__ = ["requests", "youdao account"]
3.5 完整模块代码
"""translation module.
Synopsis: <triger> <word>
"""
import locale
import json
import urllib.parse
import hashlib
from albertv0 import *
import requests
__iid__ = "PythonInterface/v0.1"
__prettyname__ = "Translation Word"
__trigger__ = "tr "
__version__ = "1.0"
__author__ = "Joseph Lin"
__dependencies__ = ["requests", "youdao account"]
ICON_PATH = iconLookup("albert")
TO_LANG = 'zh'
def initialize():
global TO_LANG
try:
TO_LANG = locale.getdefaultlocale()[0].split('_')[0] # cat /etc/locale.gen
except Exception as err:
warning(err)
class YouDaoAPI():
ua = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36"
urltmpl = "http://openapi.youdao.com/api?appKey={}&q={}&from=auto&to={}&salt={}&sign={}"
langSupported = dict.fromkeys(('zh', 'en', 'es', 'fr', 'ko', 'ja', 'ru', 'pt'))
def __init__(self, word):
self.word = word
def get_url(self, src, dst, txt):
''' 按有道的格式生成请求地址。src为源语言,dst为目标语言 '''
appKey = '<你的产品ID>' # 注册智云后获得
secretKey = '<你的密钥>'
salt = '123456' # TODO: 使用随机数
sign = appKey + txt + salt + secretKey
m1 = hashlib.md5()
m1.update(sign.encode(encoding='utf-8'))
sign = m1.hexdigest()
q = urllib.parse.quote_plus(txt)
url = self.urltmpl.format(appKey, q, dst, salt, sign)
return url
def get_result_from_api_as_dict(self):
url = self.get_url('auto', TO_LANG, self.word)
req = requests.get(url, headers={'User-Agent': self.ua})
return json.loads(req.text)
def generate_display_items(data):
results = []
if set({'web', 'phonetic', 'basic'}) & set(data.keys()):
try:
results.append( # 发音
Item(id="", icon=ICON_PATH,
completion="", urgency=ItemBase.Notification,
text=str(data['basic']['phonetic']),
subtext="phonetic",
actions=[]))
except:
pass
try:
for explain in data['basic']['explains']: # 释义
results.append(
Item(id="", icon=ICON_PATH,
completion="", urgency=ItemBase.Notification,
text=str(explain), subtext='explain', actions=[]))
except:
pass
try:
for web_expl in data['web']: # 网络释义
results.append(
Item(id="", icon=ICON_PATH,
completion="", urgency=ItemBase.Notification,
text="{}: {}".format(web_expl['key'], web_expl['value']),
subtext='web explain', actions=[]))
except:
pass
return results
raise RuntimeError("no result")
def handleQuery(query):
if not query.isValid or not query.isTriggered or len(query.string) <= 1:
return
# info(query.string)
try:
data = YouDaoAPI(query.string).get_result_from_api_as_dict()
except Exception as err:
warning("{!r}".format(err))
return [Item(id="", icon=ICON_PATH,
completion="", urgency=ItemBase.Notification,
text=str(err), subtext="YouDaoAPI Error", actions=[])]
try:
return generate_display_items(data)
except Exception as err:
warning("{!r}".format(err))
return [Item(id="", icon=ICON_PATH,
completion="", urgency=ItemBase.Notification,
text=str(err), subtext="Generate items Error", actions=[])]
4 Know Issue
虽然比较靠后,但是这一节非常非常重要!!!
关于可能崩溃退出,重新加载模块问题。
参阅 【译】拓展 Albert(编写 Alber 插件和拓展) 中的 Know Issue 小节。
5 功能升级与更新
请参阅下一篇博客 ? 编写 Albert 翻译插件之功能升级 ?