在线词典
内容
通过使用第三方API获取数据,达到读取用户输入的数据并返回其音标、汉译的目的。
获取翻译步骤:
- 打开彩云翻译官网
- 输入需要查询的单词
- 点击翻译按钮
- 等待页面返回结果
使用第三方API获取数据步骤:
-
首先,需要打开浏览器的开发者工具。可以通过
F12
或右键网页页面后点击检查选项来打开它。 -
在开发者工具中,找到网络标签页或者Network并打开它。
-
应当在原文文本框输入一个已知存在的单词,并在点击翻译后注意观察网络标签页下记录的网络请求。
-
通过筛选网络请求记录,很容易找到
dict
请求。其中,Payload
下的Preview
便是需要注意的内容。 -
右击
dict
选择Copy中的Copy as cURL。 -
并把复制的内容粘贴到解析网站解析。
解析内容大致为:
package main import ( "fmt" "io" "log" "net/http" "strings" ) func main() { client := &http.Client{} var data = strings.NewReader(`{"trans_type":"en2zh","source":"Strong"}`) 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") req.Header.Set("app-name", "xy") req.Header.Set("cache-control", "no-cache") req.Header.Set("content-type", "application/json;charset=UTF-8") req.Header.Set("device-id", "35d05b0ae7523f22cde64f11f9204282") req.Header.Set("origin", "https://fanyi.caiyunapp.com") req.Header.Set("os-type", "web") req.Header.Set("os-version", "") req.Header.Set("pragma", "no-cache") req.Header.Set("referer", "https://fanyi.caiyunapp.com/") req.Header.Set("sec-ch-ua", `"Chromium";v="112", "Google Chrome";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") req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi") resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() bodyText, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err) } fmt.Printf("%s\n", bodyText) }
- 第12行我们创建了一个 HTTP Client,创建的时候可以指定很多参数,包括请求的超时时间,是否使用Cookie 等。
- 在第14行,我们构造了一个 HTTP 请求,这是一个POST请求,然后会用到
http.NewRequest
,第一个参数是 HTTP请求方法POST
, 第二个参数是URL, 最后一个参数是RequestBody。由于RequestBody可能很大,为了支持流式发送,它是一个只读流。我们用了strings.NewReader
来把字符串转换成一个流,这样我们就成功构造了一个 HTTP Request。 - 18~35行,我们对这个 HTTP Request设置了一些Request Header。 接下来我们把我们调用
client.Do
,就能得到Response。
-
复制需要的解析内容。
生成根据参数变化的RequestBody
此时我们需要使用到json序列化和反序列化软件包,并编写对应的结构体。
type DictRequest struct {
TransType string `json:"trans_type"` // 请求类型
Source string `json:"source"` // 要查询的单词
UserID string `json:"user_id"` // 用户ID
}
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)
}
解析ResponseBody
- 复制上述图片框起的数据
- 借助工具:OKTools的
JSON转Go
功能,可以很便捷的拿到反序列化所需的结构体 - 使用转换-嵌套
type DictResponse struct {
Rc int `json:"rc"`
Wiki struct {
KnownInLaguages int `json:"known_in_laguages"`
Description struct {
Source string `json:"source"`
Target interface{} `json:"target"`
} `json:"description"`
ID string `json:"id"`
Item struct {
Source string `json:"source"`
Target string `json:"target"`
} `json:"item"`
ImageURL string `json:"image_url"`
IsSubject string `json:"is_subject"`
Sitelink string `json:"sitelink"`
} `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"`
}
剩下的步骤:
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)
}
nc 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)
- 发送HTTP请求并获取响应
- 读取响应体内容
- 检查响应状态码
- 创建一个词典响应对象
- 解析JSON响应数据到对象中
- 打印单词的英式和美式发音
- 遍历解释列表并打印
- 关闭响应体
- 检查命令行参数数量
- 获取要查询的单词
- 调用查询函数进行查询
运行程序:
go run main.go Strong
输出
完整代码
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
type DictRequest struct {
TransType string `json:"trans_type"` // 请求类型
Source string `json:"source"` // 要查询的单词
UserID string `json:"user_id"` // 用户ID
}
type DictResponse struct {
Rc int `json:"rc"` // 响应状态码
Wiki struct {
KnownInLaguages int `json:"known_in_laguages"` // 已知语言数量
Description struct {
Source string `json:"source"` // 描述来源
Target interface{} `json:"target"` // 描述目标
} `json:"description"` // 描述信息
ID string `json:"id"` // ID
Item struct {
Source string `json:"source"` // 来源
Target string `json:"target"` // 目标
} `json:"item"` // 项目信息
ImageURL string `json:"image_url"` // 图片URL
IsSubject string `json:"is_subject"` // 是否是主题
Sitelink string `json:"sitelink"` // 网站链接
} `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{} // 创建一个HTTP客户端
request := DictRequest{TransType: "en2zh", Source: word} // 创建一个词典请求对象,指定请求类型和要查询的单词
buf, err := json.Marshal(request) // 将请求对象转换为JSON格式的字节流
if err != nil {
log.Fatal(err)
}
var data = bytes.NewReader(buf) // 创建一个字节流读取器,用于读取JSON数据
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data) // 创建一个POST请求,指定URL和请求体
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")
req.Header.Set("app-name", "xy")
req.Header.Set("cache-control", "no-cache")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "35d05b0ae7523f22cde64f11f9204282")
req.Header.Set("origin", "https://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("pragma", "no-cache")
req.Header.Set("referer", "https://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Chromium";v="112", "Google Chrome";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")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
resp, err := client.Do(req) // 发送HTTP请求并获取响应
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) // 解析JSON响应数据到对象中
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) // 调用查询函数进行查询
}