快捷搜索:  汽车  科技

谷歌翻译api如何收费(免费试用谷歌的翻译接口)

谷歌翻译api如何收费(免费试用谷歌的翻译接口)实例池并发这里可以做优化,一个puppeteer同一时间只能处理一个翻译请求,如果做个实例池,维护多个puppeteer实例,这样就可以提升翻译接口的并发能力了。至此,我们的主角无头浏览器puppeteer就要登场了,puppeteer一个node类库,提供了简洁的API,可以让使用者操作chrome浏览器,基本可以完全模拟人的操作,比如打开页面、输入网址、等待页面指定内容加载、点击按钮、甚至滑动也可以,有了这个工具模拟用户翻译然后获取结果完全没问题。此文的最终目的是可以为调用者提供一个简洁的接口,请求该接口返回,返回为中文的结果,接口的响应时间尽可能的短,可支持并发。响应时间没多少可以优化的地方,主要依赖网络环境,以及谷歌的接口响应时间,我们只能做到当谷歌接口返回的时候我们也第一时间返回给调用者。

最近做个东西,需将各种语言翻译成中文,看了各家的翻译效果,还是谷歌的最好。

但谷歌的未提供免费接口,研究了谷歌的翻译页面,输入内容后会触发ajax请求,请求参数中除了输入内容,还有个加密参数tk,该加密算法在压缩的js代码中,我也在网上找到了网友摘出来的代码,js格式,一大段,压缩代码翻译起来很吃力,遂未翻译,而另辟蹊径,在生产环境的docker中打包了node环境,业务代码通过shell调用这段js,得到加密参数后再模拟请求,获得翻译结果,用着还挺好。

没过多久,发现失效了,请求返回403 Forbidden,禁止访问 ,估计加密参数算法又升级了。

接口翻译固然好用,但隔断时间就要重新搞一次加密算法,这个就有点儿难以接受了,每次都要从大量压缩js代码中找出加密算法,还不一定能完全找对。

至此,我们的主角无头浏览器puppeteer就要登场了,puppeteer一个node类库,提供了简洁的API,可以让使用者操作chrome浏览器,基本可以完全模拟人的操作,比如打开页面、输入网址、等待页面指定内容加载、点击按钮、甚至滑动也可以,有了这个工具模拟用户翻译然后获取结果完全没问题。

此文的最终目的是可以为调用者提供一个简洁的接口,请求该接口返回,返回为中文的结果,接口的响应时间尽可能的短,可支持并发。

响应时间没多少可以优化的地方,主要依赖网络环境,以及谷歌的接口响应时间,我们只能做到当谷歌接口返回的时候我们也第一时间返回给调用者。

并发这里可以做优化,一个puppeteer同一时间只能处理一个翻译请求,如果做个实例池,维护多个puppeteer实例,这样就可以提升翻译接口的并发能力了。

实例池

如下图所示,虚线框内表示一个实例池,实例池中有多个puppeteer实例,他们之间互相独立,当请求来的时候,随机从池子中拿出一个实例,处理请求,等待请求处理完毕之后,再次将改实例放回池子中。

为了减少意外情况,池子中的每个实例处理100个翻译之后推出,重新启动一个新的额实例补充进来,池子中的实例总量保持不变,如果需要甚至可以搞成动态的,像php-fpm一样,请求多的时候动态增加实例池中的实例,空闲的时候,清理推出一些实例。

谷歌翻译api如何收费(免费试用谷歌的翻译接口)(1)

如何将请求和结果联系起来

一个请求可以分为两个流程,一个请求流程,一个ajax成功回调流程,请求时候输入翻译原始内容,实例内部在请求谷歌ajax接口成功的时候调用预先注册好的回调函数,这两个流程没有办法直接联系起来,但他们都会接触到同一个实例,所以用这个实例将他们俩联系起来,ajax流程成功之后写入一个变量到实例对象上,请求流程中监测该实例上的变量,有数据说明请求成功,返回数据,清空该变量,原理可以看下面的简化代码

let obj = {} setTimeout(() => { obj.result = "this is async result" } 2000) async function sleep(duration) { return new Promise(resolve => { setTimeout(() => { resolve() } duration) }) } async function getRet() { let times = 1 while(times <= 100) { if (obj.result) { return Promise.resolve(obj.result) } else { await sleep(200) } times } } (async () => { let ret = await getRet() console.log(ret) console.log("now i can do something") })()

实现

我将这个功能包装成了一个类库,上传到了npm,google-trans-api,顺便也熟悉了整个打包流程以及typescript的使用,不得不说typescript真是不错,可以防止很多误写的错误,还有自动提示的功能,用起来不要太爽。这里是源码地址aizuyan/google-trans-api。

使用

下载Chromium

linux、mac下面的Chromium是两个不同的包,如果网络可以FQ,直接部署安装即可,否则需要手动下载,传送门,我的网络就不好,因此提前将两个版本的包放在项目根目录下的Chromium目录下,开发环境使用darwin目录下的包,生产环境使用linux下的包

. ├── Chromium │ ├── darwin │ └── linux

配合下面的代码,可以自动根据环境选择使用的包路径,并传入实例的executablePath参数中

"use strict" const path = require("path") const os = require("os") const platform = os.platform() let ret = path.join(__dirname ".." "Chromium" platform) switch (platform) { case "linux": ret = path.join(ret "chrome") break case "darwin": ret = path.join(ret "Chromium.app/Contents/MacOS/Chromium") break } module.exports = ret

代理

如果网路不好,可能需要安装代理,可以使用shadowsocks,支持所有环境,默认没有代理,如果需要,可以在初始化的时候传入proxyServer: '--proxy-server=socks5://127.0.0.1:1080'参数。

完整的试用版本

const koa = require('koa') const app = new koa() const router = require('koa-router')(); const GoogleTrans = require('google-trans-api').default // 调用的时候改为你自己的 const chromePath = '/path/to/puppeteer Chromium'; (async () => { let instance = new GoogleTrans({ handles: false worker:3 executablePath: chromePath initPageTimeout: 0 //proxyServer: '--proxy-server=socks5://127.0.0.1:1080' regExpIncludeUrl: url => { const reg = new RegExp("translate.google.cn/translate_a/single.*?q=.*") return reg.test(url) } responseCb: async response => { const url = response.url() console.log(url) try { const text = await response.text() const status = response.status() let ret = JSON.parse(text) ret = ret[0] let data = "" for (let i = 0; i < ret.length; i ) { if (ret[i][0]) { data = ret[i][0] } } return Promise.resolve(data) } catch (err) { console.error(`Failed getting data from: ${url}`) console.error(err); } } }) let flag = await instance.init() router.get('/trans-auto' async ctx => { try { let msg = decodeURIComponent(ctx.query.msg) let ret = await instance.trans(msg) ctx.response.body = ret } catch (e) { console.log(`[error] when trans ${e.message}`) ctx.response.body = "" } }) app .use(router.routes()) .use(router.allowedMethods()) app.listen(3000 () => { console.log('server is running at http://localhost:3000') }) })()

下面是我打开GUI模式,看效果的图片

谷歌翻译api如何收费(免费试用谷歌的翻译接口)(2)

猜您喜欢: