开头
本文简单的完成了在线词典课后作业的两个要求:
- 增加了另一种翻译引擎的支持
- 在上一步的基础上实现并行请求两个翻译引擎来提高响应速度。
步骤
选择翻译引擎
这里我选择的是360翻译引擎。其他的翻译引擎我都没有做出很好的解析效果,要么就是有奇奇怪怪的限制。鉴于自身实力问题,就选择了360翻译引擎。
抓包
通过翻译一个hello,找到了对应的翻译请求。
生成代码
右键->复制->复制为cURL(bash)
打开Convert curl to Go (curlconverter.com)Convert curl to Go (curlconverter.com)进行代码生成
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("POST", "https://fanyi.so.com/index/search?eng=1&validate=&ignore_trans=0&query=hello", nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("authority", "fanyi.so.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("content-length", "0")
req.Header.Set("cookie", "__huid=11wNJd%2BocFVfC2mya6DFn8FR9YfXKFnBmnHDhVe65YE1s%3D; so_huid=11wNJd%2BocFVfC2mya6DFn8FR9YfXKFnBmnHDhVe65YE1s%3D; __gid=9114931.775463156.1631263986380.1640166943863.150; QiHooGUID=97C410ED2C00E0D3A4F6B11516982081.1690537261562; Q_UDID=bb97a741-52ee-a963-d0ca-ce922256998c; __guid=144965027.578392690600855000.1692957328745.652; count=1")
req.Header.Set("dnt", "1")
req.Header.Set("origin", "https://fanyi.so.com")
req.Header.Set("pro", "fanyi")
req.Header.Set("referer", "https://fanyi.so.com/")
req.Header.Set("sec-ch-ua", `"Chromium";v="116", "Not)A;Brand";v="24", "Microsoft Edge";v="116"`)
req.Header.Set("sec-ch-ua-mobile", "?1")
req.Header.Set("sec-ch-ua-platform", `"Android"`)
req.Header.Set("sec-fetch-dest", "empty")
req.Header.Set("sec-fetch-mode", "cors")
req.Header.Set("sec-fetch-site", "same-origin")
req.Header.Set("sec-gpc", "1")
req.Header.Set("user-agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36 Edg/116.0.1938.54")
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("%sn", bodyText)
}
生成请求
http.NewRequest("POST", "https://fanyi.so.com/index/search?eng=1&validate=&ignore_trans=0&query=hello", nil)
分析这段代码可以知道,翻译的单词是直接拼接在query后面的,所以可以采用拼接的方式把要翻译的单词拼接上去即可。
http.NewRequest("POST", fmt.Sprintf("https://fanyi.so.com/index/search?eng=1&validate=&ignore_trans=0&query=%s", word), nil)
这样请求就构造好了。
生成响应体response body
右键->复制值
打开工具网站
JSON转Golang Struct - 在线工具 - OKTools
转换为嵌套结构体:
type AutoGenerated struct {
Data struct {
Explain struct {
EnglishExplain []interface{} `json:"english_explain"`
Word string `json:"word"`
Caiyun struct {
Info struct {
Lbsynonym []interface{} `json:"lbsynonym"`
Antonym []interface{} `json:"antonym"`
WordExchange []interface{} `json:"word_exchange"`
} `json:"info"`
} `json:"caiyun"`
RelatedWords []interface{} `json:"related_words"`
WordLevel []string `json:"word_level"`
Exsentence []struct {
Title string `json:"Title"`
Body string `json:"Body"`
URL string `json:"Url"`
} `json:"exsentence"`
Phonetic struct {
NAMING_FAILED string `json:"英"`
} `json:"phonetic"`
WebTranslations []struct {
Translation string `json:"translation"`
Example string `json:"example"`
} `json:"web_translations"`
Translation []string `json:"translation"`
} `json:"explain"`
Fanyi string `json:"fanyi"`
SpeakURL struct {
SpeakURL string `json:"speak_url"`
TSpeakURL string `json:"tSpeak_url"`
WordSpeakURL string `json:"word_speak_url"`
WordType string `json:"word_type"`
} `json:"speak_url"`
Vendor string `json:"vendor"`
} `json:"data"`
Error int `json:"error"`
Msg string `json:"msg"`
}
我们需要请求的数据就在result.Data.Explain.Phonetic.NAMING_FAILED
和result.Data.Explain.Translation
里面。
完善代码
func queryBy360(word string) {
client := &http.Client{}
req, err := http.NewRequest("POST", fmt.Sprintf("https://fanyi.so.com/index/search?eng=1&validate=&ignore_trans=0&query=%s", word), nil)
if err != nil {
log.Fatal(err)
}
req.Header.Set("authority", "fanyi.so.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("content-length", "0")
req.Header.Set("cookie", "__huid=11wNJd%2BocFVfC2mya6DFn8FR9YfXKFnBmnHDhVe65YE1s%3D; so_huid=11wNJd%2BocFVfC2mya6DFn8FR9YfXKFnBmnHDhVe65YE1s%3D; __gid=9114931.775463156.1631263986380.1640166943863.150; __guid=65846823.4096180342024496000.1666005986099.6982; QiHooGUID=97C410ED2C00E0D3A4F6B11516982081.1690537261562; Q_UDID=bb97a741-52ee-a963-d0ca-ce922256998c; count=1")
req.Header.Set("dnt", "1")
req.Header.Set("origin", "https://fanyi.so.com")
req.Header.Set("pro", "fanyi")
req.Header.Set("referer", "https://fanyi.so.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", "?1")
req.Header.Set("sec-ch-ua-platform", `"Android"`)
req.Header.Set("sec-fetch-dest", "empty")
req.Header.Set("sec-fetch-mode", "cors")
req.Header.Set("sec-fetch-site", "same-origin")
req.Header.Set("sec-gpc", "1")
req.Header.Set("user-agent", "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Mobile Safari/537.36 Edg/115.0.1901.183")
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)
}
var result AutoGenerated
err = json.Unmarshal(bodyText, &result)
if err != nil {
log.Fatal(err)
}
fmt.Println("---360翻译---")
fmt.Println(word, "读音:", result.Data.Explain.Phonetic.NAMING_FAILED)
for _, item := range result.Data.Explain.Translation {
fmt.Println(item)
}
}
这里把360翻译引擎的请求封装成了一个函数。
这样就可以和原有的彩云翻译分开来,提高代码可读性。
然后在main函数里分别调用彩云翻译和360翻译就可以实现串行请求翻译单词了。
改造为并行请求的方式
其实改造为并行请求的方式也很容易,就是开启协程来分别执行这两个函数。同步方式采用sync.WaitGroup
来同步两个函数的调用过程,这样就可以做到两个函数并行请求翻译了。
具体代码框架就是:
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
`)
os.Exit(1)
}
word := os.Args[1]
var wg sync.WaitGroup
wg.Add(2)
go queryByCaiYun(word, &wg)
go queryBy360(word, &wg)
wg.Wait()
}
小结
其实这个课后作业本身就是比较容易的,按照课件的步骤也能逐步完成。难点就是并行请求的方式,这里我用的是sync.WaitGroup
,当然还有其他的同步方式,这里就不介绍了。