这篇笔记用来记录我在做实战案例里的翻译工具中遇到的问题。
在课后练习中,我使用有道翻译作为第二个翻译工具
首先先打开有道翻译www.youdao.com/ 打开开发者中心,输入单词,在network中找到我们需要的post请求
在payload里我们可以找到发送请求需要的参数
不同于彩云翻译的是,这里是form data格式,因此我们并不需要自己定义发送请求的结构体,直接将string格式的word传进去就好,这里也是使用课程中的网站来直接转换请求的curl,然后修改一下发送过去的data参数。这样我们发送请求阶段就完成了。
总的来说,就是通过api调用,用POST请求发送我们的数据,再由它返回给我们数据,而我们需要对其数据进行处理,找到我们要的那部分就好。
func querybyYoudao(word string) {
client := &http.Client{}
var data = strings.NewReader("q=" + word + "&le=en&t=0&client=web&sign=bf6bfdc7703fc2ef45ce74f6b7ff6e40&keyfrom=webdict")
req, err := http.NewRequest("POST", "https://dict.youdao.com/jsonapi_s?doctype=json&jsonversion=4", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept", "application/json, text/plain, */*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Cookie", "OUTFOX_SEARCH_USER_ID=1474111096@10.112.57.88; OUTFOX_SEARCH_USER_ID_NCOO=1361789659.5254738")
req.Header.Set("Origin", "https://www.youdao.com")
req.Header.Set("Referer", "https://www.youdao.com/")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-site")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36")
req.Header.Set("sec-ch-ua", `"Not_A Brand";v="99", "Google Chrome";v="109", "Chromium";v="109"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Windows"`)
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
if resp.StatusCode != 200 {
log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))
}
var dictResponse2 AutoGenerated
err = json.Unmarshal(bodyText, &dictResponse2)
if err != nil {
log.Fatal(err)
}
fmt.Println(word, "UK:", dictResponse2.Ec.Word.Ukphone, "US:", dictResponse2.Ec.Word.Usphone)
for _, item := range dictResponse2.Ec.Word.Trs {
fmt.Println(item)
}
}
由于返回的是JSON格式的字符串,我们需要将其反序列化,并找到我们的翻译结果进行输出。
通过 JSON转Golang Struct - 在线工具 - OKTools 来将返回的 JSON 字符串转换为对应的 struct,并通过 json.Unmarshal 方法来对返回的结果进行处理,并保存到结构体变量中:
有道词典里preview里的JSON内容非常多,而且我在转过去之后发现有许多定义不明确的内容,我们只需要找到翻译结果的那部分JSON并将他转换成结构体就好。
也就是上面的EC这部分
type AutoGenerated struct {
Ec struct {
WebTrans []string `json:"web_trans"`
Special []struct {
Nat string `json:"nat"`
Major string `json:"major"`
} `json:"special"`
ExamType []string `json:"exam_type"`
Source struct {
Name string `json:"name"`
URL string `json:"url"`
} `json:"source"`
Word struct {
Usphone string `json:"usphone"`
Ukphone string `json:"ukphone"`
Ukspeech string `json:"ukspeech"`
Trs []struct {
Pos string `json:"pos,omitempty"`
Tran string `json:"tran"`
} `json:"trs"`
Wfs []struct {
Wf struct {
Name string `json:"name"`
Value string `json:"value"`
} `json:"wf"`
} `json:"wfs"`
ReturnPhrase string `json:"return-phrase"`
Usspeech string `json:"usspeech"`
} `json:"word"`
} `json:"ec"`
}
最后将请求返回的结果通过反序列化转换到结构体,然后输出就好了
var dictResponse2 AutoGenerated
err = json.Unmarshal(bodyText, &dictResponse2)
if err != nil {
log.Fatal(err)
}
fmt.Println(word, "UK:", dictResponse2.Ec.Word.Ukphone, "US:", dictResponse2.Ec.Word.Usphone)
for _, item := range dictResponse2.Ec.Word.Trs {
fmt.Println(item)
}
运行代码,可以成功运行
事实上,我在用有道翻译之前也尝试过用百度翻译,百度翻译也是FORM DATA格式,但是我并不能成功使用。在检查过程中,我发现使用百度的请求无法返回正确的JSON,导致在转换结构体这阶段找不到我要的内容。我并没有成功解决这个问题。只能说我自己的水平确实有限。还需多多学习。