这是我参与「第五届青训营 」笔记创作活动的第1天。
一、本笔记重点内容
这次笔记主要记录了青训营课程《Go语言上手-基础语法》的课后作业的实现思路。
二、实践练习例子
本文使用的浏览器是Edge,其它浏览器的操作是类似的。 首先打开百度翻译网页:百度翻译-200种语言互译、沟通全世界! (baidu.com),页面如下图所示。
然后按F12键打开浏览器的开发者工具,点击标签中的“网络”,再之后点击网页中的“翻译”按钮,此时会记录到网络传输的很多包,在其中寻找含有v2transapi字符串的POST请求,如下图所示:
然后右键,选择“复制”中的“复制为cURL”,如下图所示:
之后使用在线工具:Convert curl commands to code (curlconverter.com),将curl命令转换成Go语言代码,如下图所示:
之后将go代码粘贴到IDE中,正常编译之后就可以运行
接着点击“响应”按钮,复制所有的json字符串并使用在线工具JSON格式化 - 在线工具 - OKTools将其转换为Go Struct。
但这里有一个坑!unmarshal的时候会报错
json: cannot unmarshal string into Go struct field .dict_result.oxford.unbox.data.words of type []string
原因:json中这个words字段的取值为空时,是""即字符串类型,而当它不为空时,是["abc", "cde"]之类的[]string类型,而oktools转换的结果固定式[]string类型,所以解析时就会出错!
修改方法:将oktools的结果中的Words字段的类型改为interface{}即可,相当于可以被解析成任何类型
然后将其复制到IDE中,接着修改之前curl的请求的代码。因为这里不像教学视频中POST的data是json,而是用的form data形式,所以可以不用结构体,而是用标准库中的url.Values{}来实现,这部分的代码如下:
func baiduQuery(word string) {
client := &http.Client{}
v := url.Values{}
v.Set("from", "en")
v.Set("to", "zh")
v.Set("query", word)
v.Set("transtype", "translang")
v.Set("simple_means_flag", "3")
v.Set("sign", "262931.57378")
v.Set("token", "f47d7de03be2df6d7ac0289a0c4f4682")
v.Set("domain", "common")
var data = strings.NewReader(v.Encode())
req, err := http.NewRequest("POST", "https://fanyi.baidu.com/v2transapi?from=en&to=zh", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept", "*/*")
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("Acs-Token", "1673683497235_1673750246180_hzkVnYt4hL2hfB8aEeQfEIIMdXuerp/5Owl5hUQmX34O+j5ZUWdKNHL1H+krAjfG4ZaqClfeL9VF2Fk22P31MTDULSevejUNTHlQFlzaFm56UTKukB9mVOCSuEmNwxm8qyTvMmNpnxZNR0cgzdohysvZPTHjftPrYReji9GDQiOc0Em7aP7jycGyjn3vyP02F/q6X2BkPjsR88B/KhV9wk0uQde8EWTTU/OW3WH8ABEt31N/osdkaQZ8rRe74jpRC2cnOXGm7a1VMAmUSwul0mMG+LmGCMQqy0kqY5IzamtCEPSGJbCjyIs5Hm7v2PkXLh/6xBfaANr4rnvO6A2Vfg==")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
req.Header.Set("Cookie", `PSTM=1639389141; __yjs_duid=1_52b93bf394660d17f9b77152bd3c0c4b1639408501078; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BAIDUID=841367B4A83210075A48780585D0E775:SL=0:NR=10:FG=1; BIDUPSID=F853417669221D259FA7C1AAACC9559C; H_WISE_SIDS_BFESS=110085_180636_188333_204427_204908_209568_211986_212295_212740_213029_213359_214795_215727_216839_216942_218566_219942_219946_220017_220067_220663_221678_221967_222298_222396_222625_223063_223211_224046_224049_224080_224157_224458_225595_225860_226006_226088_226275_226549_226628_227151_227515_227529_227865_227895_227933_227972_228650_228959_229061_229154_229240_229365_229492_229682_229867_229914_229976_230089_230216_230395_230622_230689_230846_230860_230925_230930_231091_231175_231209_231420_231465_231495_231665_231722_231754_231803_231833_231874_231906_231919_232052_232236_232254_232281_232452_232734_232818_232846_232874_232879_232908_233006_233040; APPGUIDE_10_0_2=1; MCITY=-%3A; BDUSS=DNHSXk1UVQ2eklCOUJMN29GdGJUTHdIaXRYcGVWcU0yV1BjR1hHWW1sVUZMZWhqSVFBQUFBJCQAAAAAAAAAAAEAAAC-FgNLTF9qX3BfSF9sX2wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWgwGMFoMBjN; BDUSS_BFESS=DNHSXk1UVQ2eklCOUJMN29GdGJUTHdIaXRYcGVWcU0yV1BjR1hHWW1sVUZMZWhqSVFBQUFBJCQAAAAAAAAAAAEAAAC-FgNLTF9qX3BfSF9sX2wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWgwGMFoMBjN; BAIDUID_BFESS=841367B4A83210075A48780585D0E775:SL=0:NR=10:FG=1; ariaDefaultTheme=undefined; RT="z=1&dm=baidu.com&si=ua34zmtmhqj&ss=lcv8g7vw&sl=6&tt=2cm&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=koi&ul=se1&hd=sez"; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BA_HECTOR=212gal200k208100000haldl1hs57s81k; ZFY=JECfAnYyf298H30OIwOZ8kvAgO5JbLAZQB7CmLK32O4:C; BDRCVFR[feWj1Vr5u3D]=mk3SLVN4HKm; delPer=0; PSINO=5; H_PS_PSSID=36554_37973_37647_37519_38025_37139_36920_37990_37921_38040_26350_37285_38009_37881; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1671509693,1671940439,1673750233; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1673750233; ab_sr=1.0.1_Mjg4OGQ0NjlmNTljMzQwMzUzZjhlMGQyYmEzNWNlMzYyY2I2ZWY0MWY0Mjg0OWUzZTYzY2MwMGY3NTk3NjA3OTM0ODUyODQ5NTE1NGEyZmViM2E0YzFjYTNmZjQ5NTg2MTcwMDk5NjhmOWU4YjMxNDlhMWI5NGNlYTQ0NTYzYThjNjdkMTAzNWFkODQ2ZDgwOTVmNzdmZTUxMTk2ZmQ3NGNiNzE4NDU5Mjc1ZWVmNWRmZjg2YzM5MjIwYWI1ZTkz`)
req.Header.Set("Origin", "https://fanyi.baidu.com")
req.Header.Set("Referer", "https://fanyi.baidu.com/")
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/109.0.0.0 Safari/537.36 Edg/109.0.1518.52")
req.Header.Set("X-Requested-With", "XMLHttpRequest")
req.Header.Set("sec-ch-ua", `"Not_A Brand";v="99", "Microsoft Edge";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)
//bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
//fmt.Printf("%s\n", bodyText)
var baiduResponse BaiduResponse
err = json.Unmarshal(bodyText, &baiduResponse)
if err != nil {
log.Fatal(err)
}
fmt.Println(baiduResponse.TransResult.Data[0].Dst)
}
其它部分的代码和视频中类似的,就不赘述了。
三、个人总结
本文主要介绍了如何用golang实现自动调用百度翻译API,重点如下:
- 网页F12抓包,需要找到发送请求的url,将其转成curl命令再转成Go代码
- 将响应内容json转成Go Struct,对于个别类型不统一的字段,要手动修改成interface{}类型,否则json反序列化无法完成
- 可以用url.Values{}构造form data格式的请求内容