创建时间: May 16, 2022 11:30 AM
这是我参与「第三届青训营 -后端场」笔记创作活动的的第二篇笔记。
本文是课程『「5.6」Golang 语言基础』的回忆记录,课上的实验让我印象深刻,写作时间是「5.16」正好是课后的第十天。
🤖 Lab2 爬虫-命令行词典
课上:
由讲师从零实现调用彩云翻译 API 完成一个简单的命令行词典。
课后 Lab:
拓展 API,调用其他翻译 API 实现翻译功能。
-
为了兼容多个 API,设计 Translator 接口和 Result 结构。
- do(string)
- Result 用来规定好输出样式
曾经为了获得一个不能编辑的表格数据使用 Golang 爬取过xx表格的数据 ,课上看这部分的操作的时候感觉非常亲切。
// Result 英译中
type Result struct {
// 音标
En, Am string
Means []string
}
func (r Result) String() string {
var wordMean string
for _, mean := range r.Means {
wordMean += mean
}
return fmt.Sprintf("英 %s\n美 %s\n\t%v", r.En, r.Am, r.Means)
}
type Translator interface {
Do(word string) Result
}
由于之前使用过百度 API,注册过百度开发者,所以直接选择了百度通用翻译 API。
阅读文档后,很快就理解了如何完成 API 调用。但 API 上线比较久了(用的 POST/URL),编码过程不是特别顺利。
很快,发觉不对劲儿。
因为百度通用 API 翻译只有文本的翻译结果,结果比较单一。
但咱做的是命令行词典,词典没有多种词意以及单词音标是不算合格的。
接着便开始了长达数小时到折腾。
-
进入网页版本百度翻译,使用 Chrome-NetWork 工具分析网页请求。
-
提取出来关键字段
tokensignquery
-
字段分析
- query 为输入的查询目标
- token 为客户端鉴权字段
- 而 sign 则完全未知
932273.711296看似一个浮点数,我在切换多次 query 后发现这个参数可能与输入 query 绝对相关。除此以外还是一无所知。
-
寻找问题解决方案
在网上浏览了非常多帖子后,找到一种可行的解决思路。
- 首先 sign 和 query 参数相关这点是成立的。
- 其次,sign 参数顾名思义;签名,是用作服务器端鉴权用的标识。
- 那么这个 sign 是如何生成以及如何获得的,为了复现签名,我从 JS 代码中将它找了出来,做了一些简单的调试和修改以后,我确信是这段函数。
不过这中间使用的方式是 Python 运行的 JS 代码实现确认的,随即开始寻找有关 golang 调用 JS 相关的资料。最终找到了
"github.com/robertkrimen/otto"由于目录结构比较复杂,没有在这个简单需求中使用文件 io(因为最后打包以后处理 js 文件会很麻烦),直接将 js 字符串作为 consts 存起来。
-
最终调用代码
package signer import ( "github.com/robertkrimen/otto" "log" "runtime" ) var ( p = "/" ) func init() { if runtime.GOOS == "windows" { p = "\" } } // Sign 返回百度的校验签名 func Sign(word string) string { js := getJS() vm := otto.New() _, err := vm.Run(js) if err != nil { log.Fatalln("run err!", err.Error()) } res, err := vm.Call("e", nil, word) if err != nil { log.Fatalln("call err!", err.Error()) } return res.String() } // 加载 js 脚本 func getJS() string { // pwd, _ := os.Getwd() // jsFile := "baiduv2.js" // // bytes, err := ioutil.ReadFile(pwd + p + jsFile) // if err != nil { // log.Fatalln(err) // } // return string(bytes) return jsTOSign }
测试:
=== RUN TestBaiDuAPIV2 英 həˈləʊ 美 həˈloʊ
[int./n.你好, (用于问候、接电话或引起注意)喂, (表示惊讶或认为 别人说了蠢话或没有注意听)嘿; ]
--- PASS: TestBaiDuAPIV2 (0.91s) PASS
-