Go实现在线词典| 青训营笔记

3,064 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天

前言

本文是介绍用Go实现一个简易版的在线英语单词查询功能,该功能主要是调用第三方在线Api实现英语单词的翻译功能。

在本文中将使用到以下技术点:json解析、http请求、获取命令行参数、浏览器网络抓包。

本次采用翻译软件为彩云小译,找了其他网站发现都需要签名┭┮﹏┭┮。

网页抓包

打开翻译网页,在网页中间右键选择审查Inspect打开网页控制台。

输入要查询的单词,在控制台中选择web这个请求,如图,可以看到我们需要的信息在图中的标记5中。

image.png

代码生成

在请求单词查询接口,可以看到有很多参数以及请求头,要是一个一个的写有点麻烦,好在有网站可以根据请求在线生成代码。

首先在浏览器控制台中,选中接口右键选择Copy -> Copy as cURL如图。

image.png

复制出来的内容如下:

curl 'https://api.interpreter.caiyunai.com/v1/dict' \
  -H 'authority: api.interpreter.caiyunai.com' \
  -H 'accept: application/json, text/plain, */*' \
  -H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7' \
  -H 'app-name: xy' \
  -H 'cache-control: no-cache' \
  -H 'content-type: application/json;charset=UTF-8' \
  -H 'device-id: ' \
  -H 'origin: https://fanyi.caiyunapp.com' \
  -H 'os-type: web' \
  -H 'os-version: ' \
  -H 'pragma: no-cache' \
  -H 'referer: https://fanyi.caiyunapp.com/' \
  -H 'sec-ch-ua: "Google Chrome";v="105", "Not)A;Brand";v="8", "Chromium";v="105"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: cross-site' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36' \
  -H 'x-authorization: token:qgemv4jr1y38jyq6vhvi' \
  --data-raw '{"trans_type":"en2zh","source":"hello"}' \
  --compressed

打开代码生成网址,将复制的cURL粘贴进去就能得到请求对应的代码。

生成的代码如下:

image.png

&http.Client{}为创建一个httpclient,创建的时候可以指定一些参数,比如超时时间等,不指定就是不限制时间。

http.NewRequest创建一个http请求,参数为请求方式(GET/POST)、请求URL以及请求参数。

req.Header.Set设置请求头参数,有些参数不是必须的话可以删掉。

client.Do发起请求并返回内容以及错误信息。

resp为请求响应流,为了避免资源泄露,需要对流进行关闭。

defer一般用于资源的释放和异常的捕捉, defer语句会将其后面跟随的语句进行延迟处理,将会在程序进行最后的return之后再执行。如果一个函数中有多个defer的话,会从下往上执行,也就是最后被defer的语句,最先被执行。

JSON转化

因为请求得到的内容是个字符串,而且有很多不需要的信息,接下来就是要把得到的字符串转为JSON

需要定义一个结构体与请求后的response来对应起来用来接收数据,通过JSON反序列化到结构体里即可。

因为response返回的数据非常多而且复杂,自己书写起来很容易出错,所以我们可以通过在线生成代码工具来帮助我们生成代码。

JSON转结构体工具

打开这个网站,把浏览器response的内容复制到网站里点击转换-嵌套就能生成对应的结构体。

image.png

删除无用的字段,得到结果如下:

type DictResp struct {
    Dictionary struct {
        Prons struct {
            EnUs string `json:"en-us"`
            En   string `json:"en"`
        } `json:"prons"`
        Explanations []string `json:"explanations"`
    } `json:"dictionary"`
}

接下来是对请求响应体进行JSON反序列化:

var dictResp DictResp
err = json.Unmarshal(bodyText, &dictResp)
if err != nil {
        log.Fatal(err)
}
fmt.Println(word, "UK:", dictResp.Dictionary.Prons.En, "US:", dictResp.Dictionary.Prons.EnUs)
for _, item := range dictResp.Dictionary.Explanations {
        fmt.Println(item)
}

运行一下看下结果:

image.png

读取参数

接下来是从命令行读取参数,命令行参数可以通过os.Args来获取。

下面来看一个简单例子:

func main() {
    fmt.Println(os.Args)
}

通过go run main.go hello运行,可以获得两个参数,一个是临时执行路径,另一个是自己输入的参数hello,如下:

[/var/folders/tk/gcvj01wx7m92km/T/go-build446/b001/exe/main hello]

获取参数代码如下:

func main() {
    // 判断参数的数量要为2个,否则提示错误
    if len(os.Args) != 2 {
        fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello`)
        os.Exit(1)
    }
    word := os.Args[1]
    query(word)
}

完整代码

好了,到目前为止一个查单词的软件就实现了,完整的代码就不贴出来了,已经放到码上掘金了。

引用

字节内部课——Go 语言的实战案例