Go实现单词翻译功能 | 青训营笔记

204 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记

在线词典功能介绍

在调用程序时只需要在后面填入单词,就会显示单词的意思

原理是调用第三方的API查询单词的翻译,并且将查询结果打印出来

这里我调用的是火山翻译,因为火山翻译返回结果是简单的Json格式,不需要进行一些复杂的变换

程序运行实例图如下:

image.png

程序实现过程

1、抓包、解析网站发送的数据格式

我们打开火山翻译界面,打开浏览器控制台监控网络传输情况

任意输入一个单词,找到我们需要的返回文件数据

image.png

能看到如上图手势指向的文件就是发送的请求

可以看到请求的数据和配置很多,如果要自己完成可能非常麻烦

我们可以使用 curlconverter.com/#go 提供的实现自动的生成相关代码功能

右键该文件,选择复制为cURL

image.png

将复制结果粘贴到 curlconverter.com/#go 中,就能够自动生成相关代码了

image.png

2、解析返回的JSON数据

得到代码后,我们来分析一下代码的内容

image.png

来尝试运行一下看看能输出什么内容

image.png

可以看到输出了一大串的JSON,我们需要的结果就在JSON里

为了简单起见,这里只提取该单词的翻译。其中的例句之类的信息直接丢弃

我们要反序列化结果的JSON,可以使用 oktools.net/json2go 提供的工具生成JSON的结构代码

复制输出的结果,除去一些换行等信息。

因为我们不需要对返回结果进行过多的操作,使用“转换-嵌套”,可以使得代码更为紧凑

image.png

接下来我们修改一些代码,将JSON数据反序列化到变量中

image.png

AutoGenerated就是上面得到的JSON的格式化代码。可以使用“%#v”输出结构体变量的详细信息

我们可以得到一长串的信息,但是我们不需要这么多信息,只需要翻译的内容

image.png

结合输出结果和结构体代码,我们可以找到翻译结果的存储位置:

image.png

所以我们只需要输出AutoGenerated下的Words下的PosList下的Explanations下的Text就可(可能有点长

所以再次修改我们的代码:

image.png

我们就能得到需要的输出了

3、设置命令行输入单词翻译

我们发现现在需要翻译其他单词只能修改源代码,这显然没有做到一个程序员应该做到的交互操作

我们可以将原main函数中的代码封装为一个函数,函数设置word参数,实现从命令行输入单词传入函数得到翻译结果

完成这两步我们的程序就算成功了

image.png

image.png

最后我们的功能展示如下

image.png

4、最终代码

package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

type AutoGenerated struct {
	Words []struct {
		Source  int    `json:"source"`
		Text    string `json:"text"`
		PosList []struct {
			Type      int `json:"type"`
			Phonetics []struct {
				Type int    `json:"type"`
				Text string `json:"text"`
			} `json:"phonetics"`
			Explanations []struct {
				Text     string `json:"text"`
				Examples []struct {
					Type      int `json:"type"`
					Sentences []struct {
						Text      string `json:"text"`
						TransText string `json:"trans_text"`
					} `json:"sentences"`
				} `json:"examples"`
				Synonyms []interface{} `json:"synonyms"`
			} `json:"explanations"`
			Relevancys []interface{} `json:"relevancys"`
		} `json:"pos_list"`
	} `json:"words"`
	Phrases  []interface{} `json:"phrases"`
	BaseResp struct {
		StatusCode    int    `json:"status_code"`
		StatusMessage string `json:"status_message"`
	} `json:"base_resp"`
}

func HuoShan(word string) {
	client := &http.Client{}
	var data = strings.NewReader(`{"text":"` + word + `","language":"en"}`)
	req, err := http.NewRequest("POST", "https://translate.volcengine.com/web/dict/match/v1/?msToken=&X-Bogus=DFSzswVLQDc7Eu3KSWH2qsUClLxa&_signature=_02B4Z6wo00001FnkuZAAAIDBcm7iVysoh5BZ5L0AAHQHcz130TjK8x7CNsIS6vQ3Lj2smHucJ9SY6YcbE9BvRlUhX2nU9vWWanBFiKBRb5hyOGW8usVR0hQ9LFhYX9eu87Z5Q.JUqqwnKb1f12", data)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("authority", "translate.volcengine.com")
	req.Header.Set("accept", "application/json, text/plain, */*")
	req.Header.Set("accept-language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
	req.Header.Set("cache-control", "no-cache")
	req.Header.Set("content-type", "application/json")
	req.Header.Set("cookie", "x-jupiter-uuid=16518491619698024; i18next=zh-CN; ttcid=edaf3b3b984140d884d5c8b7e75d023d29; s_v_web_id=verify_7803fc0105a7bd23f690d645be06e37e; _tea_utm_cache_2018=undefined; tt_scid=P2mPJqgyrhzfyPg79xGj36hfHCIbkYY0l5uc865DMdrjTrbwbQjNAX7xiEUJD5vh9722")
	req.Header.Set("origin", "https://translate.volcengine.com")
	req.Header.Set("pragma", "no-cache")
	req.Header.Set("referer", "https://translate.volcengine.com/translate?category=&home_language=zh&source_language=detect&target_language=zh&text=good")
	req.Header.Set("sec-ch-ua", `" Not A;Brand";v="99", "Chromium";v="101", "Microsoft Edge";v="101"`)
	req.Header.Set("sec-ch-ua-mobile", "?0")
	req.Header.Set("sec-ch-ua-platform", `"Windows"`)
	req.Header.Set("sec-fetch-dest", "empty")
	req.Header.Set("sec-fetch-mode", "cors")
	req.Header.Set("sec-fetch-site", "same-origin")
	req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39")
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
	bodyText, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}
	// fmt.Printf("%s\n", bodyText)
	var autoGenerated AutoGenerated
	err = json.Unmarshal(bodyText, &autoGenerated)
	if err != nil {
		log.Fatal(err)
	}
	// fmt.Printf("%#v", autoGenerated)
	fmt.Println(autoGenerated.Words[0].PosList[0].Explanations[0].Text)
}
func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
		`)
		os.Exit(1)
	}
	word := os.Args[1]
	HuoShan(word)
}