本篇文章主要梳理总结了如何使用go语言,并且在一些代码生成工具的帮助下实现命令行在线词典的功能,以下是具体实践过程和走过的一些弯路(调错过程)
(一)抓包
(1)打开“彩云翻译网页”:[
(2)右键->检查
(3)在左边的英文区域输入英文->点击“翻译按钮”
(4)点击开发者工具中的“网络”->从下往上寻找请求方法为POST的dict文件
(5)点击“负载”进行查看(点击“翻译”时触发了POST请求,其参数是json,json里面包括2个字段source:要翻译的单词;trans_type:翻译方式如英译中)
(二)主体代码生成
(1)右键请求->复制->复制为cURL(bash)
(2)打开“主体代码生成网址”:[
(3)将复制的内容粘贴进去,选择go语言,自动生成代码
报错:.\main.go:49:19: undefined: io.ReadAll
原因:go的版本和io.ReadAll不匹配
修改:将导入的包"io"改为"io/ioutil" 将bodyText, err := io.ReadAll(resp.Body)改为bodyText,err := ioutil.ReadAll(resp.Body)
直到修改到可以打印出一大串返回的json请求如下即可:
(三)生成request body
(1)定义请求结构体
(2)new一个结构体变量,初始化字段
(3)序列化request变成一个数组
报错:undefined: json及undefined: bytes
修改:导入包"encoding/json"及"bytes"
(4)转化为data
报错:data redeclared in this block
原因:data已经定义过
修改:删除导入的包"strings"及var data =strings.NewReader(`{"trans_type":"en2zh","source":"network"}`)
直到终端可以输出如下信息:
(5)结构体代码生成
打开“结构体生成网址”:[
打开“彩云小译”界面,复制“响应”的内容到上述页面左边的JSON框中
点击“转换-嵌套”得到go语言结构体
将得到的结构体粘贴至代码中
(6)删除打印语句:fmt.Printf("%s\n", bodyText)
(7)增加报错检验:
(8)增加返回结构体变量:
(9)更改打印语句:
(10)修改函数主体:
(11)写一个新的main函数:
报错:cannot use os.Stderr (type *os.File) as type string in argument to fmt.Printf
原因:os.Stderr 是一个指向标准错误输出的文件对象的指针,无法直接转换为字符串类型
修改:将Printf改为Fprintf
(12)导入包查漏补缺
运行程序
命令1:go run .\main.go
报错1:usage:simpleDict WORD example:simpleDict helloexit status 1
原因:程序在没有提供命令行参数的情况下执行,或者提供的命令行参数不符合期望的格式
命令2:go run .\main.go hello
(13)可以正常运行,但是如果我们输入go run .\main.go 你好,可以发现程序并不报错,但是也无法正常给出翻译。因为我们选择的翻译类型为英译中,所以需要增加判断输入单词是否为英文单词的方法:
以上步骤都完成后,就可以实现【在线词典onlineDictionary】的功能啦!
下面是完整代码:
// 查询一个单词,输出其音标、注释package mainimport ( "fmt" "io/ioutil" "log" "net/http" "encoding/json" "bytes" "strings" "os")//定义请求结构体type DictRequest struct { TransType string `json:"trans_type"` Source string `json:"source"` UserID string `json:"user_id"`}//定义返回结构体type DictResponse struct { Rc int `json:"rc"` Wiki struct { } `json:"wiki"` Dictionary struct { Prons struct { EnUs string `json:"en-us"` En string `json:"en"` } `json:"prons"` Explanations []string `json:"explanations"` Synonym []string `json:"synonym"` Antonym []string `json:"antonym"` WqxExample [][]string `json:"wqx_example"` Entry string `json:"entry"` Type string `json:"type"` Related []interface{} `json:"related"` Source string `json:"source"` } `json:"dictionary"`}func query(word string) { client := &http.Client{} //申请结构体变量 request := DictRequest{TransType:"en2zh",Source:word} buf,err := json.Marshal(request) if err != nil { log.Fatal(err) } var data = bytes.NewReader(buf) //创建请求 req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data) if err != nil { log.Fatal(err) } //设置请求头 req.Header.Set("authority", "api.interpreter.caiyunai.com") req.Header.Set("accept", "application/json, text/plain, */*") 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("app-name", "xy") req.Header.Set("content-type", "application/json;charset=UTF-8") req.Header.Set("device-id", "43253aa06c2732303c265c61e036e33b") req.Header.Set("origin", "https://fanyi.caiyunapp.com") req.Header.Set("os-type", "web") req.Header.Set("os-version", "") req.Header.Set("referer", "https://fanyi.caiyunapp.com/") req.Header.Set("sec-ch-ua", `"Chromium";v="112", "Microsoft Edge";v="112", "Not:A-Brand";v="99"`) req.Header.Set("sec-ch-ua-mobile", "?0") req.Header.Set("sec-ch-ua-platform", `"Windows"`) req.Header.Set("sec-fetch-dest", "empty") req.Header.Set("sec-fetch-mode", "cors") req.Header.Set("sec-fetch-site", "cross-site") req.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.46") req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi") //发起请求 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 DictResponse err = json.Unmarshal(bodyText, &dictResponse) if err != nil { log.Fatal(err) } //打印结果 fmt.Println(word,"UK:",dictResponse.Dictionary.Prons.En,"US:",dictResponse.Dictionary.Prons.EnUs) for _,item := range dictResponse.Dictionary.Explanations { fmt.Println(item) }}//判断输入是否为英文单词func ContainsEnglish(str string) bool { dictionary := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" for _, v := range str { if strings.Contains(dictionary, string(v)) { return true } } return false }func main() { if len(os.Args) != 2 { fmt.Fprintf(os.Stderr,"usage:simpleDict WORD example:simpleDict hello") os.Exit(1) } word := os.Args[1] if ContainsEnglish(word) { query(word) return } fmt.Println("Please input an English word.") return}