对腾讯AI机器翻译接口的调用
在上一次文字识别代码的基础上,进行了改进,代码结构优化了一点(我认为···)
开完账号,加好应用能力,安装好依赖包,按代码最后的提示改成http(如果要在其他页面中访问,就需要设置 https),就可以启动服务了。浏览器输入 http://localhost:8203/trans/to/zh?text=hello 进行测试我测试用的前端代码也已给出(本来的目的是要实现一个小插件)其中Param 及其方法可以用于腾讯 AI 其他 Api 调用,例:
package main
import (
"bytes"
"crypto/md5"
"encoding/hex"
"fmt"
"github.com/gin-gonic/gin"
"github.com/unrolled/secure"
"io/ioutil"
"log"
"net/http"
"net/url"
"sort"
"strings"
"time"
)
/*
可以直接拿去使用
把自己开通好的 id 和 key 换了就可以,需要在应用中添加对应能力
返回的数据是没有进行json解析,添加自定义的 status 之后直接返回到前端解析
*/
var (
// 自己去官网开账号,开应用
appId = "*"
appKey = "*"
)
// 为了排序
type Param struct {
key, value string
}
func SortParams(p []Param) {
// 升序
sort.Slice(p, func(i, j int) bool {
if p[i].key < p[j].key {
return true
}
return false
})
}
func ParamsToString(p []Param) string {
s := ""
for _, v := range p {
if v.value == "" {
continue
}
// value 需要进行 url 编码
s += v.key + "=" + url.QueryEscape(v.value) + "&"
}
return s[:len(s)-1]
}
func PostToTansApi(text, target string) (s []byte, ok bool) {
client := http.Client{}
params := make([]Param, 0, 10)
params = append(params, Param{"app_id", appId})
params = append(params, Param{"source", "auto"})
params = append(params, Param{"target", target})
params = append(params, Param{"text", text})
// 随便啥都行,非空且长度小于32
params = append(params, Param{"nonce_str", "asbfiuasbhjbcuicg"})
params = append(params, Param{"time_stamp", fmt.Sprintf("%d", time.Now().Unix())})
// 取得动态加密标志,获取body
params = getSign(params)
form := ParamsToString(params)
body := bytes.NewBufferString(form)
request, err := http.NewRequest("POST", "https://api.ai.qq.com/fcgi-bin/nlp/nlp_texttranslate", body)
if err != nil {
log.Println(err)
return
}
// 重要的!!!
request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
response, err := client.Do(request)
if err != nil {
log.Println(err)
return
}
defer response.Body.Close()
s, err = ioutil.ReadAll(response.Body)
if err != nil {
log.Println(err)
return
}
return s, true
}
func getSign(p []Param) []Param {
s := strings.Builder{}
SortParams(p)
s.WriteString(ParamsToString(p))
s.WriteString("&app_key=" + appKey)
// MD5
hash := md5.New()
hash.Write([]byte(s.String()))
encodeToString := strings.ToUpper(hex.EncodeToString(hash.Sum(nil)))
p = append(p, Param{"sign", encodeToString})
return p
}
func TansToZHHandle(c *gin.Context) {
text, ok := c.GetQuery("text")
if !ok || text == "" {
c.JSON(http.StatusOK, map[string]string{"status": "no", "msg": "参数呢"})
return
}
s, ok := PostToTansApi(text, "zh")
if !ok {
c.JSON(http.StatusOK, map[string]string{"status": "no", "msg": "不可能出现的错误,多次失败请联系管理员"})
return
}
c.JSON(http.StatusOK, map[string]string{"status": "ok", "msg": string(s)})
}
func TansToENHandle(c *gin.Context) {
text, ok := c.GetQuery("text")
if !ok || text == "" {
c.JSON(http.StatusOK, map[string]string{"status": "no", "msg": "参数呢"})
return
}
s, ok := PostToTansApi(text, "en")
if !ok {
c.JSON(http.StatusOK, map[string]string{"status": "no", "msg": "不可能出现的错误,多次失败请联系管理员"})
return
}
c.JSON(http.StatusOK, map[string]string{"status": "ok", "msg": string(s)})
}
func AllowControl(c *gin.Context) {
c.Header("Access-Control-Allow-Origin", "*")
}
func TlsHandler(c *gin.Context) {
secureMiddleware := secure.New(secure.Options{
SSLRedirect: true,
SSLHost: ":8203",
})
err := secureMiddleware.Process(c.Writer, c.Request)
if err != nil {
log.Println(err)
return
}
}
func main() {
gin.SetMode(gin.ReleaseMode)
r := gin.Default()
r.Use(TlsHandler)
r.Use(AllowControl)
{
r.GET("trans/to/zh", TansToZHHandle)
r.GET("trans/to/en", TansToENHandle)
}
err := r.RunTLS(":8203", "*.pem", "*.key")
if err != nil {
panic(err)
}
}
/*
本地测试注释掉
r.Use(TlsHandler())
改
err := r.RunTLS(":8203", "*.pem", "*.key")
为
err := r.Run(":8203")
*/
前端示例
- 这里设置了按 ` 显示/隐藏 ESC下面的
- 仅提供参考,如果我的实例不能访问,替换为本地开启的服务 http://localhost:8203/* 或其他。。。
- 如果需要,样式大小自行修改
- 嗯。。希望能有点用吧
<!doctype html>
<html lang="ch">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<style>
#trans-container {
top: 200px;
left: 200px;
margin: 0 auto;
border-radius: 8px;
box-shadow: 0 0 0 -20px rgba(0, 0, 0, .2), 0 24px 38px 3px rgba(0, 0, 0, .14), 0 9px 46px 8px rgba(0, 0, 0, .12);
position: fixed;
background: rgba(255, 255, 255, 0.95);
width: 150px;
max-height: 100px;
overflow: auto;
opacity: 40%;
z-index: 999999999;
}
#trans-container div p,
#trans-container div input {
font-weight: 100;
padding: 0;
margin: 0;
}
#trans-container div input{
border-width: 0;
}
#trans-container div input:focus{
outline: none;
}
#trans-container::-webkit-scrollbar {
display: none;
}
[v-cloak] {
display: none
}
</style>
</head>
<body>
<div id="trans-container" @mousedown="move" v-cloak v-show="show">
<div style="text-align: center;">
<input type="text" v-model="text" placeholder="翻译,在此输入" @keypress.enter="send"
style="width: 100%;text-align: center;">
</div>
<div>
<p v-text="ret"></p>
</div>
</div>
</body>
<script>
let pattern = new RegExp("[\u4E00-\u9FA5]+");
function getTrans(text) {
if (pattern.test(text)) {
if (window.top.transapp)
getEN(text)
} else {
if (window.top.transapp)
getZH(text)
}
}
function getZH(text) {
axios.get('https:ligaofeng.top:8203/trans/to/zh?text=' + text)
.then(function (response) {
let data = response.data;
if (data["status"] == "ok") {
data = data.msg;
data = JSON.parse(data);
if (data.ret!=0){
console.log(data.msg)
window.top.transapp.ret = "翻译失败";
return
}
window.top.transapp.ret = data.data.target_text;
} else {
console.log(data.msg)
window.top.transapp.ret = "翻译失败";
}
})
.catch(function (error) {
console.log(error);
window.top.transapp.ret = "翻译失败";
});
}
function getEN(text) {
axios.get('https:ligaofeng.top:8203/trans/to/en?text=' + text)
.then(function (response) {
let data = response.data;
if (data["status"] == "ok") {
data = data.msg;
data = JSON.parse(data);
if (data.ret!=0){
console.log(data.msg)
window.top.transapp.ret = "翻译失败";
return
}
window.top.transapp.ret = data.data.target_text;
} else {
console.log(data.msg)
window.top.transapp.ret = "翻译失败";
}
})
.catch(function (error) {
console.log(error);
window.top.transapp.ret = "翻译失败";
});
}
window.top.addEventListener("keypress", function (ev) {
switch (ev.key) {
case "`":
if (!window.top.transapp)
window.top.transapp = new Vue({
el: "#trans-container",
data: {
text: "",
ret: "",
positionX: 0,
positionY: 0,
show: true
},
methods: {
send() {
if (this.text) {
this.ret = "获取中。。。"
getTrans(this.text)
this.text = ""
}
},
move(e) {
let odiv = document.getElementById("trans-container");
let disX = e.clientX - odiv.offsetLeft;
let disY = e.clientY - odiv.offsetTop;
document.onmousemove = (e) => {
let left = e.clientX - disX;
let top = e.clientY - disY;
this.positionX = top;
this.positionY = left;
odiv.style.left = left + 'px';
odiv.style.top = top + 'px';
};
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
};
},
}
})
else
window.top.transapp.show = !window.top.transapp.show
break
}
})
</script>
</html>