Go语言上手 - 实现命令行字典 | 青训营笔记

180 阅读4分钟

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

字节跳动青训营开课第1天!期待已久的青训营课程今天终于开始啦。今天的课程为我们讲解了go语言的基础语法,并给出了三个十分有趣的小demo,命令行字典便是其中之一。

QQ图片20220507202007.png

网课github仓库提供了demo的源码,运行效果如上图。源码中用到了彩云翻译引擎的接口,基本实现了英文单词翻译的基础功能,十分别致!直播课中也详细的讲解了这个字典的实现过程和思路。

课程结束后,讲师为我们布置了对应的作业——为命令行字典添加另一个翻译引擎! 那我也参照直播课中的思路来做一下吧。

抓取接口

首先选择一个翻译引擎,这里我使用百度翻译。打开百度翻译页面,随便输入一个单词:

image.png

如所期望的看到了单词的具体翻译。然后打开开发者工具,再次点击翻译按钮:

image.png

观察network情况,发现一时间内出现了大量的请求,其中一条名为v2transapi的请求响应里刚好包含了我们想要的翻译信息。

然鹅,经过尝试,很遗憾的发现这个接口很难拿来用啦,原因是其负载的表单数据中有一个sign字段不知道是怎么得来的。在无法给出正确的sign值的情况下请求都失败了......

好在经过一番观察,我很快找到了另一个名为sug的请求,其响应也给出了我们所需的翻译信息!(虽然没有音标),其参数只需要一个要翻译的英文单词即可,十分简洁。

生成代码

确定了要使用的接口,我们便复制请求对应的curl:

QQ图片20220507205729.png

然后打开直播课中提到的网站:curlconverter.com,在其中生成向该接口发送请求的Go语言代码。

image.png

取得到代码后,将其粘贴到我们之前的demo源码中,并将其单独封装到一个方法里面,以便之后调用:

func queryBD(word string) {
	client := &http.Client{}
	var data = strings.NewReader("kw=" + word)
	req, err := http.NewRequest("POST", "https://fanyi.baidu.com/sug", data)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Accept", "application/json, text/javascript, */*; q=0.01")
	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("Connection", "keep-alive")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	req.Header.Set("Cookie", `BIDUPSID=C800CE5CD446FC3EB5BF645BA351081E; PSTM=1629005484; BDUSS=d1ZnVqSGVmTH43LXh5UDRSRDR3WTNoQWdLajY0dlNQMW1ZRllSSEhiUVZOVUJoRVFBQUFBJCQAAAAAAAAAAAEAAAC029PNwvrL8Mer0uZ0cnoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWoGGEVqBhhTH; BDUSS_BFESS=d1ZnVqSGVmTH43LXh5UDRSRDR3WTNoQWdLajY0dlNQMW1ZRllSSEhiUVZOVUJoRVFBQUFBJCQAAAAAAAAAAAEAAAC029PNwvrL8Mer0uZ0cnoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABWoGGEVqBhhTH; __yjs_duid=1_2f34bb903ff54977c104c3c8f5039cb41629028188136; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; HISTORY_SWITCH=1; BAIDUID=3299D08E603EF5171F898A6296DB47C3:FG=1; BAIDU_WISE_UID=wapp_1631591012256_912; APPGUIDE_10_0_2=1; BAIDUID_BFESS=3299D08E603EF5171F898A6296DB47C3:FG=1; RT="z=1&dm=baidu.com&si=utj8eu5533d&ss=l2rdvgwu&sl=2&tt=2at&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=34c&ul=bbh&hd=bcs"; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1649938460,1650448079,1650869079,1651919899; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1651920186; ab_sr=1.0.1_ZDI3OWNjNWQ0NmNlNzUxNzEzNTllMTYxYTc5MmU2MDg3ZWYyYjU2MTQzY2VmNDc5MjFlMzYzODdjYmFmMWVjYjNmODdkODM3MGViZjI2N2QyOTRkN2NkNjQ4NGE5MTY2OWRlODMzZTYxN2EyYmQzNTFlMTgxOGNmNzI3YTE2ZWMwMTcwMWI3YWM4MGI3NzQ4YWRmNjNjYzE4ZTFhMDFkMjFmNGIxNmRlYTQyNmFmYzdhZWM2NDQyMzhmYzdhMmRi`)
	req.Header.Set("Origin", "https://fanyi.baidu.com")
	req.Header.Set("Referer", "https://fanyi.baidu.com/?aldtype=16047")
	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.41 Safari/537.36 Edg/101.0.1210.32")
	req.Header.Set("X-Requested-With", "XMLHttpRequest")
	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"`)
	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)
	}
	if resp.StatusCode != 200 {
		log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))
	}
	var dictResponse DictResponseBD
	err = json.Unmarshal(bodyText, &dictResponse)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(word," ",dictResponse.DictResDataBD[0].V)
}

定义响应结构

能够发送请求后,我们还需要将返回的数据(json数据)解析为go中的结构体类型,以便取得我们需要的信息。

然鹅要自己手动敲代码定义这个繁杂的返回数据结构实在太麻烦啦,还容易出错。这里我使用直播课中提到的工具:oktools.net来完成这个过程,最后得到以下类型定义:

type AutoGenerated struct {
	Errno int `json:"errno"`
	Data []struct {
		K string `json:"k"`
		V string `json:"v"`
	} `json:"data"`
}

将其贴入源代码中,然后我们只要稍微调整一下上面的queryBD函数,最后也在main函数中调用queryBD,完成!

这样就完成了另一个翻译引擎的添加,效果如下:

image.png

针不戳!