[314]谷歌翻译

googletrans

pip install requests
#安装googletrans,需要安装requests依赖
pip install googletrans
#-*- coding:utf-8 -*-
from googletrans import Translator

'''
ZH,    // 中文       "zh-CN"
EN,    // 英语       "en"
JP,    // 日语       "ja"
JPKA,  // 日语假名
TH,    // 泰语
FRA,   // 法语       "fr"
SPA,   // 西班牙语   "es"   <---  添加语种(自定义语种代号)
KOR,   // 韩语       "ko"
'''

# 设置Google翻译服务地址
# translator = Translator(service_urls=[
#       'translate.google.cn'
#     ])
translator = Translator()
print(translator.translate('今天天气不错',dest='en', src='auto').text)
print(translator.translate('hello', dest='zh-CN').text)
print(translator.translate('今天天气不错', dest='ja').text)
print(translator.translate('今天天气不错', dest='ko').text)
print(translator.translate('今天天气不错', dest='es').text)
print(translator.translate('今天天气不错', dest='fr').text)

首先在github上我们找到了这篇链接 https://github.com/ssut/py-googletrans
然后运行 pip install googletrans 这个命令,去下载提供的这个库。
image.png
这个时候出错,提示我们没有requests库,因此我们还需要在安装requests库。果然文档里也有些
image.png
这个时候我们调用它API提供的方法试试,代码如下:

#-*- coding:utf-8 -*-
from googletrans import Translator
import sys

reload(sys)
sys.setdefaultencoding( "utf-8" )

translator = Translator()
print translator.translate('今天天气不错').text
print translator.translate('今天天气不错', dest='ja').text
print translator.translate('今天天气不错', dest='ko').text

这个时候就可以看到输出结果:

the weather is nice today
今日天気がいいです
오늘 날씨가 좋은

一个简单的翻译demo就实现了。是不是非常的简单

然而,这个库并不是google官方提供的,并且有的时候这个库也是不稳定的


Google

第一步当然是抓取它的请求,看看它是怎么请求的。按下F12进入浏览器调试模式,眼睛盯紧network:

image

接着我们输入一句话,看看它会产生什么消息包。

image

居然有这么多的消息包,我们一个一个找,直到找到Response中有翻译内容的。这个时候我们去看一下它的header:

image

可以看到是get方式,于是我们可以浏览器里直接去请求这个url。

果然我们的得到了一个文件,这个时候打开文件,文件里就是请求回来的翻译结果:

image

这时候我们去分析一下请求的参数,看看我们是否可以构造,可以看到原来要翻译的文本,就是跟着q这个参数出去的:

image

只不过在请求的时候,文字被encode成了%**%,这时候我们试着换一个文字去请求,结果发现返回:

image

仔细上网查过之后,每次翻译的文字不同,参数中的tk值就会不同,ticket这种策略就是google用来防爬虫的。

tk和文字以及TKK有关,TKK也是实时变化的,具体怎么拿到是在 translate.google.cn 这个网页源代码中有一段js代码:

image

我们直接运行这段js,会得到一个值,这个值就是 TKK值:

image

那么如何根据TKK和文本算出tk值呢,网上有大神已经实现了js的代码,直接拿过来用了:

var b = function (a, b) {
    for (var d = 0; d < b.length - 2; d += 3) {
        var c = b.charAt(d + 2),
            c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),
            c = "+" == b.charAt(d + 1) ? a >>> c : a << c;
        a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c
    }
    return a
}

var tk =  function (a,TKK) {
    for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {
        var c = a.charCodeAt(f);
        128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ? (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240, g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)
    }
    a = h;
    for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");
    a = b(a, "+-3^+b+-f");
    a ^= Number(e[1]) || 0;
    0 > a && (a = (a & 2147483647) + 2147483648);
    a %= 1E6;
    return a.toString() + "." + (a ^ h)

这段代码只需要直接调用 tk这个函数就可以得到tk值,得到tk值之后,我们就可以拼接出url来进行请求了。

google demo

这里我用Python和node一起完成了一个小的demo,大家可以下载我的代码。我简单介绍一下脚本的原理。

首先入口是用node完成的:

// 导入translate
var trans= require('./translate.js');

// 调用翻译结果
trans.gettrans('你好')

直接调用了 translate.js,我们看看这个文件:

// 得到TKK
var exec = require('child_process').exec; 
var cmdStr = 'getTKK.py';
exec(cmdStr, function(err,stdout,stderr){
    if(err) {
        console.log('get TKK is error' + stderr);
    } else {
        //console.log(stdout);
    }
}); 

// 读取TKK
var rf=require("fs");  
var tkk=rf.readFileSync("TKK","utf-8");  
//console.log(tkk);

var gettrans=function(text){
    var gettk= require('./gettk.js')
    res=gettk.tk(text, tkk.toString())
    //console.log(res)
    var testenc = encodeURI(text)
    //console.log(encodeURI(text))

    var exec2 = require('child_process').exec; 
    var cmdStr2 = 'http.py '+testenc+' '+res+' ';
    //console.log('http.py '+testenc+' '+res)
    exec2(cmdStr2, function(err,stdout,stderr){
        if(err) {
            //console.log('http is error' + stderr);
        } else {
            // 最终的结果
            console.log(stdout);
        }
    });
}

module.exports.gettrans=gettrans;

translate.js 当中融合了比较多的内容,首先是调用Python的getTKK.py。

#-*- coding:utf-8 -*-
import os

# 爬取网页拿到TKK的js代码
os.system('getTKKjs.py > getTKK.js')  

# 执行TKKjs代码拿到TKK值
os.system('node getTKK.js > TKK')

我们可以看到原理很简单,先调用 getTKKjs.py 利用爬虫先将刚才我们分析的那段网页代码给爬取下来,然后生成js文件,接着调用这个js文件,将结果写入到本地一个文件TKK当中。紧接着translate.js读取了TKK值之后,调用我们前面提到的那段node的接口,就可以得到tk值了,这个时候再调用http.py送给Python进行请求,将结果回传给node。

#-*- coding:utf-8 -*-
import urllib2
from bs4 import BeautifulSoup


# 要爬取的总url
weburl='http://translate.google.cn/'

class Climbing():    
    # 设置代理开关
    enable_proxy = False
    # 总url
    url = ''
 
    # 初始化
    def __init__(self, url):
        self.url = url
        proxy_handler = urllib2.ProxyHandler({"http" : 'web-proxy.oa.com:8080'})
        null_proxy_handler = urllib2.ProxyHandler({})
        if self.enable_proxy:
            opener = urllib2.build_opener(proxy_handler)
        else:
            opener = urllib2.build_opener(null_proxy_handler)
        urllib2.install_opener(opener)
    
    # 根据url,得到请求返回内容的soup对象
    def __getResponseSoup(self, url):
        request = urllib2.Request(url)
        request.add_header('User-Agent', "Mozilla/5.0")
        #request.add_header('Accept-Language', 'zh-ch,zh;q=0.5')
        response = urllib2.urlopen(request)
        resault = response.read()
        soup = BeautifulSoup(resault, "html.parser")
        return soup
    
    # 爬取TKK
    def getTKK(self):    
        soup = self.__getResponseSoup(self.url)
        allinfo = soup.find_all('script')
        for info in allinfo:
            chinese = info.get_text().encode('utf-8')
            #print chinese
            if chinese.find("TKK") > 0:    
                #print chinese
                res = chinese.split("TKK")[1]
                res = res.split(");")[0]
                print "TKK"+res+");"
                print "console.log(TKK);"

        
c = Climbing(weburl)
c.getTKK()
#-*- coding:utf-8 -*-
import time
import urllib2
import urllib
from sys import argv
 
script,zh,tk = argv

url='http://translate.google.cn/translate_a/single?client=t&sl=zh-CN&tl=en&hl=zh-CN&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&ie=UTF-8&oe=UTF-8&pc=1&otf=1&ssel=6&tsel=3&kc=0&tk='+ tk +'&q=' + zh

def getRes():
    #print 'chinese is :'+urllib.unquote(first)
    
    null_proxy_handler = urllib2.ProxyHandler({})
    opener = urllib2.build_opener(null_proxy_handler)
    urllib2.install_opener(opener)

    req = urllib2.Request(url) 
    req.add_header('User-Agent', "Mozilla/5.0")

    response = urllib2.urlopen(req)
    print response.read()

print getRes()

Gogle two

另外一个翻译的项目:https://github.com/IAMABOY/GoogleFreeTrans.git
需要安装几个软件包,如下

pip install pytest;
pip install flake8;
pip install coverage;
pip install PyExecJS
  • GoogleTrans/Translator.py
# -*- coding:utf-8 -*-
import requests, execjs, json, sys,time,re
from GoogleTrans.CalcTk import CalcTk


class translator():
    headers = {
        'Host': 'translate.google.cn',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
        'Accept-Encoding': 'gzip, deflate, br',
        'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
        'Referer': 'https://translate.google.cn/',
        'Connection': 'keep-alive',
        'Cache-Control': 'max-age=0'
    }
    support_lauguage = {
        'afrikaans': 'af',
        'arabic': 'ar',
        'belarusian': 'be',
        'bulgarian': 'bg',
        'catalan': 'ca',
        'czech': 'cs',
        'welsh': 'cy',
        'danish': 'da',
        'german': 'de',
        'greek': 'el',
        'english': 'en',
        'esperanto': 'eo',
        'spanish': 'es',
        'estonian': 'et',
        'persian': 'fa',
        'finnish': 'fi',
        'french': 'fr',
        'irish': 'ga',
        'galician': 'gl',
        'hindi': 'hi',
        'croatian': 'hr',
        'hungarian': 'hu',
        'indonesian': 'id',
        'icelandic': 'is',
        'italian': 'it',
        'hebrew': 'iw',
        'japanese': 'ja',
        'korean': 'ko',
        'latin': 'la',
        'lithuanian': 'lt',
        'latvian': 'lv',
        'macedonian': 'mk',
        'malay': 'ms',
        'maltese': 'mt',
        'dutch': 'nl',
        'norwegian': 'no',
        'polish': 'pl',
        'portuguese': 'pt',
        'romanian': 'ro',
        'russian': 'ru',
        'slovak': 'sk',
        'slovenian': 'sl',
        'albanian': 'sq',
        'serbian': 'sr',
        'swedish': 'sv',
        'swahili': 'sw',
        'thai': 'th',
        'filipino': 'tl',
        'turkish': 'tr',
        'ukrainian': 'uk',
        'vietnamese': 'vi',
        'yiddish': 'yi',
        'chinese_simplified': 'zh-CN',
        'chinese_traditional': 'zh-TW',
        'auto': 'auto',
    }
    def __init__(self, src='en', dest='fr', updata_time=600):
        if src not in self.support_lauguage and src not in self.support_lauguage.values():
            raise ValueError('source language not support')
        if dest not in self.support_lauguage and dest not in self.support_lauguage.values():
            raise ValueError('destination language not support')
        self.url = 'https://translate.google.cn/translate_a/single'
        self.params = {
            'client': 't',#webapp   t
            'sl': src,
            'tl': dest,
            'hl': 'zh-CN',
            'dt': 'at', 'dt': 'bd','dt': 'ex', 'dt': 'ld', 'dt': 'md',
            'dt': 'qca', 'dt': 'rw', 'dt': 'rm', 'dt': 'ss', 'dt': 't',
            'ie': 'UTF-8', 'oe': 'UTF-8', 'source': 'bh', 'ssel': '0',
            'tsel': '0', 'kc': '1',
            'tk': '376032.257956'
        }
        self.updata_time = updata_time
        self.__updata_tk()

    def __updata_tk(self):
        self.__TK = CalcTk()
        self.__next_up_time = time.time() + self.updata_time

    def __get_res(self, data):  
        try:
            res = requests.post(self.url,headers=self.headers,data=data,params=self.params,timeout=6)
            res.raise_for_status()
        except Exception as e:
            print('class translator __get_res  [-]ERROR: ' + str(e))
            res = ''
        return res
    
    def translate(self, text, multi=False):
        if time.time() > self.__next_up_time:
            self.__updata_tk()
        data = {'q': text}
        self.params['tk'] = self.__TK.get_tk(text)
        # 设置最大请求次数为三次,减少因为超时的失败情况
        for count in range(0,3):
            res = self.__get_res(data)
            if res !='':
                break
        if res=='':
            return res
        retrunString = ''
        for item in res.json()[0]:
            retrunString = retrunString + item[0]#返回的json中按照句子断句翻译,需要进行拼接

        return retrunString
        #ret_list = json.loads(res.text)
        #return ret_list[0][0][0]


if __name__=='__main__':
    cn = '''您好'''
    en = '''
    中国
    '''
    trans = translator(src='zh-CN', dest='en')
    out = trans.translate(en)
    print(out)
  • GoogleTrans/CalcTk.py
# -*- coding:utf-8 -*-
import requests,re,execjs,time


class CalcTk():
    def __init__(self):
        self.tkk = self.get_tkk()  #从服务器获取TKK
        self.ctx = execjs.compile(
        """
        function b(a, b) {
            for (var d = 0; d < b.length - 2; d += 3) {
                var c = b.charAt(d + 2),
                    c = "a" <= c ? c.charCodeAt(0) - 87 : Number(c),
                    c = "+" == b.charAt(d + 1) ? a >>> c : a << c;
                a = "+" == b.charAt(d) ? a + c & 4294967295 : a ^ c
            }
            return a
        }
        function tk(a,TKK) {
            for (var e = TKK.split("."), h = Number(e[0]) || 0, g = [], d = 0, f = 0; f < a.length; f++) {
                var c = a.charCodeAt(f);
                128 > c ? g[d++] = c : (2048 > c ? g[d++] = c >> 6 | 192 : (55296 == (c & 64512) && f + 1 < a.length && 56320 == (a.charCodeAt(f + 1) & 64512) ? (c = 65536 + ((c & 1023) << 10) + (a.charCodeAt(++f) & 1023), g[d++] = c >> 18 | 240, g[d++] = c >> 12 & 63 | 128) : g[d++] = c >> 12 | 224, g[d++] = c >> 6 & 63 | 128), g[d++] = c & 63 | 128)
            }
            a = h;
            for (d = 0; d < g.length; d++) a += g[d], a = b(a, "+-a^+6");
            a = b(a, "+-3^+b+-f");
            a ^= Number(e[1]) || 0;
            0 > a && (a = (a & 2147483647) + 2147483648);
            a %= 1E6;
            return a.toString() + "." + (a ^ h)
        }
        """
        )

    # 从服务器获取TKK
    def get_tkk(self):
        url = 'https://translate.google.cn/'
        headers = {
            'accept': '*/*',
            'accept-encoding': 'gzip, deflate, br',
            'accept-language': 'zh-CN,zh;q=0.9',
            'referer': 'https//translate.google.cn/',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
        }
        retry = 3
        time_interval = 1
        while retry > 0:
            try:
                time.sleep(time_interval)
                response = requests.get(url, headers=headers, timeout=1.5)
                # result.raise_for_status()
                # result.encoding = 'utf-8'
                tkk = re.search(r'tkk\:\'(\d+\.\d+)?\'', response.text).group(1)
                return tkk
            except Exception as e:
                print('function get_tkk [-]ERROR: ' + str(e))
                time.sleep(time_interval)
                time_interval += 1
                retry -= 1
        return 0.0

    def get_tk(self, text):
        try:
            return self.ctx.call('tk', text, self.tkk)
        except Exception as ex:
            print('class CalcTk function get_tk [-]ERROR: ' + str(ex))
        return 0.0

参考:https://www.cnblogs.com/by-dream/p/6554340.html
https://blog.csdn.net/javajiawei/article/details/91456488
https://www.cnblogs.com/sen-c7/p/10070306.html

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周小董

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值