这是我参与「第五届青训营 -后端场」笔记创作活动的的第1篇笔记
1 介绍
- 功能:用户可以在命令行输入想要查询的单词,然后程序会通过调用第三方翻译的API查询单词的翻译内容,并将查询结果打印到终端显示出来
- 技术要点:Go、HTTP请求的发送和响应的处理、解析JSON
2 实现过程
2.1 翻译引擎
采用了视频中所说的火山引擎
2.2 抓包
打开火山翻译引擎的网页,然后按F12或点击鼠标右键“检查”打开开发者工具
在输入完单词进行查询之后,就会出现如图所示的翻译文件
2.3 代码生成
右键该文件,并复制其cURL到 curlconverter.com/#go然后复制下来写到本地文件main.go
运行程序可以得到
接着对请求结果进行处理
2.4 生成resquest body
将其复制下来到oktools.net/json2go 可以生成结构体
接着将
var data = strings.NewReader(`{"source":"youdao","words":["good"],"source_language":"en","target_language":"zh"}`)
修改为
2.5解析response body
不知道是我电脑的问题还是怎么回事,跟所教学的不太一样,不过,我会出手!
在响应这里,将其复制到oktools.net/json2go 进行解析,可以得到
接下来将之前读取的响应内容,使用json.Unmarshal方法反序列化到结构体中,即将主函数最后的fmt.Printf("%s\n", bodyText)这行语句,修改变成:
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse)
if err != nil {
log.Fatal(err)
}
此时响应内容以JSON格式存储在了dictResponse中。
2.6 打印结果
因为要查询任意单词,所以将之前的主函数改为一个参数为单词字符串的查询函数,即将func main()改为func query(word []string),将查询特定good单词的语句 request := DictRequest{Source: "youdao", Words: "["good"]", SourceLanguage: "en", TargetLanguage: "zh"} 改为 request := DictRequest{Source: "youdao", Words: word, SourceLanguage: "en", TargetLanguage: "zh"} ,并添加主函数:
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, `usage: simpleDict WORD example: simpleDict hello`)
os.Exit(1)
}
query(os.Args[1:])
}
此时在命令行下进入文件目录后输入go run main.go word,即可对指定单词进行查询
2.7 继续解析response
如果就按照刚才的进行输出,还是乱序无章,观察
可以看到结果都在第二层
detail里面,于是可以在做完第一次json.Unmarshal方法反序列化到结构体中之后取其detail,Detail := dictResponse.Details[0].Detail然后将其输出
根据输出结果建立结构体(复制到oktools.net/json2go 进行解析)
2.8 完整代码
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
type DictRequest struct {
Source string `json:"source"`
Words []string `json:"words"`
SourceLanguage string `json:"source_language"`
TargetLanguage string `json:"target_language"`
}
type DictResponse struct {
Details []struct {
Detail string `json:"detail"`
Extra string `json:"extra"`
} `json:"details"`
BaseResp struct {
StatusCode int `json:"status_code"`
StatusMessage string `json:"status_message"`
} `json:"base_resp"`
}
type DictResponse_Detail struct {
ErrorCode string `json:"errorCode"`
RequestID string `json:"requestId"`
Msg string `json:"msg"`
Result []struct {
Ec struct {
ReturnPhrase []string `json:"returnPhrase"`
Synonyms []struct {
Pos string `json:"pos"`
Words []string `json:"words"`
Trans string `json:"trans"`
} `json:"synonyms"`
Etymology struct {
ZhCHS []struct {
Description string `json:"description"`
Detail string `json:"detail"`
Source string `json:"source"`
} `json:"zh-CHS"`
} `json:"etymology"`
SentenceSample []struct {
Sentence string `json:"sentence"`
SentenceBold string `json:"sentenceBold"`
Translation string `json:"translation"`
Source string `json:"source"`
} `json:"sentenceSample"`
WebDict string `json:"webDict"`
Web []struct {
Phrase string `json:"phrase"`
Meanings []string `json:"meanings"`
} `json:"web"`
MTerminalDict string `json:"mTerminalDict"`
RelWord struct {
Word string `json:"word"`
Stem string `json:"stem"`
Rels []struct {
Rel struct {
Pos string `json:"pos"`
Words []struct {
Word string `json:"word"`
Tran string `json:"tran"`
} `json:"words"`
} `json:"rel"`
} `json:"rels"`
} `json:"relWord"`
Dict string `json:"dict"`
Basic struct {
UsPhonetic string `json:"usPhonetic"`
UsSpeech string `json:"usSpeech"`
Phonetic string `json:"phonetic"`
UkSpeech string `json:"ukSpeech"`
ExamType []string `json:"examType"`
Explains []struct {
Pos string `json:"pos"`
Trans string `json:"trans"`
} `json:"explains"`
UkPhonetic string `json:"ukPhonetic"`
WordFormats []struct {
Name string `json:"name"`
Value string `json:"value"`
} `json:"wordFormats"`
} `json:"basic"`
Phrases []struct {
Phrase string `json:"phrase"`
Meanings []string `json:"meanings"`
} `json:"phrases"`
Lang string `json:"lang"`
IsWord bool `json:"isWord"`
} `json:"ec"`
} `json:"result"`
}
func query(w []string) {
client := &http.Client{}
// var data = strings.NewReader(`{"source":"youdao","words":["good"],"source_language":"en","target_language":"zh"}`)
request := DictRequest{Source: "youdao", Words: w, SourceLanguage: "en", TargetLanguage: "zh"}
buf, err := json.Marshal(request)
if err != nil {
log.Fatal(err)
}
var data = bytes.NewReader(buf)
req, err := http.NewRequest("POST", "https://translate.volcengine.com/web/dict/detail/v1/?msToken=&X-Bogus=DFSzswVLQDaZVwrASZWeZ37TlqSX&_signature=_02B4Z6wo00001bQXZJQAAIDCIME.mlnFBXW0F2AAAA7HCjAJYYrhhoQpKtCNBZ4DvM3uCw2HmLtMw9tRYCIsQF1PdGVb8Qco3.OJBjWm74knkFabcutJC8rwMRONm5rvh2WHbxXQlkAGb5aRea", 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-US;q=0.8,en;q=0.7")
req.Header.Set("content-type", "application/json")
req.Header.Set("cookie", "x-jupiter-uuid=16737874782996226; i18next=zh-CN; s_v_web_id=verify_lcxduk3g_aatU4Zh1_znbW_4LK1_Bl4d_K3w7RCsU8teA; ttcid=6150c6c309cc40fea7cc6e96f1e2b2a414; tt_scid=7NTge.aVQRRHaMQSMrZLus.Lq8aGpQ10EO9N8QMv9Uu0EpMH-b3YvEDTJqFQmNv90bdc")
req.Header.Set("origin", "https://translate.volcengine.com")
req.Header.Set("referer", "https://translate.volcengine.com/mobile?category=&home_language=zh&source_language=detect&target_language=zh&text=good")
req.Header.Set("sec-ch-ua", `"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"macOS"`)
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 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36")
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)
}
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse)
if err != nil {
log.Fatal(err)
}
Detail := dictResponse.Details[0].Detail
var detail DictResponse_Detail
err = json.Unmarshal([]byte(Detail), &detail)
if err != nil {
log.Fatal(err)
}
fmt.Println("[US: ", detail.Result[0].Ec.Basic.UsPhonetic, "]", "[UK: ", detail.Result[0].Ec.Basic.UkPhonetic, "]")
for i, item := range detail.Result[0].Ec.Basic.Explains {
fmt.Println(i+1, item.Pos, item.Trans)
}
}
func main() {
if len(os.Args) != 2 {
fmt.Fprint(os.Stderr, "usage: simpleDict WORD example: simpleDict hello", os.Args[0])
os.Exit(1)
}
query(os.Args[1:])
}