记录一下在字节青训营中学到的内容 这里用到的三个网站是彩云小译,在线生成代码,json转换器
首先我们想要做到在翻译网站中获取到请求和响应
拿到这些数据我们要学会怎么去查看这个页面的信息
json格式的代码
查看网页信息
右键选中检查
选中上方栏目的Network
选中刚刚输入good所生成的dict
检查一下其Headers是否是包含Post请求
这里的Payload中的en2zh就是英文转换成中文的意思
选中其中的Preview里面可以看到具体的翻译
获取网页的cURL
这里我们右键copy一下它的cURL,等会会用到。
这里的cURL是一个命令行工具,用于在服务器中传输数据用的
具体感兴趣的同学可以参考这个文章cURL是什么
代码转换
然后打开第二个网站
将刚刚cope的cURL复制到这个框内
底下就会生成go语言的代码将它复制粘贴到idea就好了
package main
import (
"fmt"
"io"
"log"
"net/http"
"strings"
)
func main() {
// http.Client创建了一个http客户端实例,并把值赋给client变量用来接受和传送http响应和请求
client := &http.Client{}
// 这里的data用了strings.NewReader的方法将字符串转换成流,可以节省内存
var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`)
// 创建请求
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
log.Fatal(err)
}
// 设置请求头
req.Header.Set("accept", "application/json, text/plain, */*")
req.Header.Set("accept-language", "zh")
req.Header.Set("app-name", "xiaoyi")
req.Header.Set("authorization", "Bearer")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "67e26c3ec5a2bd9d1f1a8472eed9443c")
req.Header.Set("origin", "http://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("priority", "u=1, i")
req.Header.Set("referer", "http://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Linux"`)
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 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
//发起请求
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// 这个defer会在函数结束之后从下往上触发释放这个流
// 读取响应
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}
这里我已经在代码中做出详细的注释了就不一一解析了
我们每次发送请求的时候应该是传递值而不是直接的json序列,所以进入下一步
传参的http代码
我们需要定义一个结构体用作传参
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserId string `json:"user_id"`
}
实际上我们在上一段代码中并没有用到UserId,这个参数是可以省略的
以下是完整的代码
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserId string `json:"user_id"`
}
func main() {
// http.Client创建了一个http客户端实例,并把值赋给client变量用来接受和传送http响应和请求
client := &http.Client{}
request := DictRequest{TransType: "en2zh", Source: "good"}
// 这里将结构体数据转换成json格式用来传输数据
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("accept", "application/json, text/plain, */*")
req.Header.Set("accept-language", "zh")
req.Header.Set("app-name", "xiaoyi")
req.Header.Set("authorization", "Bearer")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "67e26c3ec5a2bd9d1f1a8472eed9443c")
req.Header.Set("origin", "http://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("priority", "u=1, i")
req.Header.Set("referer", "http://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Linux"`)
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 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
//发起请求
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// 这个defer会在函数结束之后从下往上触发释放这个流
// 读取响应
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}
注释写的很明确了,就不赘述了
运行结果
{"rc":0,"wiki":{},"dictionary":{"prons":{"en-us":"[g\u028ad]","en":"[gud]"},"explanations":["a.\u597d\u7684;\u5584\u826f\u7684;\u5feb\u4e50\u7684;\u771f\u6b63\u7684;\u5bbd\u5927\u7684;\u6709\u76ca\u7684;\u8001\u7ec3\u7684;\u5e78\u798f\u7684;\u5fe0\u5b9e\u7684;\u4f18\u79c0\u7684;\u5b8c\u6574\u7684;\u5f7b\u5e95\u7684;\u4e30\u5bcc\u7684","n.\u5229\u76ca;\u597d\u5904;\u5584\u826f;\u597d\u4eba","ad.=well"],"synonym":["excellent","fine","nice","splendid","proper"],"antonym":["bad","wrong","evil","harmful","poor"],"wqx_example":[["to the good","\u6709\u5229,\u6709\u597d\u5904"],["good, bad and indifferent","\u597d\u7684,\u574f\u7684\u548c\u4e00\u822c\u7684"],["good innings","\u957f\u5bff"],["good and ...","\u5f88,\u9887;\u5b8c\u5168,\u5f7b\u5e95"],["do somebody's heart good","\u5bf9\u67d0\u4eba\u7684\u5fc3\u810f\u6709\u76ca,\u4f7f\u67d0\u4eba\u611f\u5230\u6109\u5feb"],["do somebody good","\u5bf9\u67d0\u4eba\u6709\u76ca"],["be good for","\u5bf9\u2026\u6709\u6548,\u9002\u5408,\u80dc\u4efb"],["be good at","\u5728\u2026\u65b9\u9762(\u5b66\u5f97,\u505a\u5f97)\u597d;\u5584\u4e8e"],["as good as one's word","\u4fe1\u5b88\u8bfa\u8a00,\u503c\u5f97\u4fe1\u8d56"],["as good as","\u5b9e\u9645\u4e0a,\u51e0\u4e4e\u7b49\u4e8e"],["all well and good","\u4e5f\u597d,\u8fd8\u597d,\u5f88\u4e0d\u9519"],["a good","\u76f8\u5f53,\u8db3\u8db3"],["He is good at figures . ","\u4ed6\u5584\u4e8e\u8ba1\u7b97\u3002"]],"entry":"good","type":"word","related":[],"source":"wenquxing"}}
接下来要做的就是解析这段bodyText
解析http响应
我们获取到的http响应是一个json字典,可以通过像python一样的字典索引的方法去做,不过最好的方法是写一个结构体来承载这个数据。 直接根据响应的response来写结构体容易写漏,我们这里可以直接copy一下。
打开第三个网站json转换器
将刚刚copy的内容粘贴进去
选中转换-嵌套
将这个结构体复制到代码里面就好了
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
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"`
}
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserId string `json:"user_id"`
}
func main() {
// http.Client创建了一个http客户端实例,并把值赋给client变量用来接受和传送http响应和请求
client := &http.Client{}
request := DictRequest{TransType: "en2zh", Source: "good"}
// 这里将结构体数据转换成json格式用来传输数据
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("accept", "application/json, text/plain, */*")
req.Header.Set("accept-language", "zh")
req.Header.Set("app-name", "xiaoyi")
req.Header.Set("authorization", "Bearer")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "67e26c3ec5a2bd9d1f1a8472eed9443c")
req.Header.Set("origin", "http://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("priority", "u=1, i")
req.Header.Set("referer", "http://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Linux"`)
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 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
//发起请求
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// 这个defer会在函数结束之后从下往上触发释放这个流
// 读取响应
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
var dictResponse DictResponse
// 这里将json反序列化传入到dictResponse中
err = json.Unmarshal(bodyText, &dictResponse)
if err != nil {
log.Fatal(err)
}
// 在这里的%#v会用最详细的方式来打印结构体
fmt.Printf("%#v\n", dictResponse)
}
打印出来的结果是这样的
main.DictResponse{Rc:0, Wiki:struct {}{}, 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\"" }{Prons:struct { EnUs string "json:\"en-us\""; En string "json:\"en\"" }{EnUs:"[gʊd]", En:"[gud]"}, Explanations:[]string{"a.好的;善良的;快乐的;真正的;宽大的;有益的;老练的;幸福的;忠实的;优秀的;完整的;彻底"}, Synonym:[]string{"excellent", "fine", "nice", "splendid", "proper"}, Antonym:[]string{"bad", "wrong", "evil", "harmful", "poor"}, WqxExample:[][]string{[]string{"to the good", "有利,有好处"}, []string{"good, bad andfferent", "好的,坏的和一般的"}, []string{"good innings", "长寿"}, []string{"good and ...", "很,颇;完全,彻底"}, []string{"do somebody's heart good", "对某人的心脏有益,使某人感到愉快"}, []string{"do somebody good", "对某人有效,适合,胜任"}, []string{"be good at", "在…方面(学得,做得)好;善于"}, []string{"as good as one's word", "信守诺言,值得信赖"}, []string{"as good as", "实际上,几乎等于"}, []string{"all well and good", "也好,还好,很不错"}g{"He is good at figures . ", "他善于计算。"}}, Entry:"good", Type:"word", Related:[]interface {}{}, Source:"wenquxing"}}
最后格式化一下输出
我们看到输出这么一长串数据并不是我们都需要的,我们可以格式化一下输出 这里我们输出的格式是单词,英式发音,美式发音,和中文意思i
fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
for _, item := range dictResponse.Dictionary.Explanations {
fmt.Println(item)
}
完善代码
加一段卫式编程 刚刚的代码中获取response的时候,如果获取到数据就会进行打印,如果不是200,数据只是为空而已,所以我们这里加一段判断是否是正确响应
if resp.StatusCode != 200 {
log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))
}
以下是完整代码
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
)
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"`
}
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserId string `json:"user_id"`
}
func query(word string) {
// http.Client创建了一个http客户端实例,并把值赋给client变量用来接受和传送http响应和请求
client := &http.Client{}
request := DictRequest{TransType: "en2zh", Source: word}
// 这里将结构体数据转换成json格式用来传输数据
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("accept", "application/json, text/plain, */*")
req.Header.Set("accept-language", "zh")
req.Header.Set("app-name", "xiaoyi")
req.Header.Set("authorization", "Bearer")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "67e26c3ec5a2bd9d1f1a8472eed9443c")
req.Header.Set("origin", "http://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("priority", "u=1, i")
req.Header.Set("referer", "http://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Chromium";v="128", "Not;A=Brand";v="24", "Google Chrome";v="128"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Linux"`)
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 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
//发起请求
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// 这个defer会在函数结束之后从下往上触发释放这个流
// 读取响应
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 dictResponse DictResponse
// 这里将json反序列化传入到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 main() {
if len(os.Args) < 2 {
fmt.Fprintf(os.Stderr, `usage:simpleDict WORD example:simpleDict hello`)
os.Exit(1)
}
word := os.Args[1]
query(word)
}
这里具体解释一下main()这里的代码,这里的os.Args是字符串切片,包含了命令行传入的参数
- 其中os.Arag[0]是程序的名称
- os.Args[1]是第一个参数
如果长度小于2即代表没有传入参数 返回状态码数1表示异常退出 然后赋值给word最后调用刚刚写的方法执行
下面是运行结果
$ go run main.go love
love UK: [lʌv] US: [lʌv]
n.爱;喜爱;爱情
[俗]漂亮的东西;嗜好;(网球)零分;性欲
vt.求爱;热爱;茂盛;需要
vi.喜爱;热爱;出于怜悯;不奢求报酬