涟水网站建设,行政还要负责网站建设新媒体吗,淘宝网页版登录,毕业生就业推荐表模板网站开发文章目录 程序介绍抓包代码生成生成request body解析respond body完整代码 字节青训营基础班学习记录。 程序介绍
在运行程序的时候以命令行的形式输入要查询的单词#xff0c;然后程序返回单词的音标、释义等信息。
示例如下#xff1a; 抓包
我们选择与网站https://fany… 文章目录 程序介绍抓包代码生成生成request body解析respond body完整代码 字节青训营基础班学习记录。 程序介绍
在运行程序的时候以命令行的形式输入要查询的单词然后程序返回单词的音标、释义等信息。
示例如下 抓包
我们选择与网站https://fanyi.caiyunapp.com/建立连接。
首先我们打开网站Windows下直接按f12进入开发者工具
然后输入一个单词并点击翻译按钮在网络tag部分找到请求方法为POST的dict 这里有部分请求表头是我们后续需要在代码中添加设置的。
然后去负载tag可以看到这次请求的source也就是要翻译的单词
也能看到要翻译的类型这里是en2zh也就是英文到中文 这个请求是JSON类型的我们后续存储会用结构体去存储这个数据所以传请求信息的时候要先对结构体进行序列化。
预览tag就是这次请求返回的信息 返回信息也是JSON为了方便打印我们后续也会将返回得到的JSON反序列化存放到对应的结构体变量中。 代码生成
我们要实现一个在线词典所以我们运行程序后需要程序发送对应的请求。
上面也看了部分代码会特别复杂
所以这里用到一个代码生成工具Convert curl to Go (curlconverter.com)帮我们完成部分代码工作。
鼠标指向刚刚的请求tag - 右键点击 - 选择复制 - 选择复制为cURL(cmd) 然后将我们复制后的信息粘贴到网站的curl command下面的代码框内得到生成的go语言代码
此时可能会出现这样的报错信息 这是因为我们复制的command的每一行是以^结尾的我们需要手动改成\这样就没问题了 然后把代码复制到我们的代码编辑器中就OK了。
下面添加了部分注释帮助理解代码
package mainimport (fmtiolognet/httpstrings
)func main() {//创建http客户端client : http.Client{}//data是请求参数也就是翻译类型和要翻译的单词//由于创建请求信息的时候请求参数是io.Reader流类型//所以需要用strings.NewReader()将JSON转化为io.Reader类型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(authority, api.interpreter.caiyunai.com)req.Header.Set(accept, application/json, text/plain, */*)req.Header.Set(accept-language, zh-CN,zh;q0.9,en;q0.8,en-GB;q0.7,en-US;q0.6)req.Header.Set(app-name, xy)req.Header.Set(content-type, application/json;charsetUTF-8)req.Header.Set(device-id, dde0d0432ca66c7fe6175b7bf940b7f2)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, \Not/A)Brand\;v\99\, \Microsoft Edge\;v\115\, \Chromium\;v\115\)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/115.0.0.0 Safari/537.36 Edg/115.0.1901.183)req.Header.Set(x-authorization, token:qgemv4jr1y38jyq6vhvi)//发送请求resp, err : client.Do(req)if err ! nil {log.Fatal(err)}//成功拿到请求后关闭请求如果不关闭请求可能会造成资源泄漏//defer关键字会在函数结束时调用resp.Body.Close()方法defer resp.Body.Close()//读取请求返回的数据//这里使用ioutil.ReadAll()方法读取,返回的是[]byte类型的数据bodyText, err : io.ReadAll(resp.Body)if err ! nil {log.Fatal(err)}//打印返回的信息fmt.Printf(%s\n, bodyText)
}生成request body
上面的代码已经能够成功发送请求并接收序列化的返回信息。
但是现在有一个缺点请求信息是一个写死的JSON转成的流
而我们需要从命令行自己输入单词而单词又是请求信息的一部分
所以我们需要定义一个能存放请求信息的结构体结构体核心字段为trans_type和source 我们是要从命令行中获取要翻译的单词
所以可以从命令行参数中读取单词并用其初始化我们要创建的请求信息结构体变量
trans_type字段是我们要翻译的类型需要初始化为en2zh。
这样就可以用结构体来表示我们的请求信息。
但是发送请求时请求信息需要转为io.Reader类型
所以我们还需要先将结构体序列化
然后使用func bytes.NewReader(b []byte) *bytes.Reader将序列化后的JSON转成io.Reader类型
之后就可以创建请求。
// DictRequest 请求参数
// 因为需要序列化所以结构体每个字段的首字母都要大写
type DictRequest struct {TransType string json:trans_typeSource string json:sourceUserID string json:user_id
}//读取命令行参数也就是我们要翻译的单词
word : os.Args[1]
//用我们读到的单词初始化请求信息结构体
request : DictRequest{TransType: en2zh, Source: word} //将结构体序列化为json字符串
buf, err : json.Marshal(request)
if err ! nil {log.Fatal(err)
}//将json字符串转换为io.Reader类型,因为NewRequest()方法需要传入io.Reader类型的参数
var data bytes.NewReader(buf)
req, err : http.NewRequest(POST, https://api.interpreter.caiyunai.com/v1/dict, data)
if err ! nil {log.Fatal(err)
}解析respond body
此时我们的程序已经可以翻译单个从命令行输入的单词
并接收全部的返回信息 请求返回的信息是JSON序列
而我们需要把这些信息反序列到一个结构体中
然后打印出结构体中我们想要的部分信息。
所以我们还需要定义一个结构体用以接收返回信息反序列化的结果。
而返回信息中有太多字段了一一去定义这些字段不仅低效并且容易出错
所以这里使用到了另一款工具JSON转Golang Struct - 在线工具 - OKTools。
首先还是打开开发者工具找到POST请求点击预览 然后单击鼠标右键选择复制值。
随后进入上面那个网站将复制的内容 粘贴在左边一栏然后点击转换嵌套 这样就得到了对应的接收返回信息的结构体类型。
现在就可以把这段代码改个结构体的名添加到我们的代码中
type DictResponse struct {Rc int json:rcWiki struct {} json:wikiDictionary struct {Prons struct {EnUs string json:en-usEn string json:en} json:pronsExplanations []string json:explanationsSynonym []string json:synonymAntonym []string json:antonymWqxExample [][]string json:wqx_exampleEntry string json:entryType string json:typeRelated []interface{} json:relatedSource string json:source} json:dictionary
}此前代码生成部分接收的返回数据是以[]byte类型在bodyTest中存储的
此时我们就可以将其反序列化为结构体对象
然后选择性地打印我们所需要的字段
//将返回的数据反序列化解析到结构体中
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)
}完整代码
此时将上面的代码整合一下就得到了完整的代码
这里我们对代码进行了部分封装
从main函数中读取待翻译的单词
然后将发送请求到接受返回信息并打印这一部分封装成query函数
将待翻译的单词作为参数
如果有多个待翻译的单词可以在main函数中一个个读取并调用query函数
package mainimport (bytesencoding/jsonfmtio/ioutillognet/httpos
)// DictRequest 请求参数
type DictRequest struct {TransType string json:trans_typeSource string json:sourceUserID string json:user_id
}// DictResponse 返回参数
type DictResponse struct {Rc int json:rcWiki struct {} json:wikiDictionary struct {Prons struct {EnUs string json:en-usEn string json:en} json:pronsExplanations []string json:explanationsSynonym []string json:synonymAntonym []string json:antonymWqxExample [][]string json:wqx_exampleEntry string json:entryType string json:typeRelated []interface{} json:relatedSource string json:source} json:dictionary
}func query(word string) {//创建http客户端client : http.Client{}//创建请求//POST请求需要传入请求方法请求地址请求参数//这里的地址是我自己搭建的一个测试接口大家可以自行搭建或者使用其他接口//data是请求参数需要使用strings.NewReader()方法转换为io.Reader类型request : DictRequest{TransType: en2zh, Source: word}//将结构体序列化为json字符串buf, err : json.Marshal(request)if err ! nil {log.Fatal(err)}//将json字符串转换为io.Reader类型,因为NewRequest()方法需要传入io.Reader类型的参数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(Connection, keep-alive)req.Header.Set(DNT, 1)req.Header.Set(os-version, )req.Header.Set(sec-ch-ua-mobile, ?0)req.Header.Set(User-Agent, Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36)req.Header.Set(app-name, xy)req.Header.Set(Content-Type, application/json;charsetUTF-8)req.Header.Set(Accept, application/json, text/plain, */*)req.Header.Set(device-id, )req.Header.Set(os-type, web)req.Header.Set(X-Authorization, token:qgemv4jr1y38jyq6vhvi)req.Header.Set(Origin, https://fanyi.caiyunapp.com)req.Header.Set(Sec-Fetch-Site, cross-site)req.Header.Set(Sec-Fetch-Mode, cors)req.Header.Set(Sec-Fetch-Dest, empty)req.Header.Set(Referer, https://fanyi.caiyunapp.com/)req.Header.Set(Accept-Language, zh-CN,zh;q0.9)req.Header.Set(Cookie, _ym_uid16456948721020430059; _ym_d1645694872)//发送请求resp, err : client.Do(req)if err ! nil {log.Fatal(err)}//成功拿到请求后关闭请求//这里需要注意如果不关闭请求会造成内存泄漏//defer关键字会在函数结束时调用resp.Body.Close()方法defer resp.Body.Close()//读取请求返回的数据//这里使用ioutil.ReadAll()方法读取,返回的是[]byte类型的数据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 DictResponseerr 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 os.Args nil || len(os.Args) 2 {fmt.Fprintf(os.Stderr, usage: simpleDict WORDexample: simpleDict hello)os.Exit(1)}for _, word : range os.Args[1:] {query(word)fmt.Println() //每打印完一个单词的信息用空行隔开}
}
至此就完成了一个 简单的命令行在线词典。