美文网首页Python新世界python热爱者
python破解百度翻译反爬机制——自制翻译器

python破解百度翻译反爬机制——自制翻译器

作者: 48e0a32026ae | 来源:发表于2018-12-26 15:45 被阅读1次

    这篇文章的主要目的还是破解JS参数加密,百度翻译的JS过程并不是很复杂,非常适合新手练手。

    首先,打开百度翻译,随便输点词语,点击翻译。

    不断点击翻译,在network中会一直跳出框框内的内容。

    打开第二个文件v2transapi,可以看到我们需要的内容。

    现在来分析一下这个文件,它的请求方式为post,下图是它post时所需的data。from是你输入词语的类型,to是需要翻译成的类型,query是翻译的词语,sign和token是通过js文件生成的;现在来找一找这两个参数。

    https://fanyi.bdstatic.com/static/translation/pkg/index_9b62d56.js:formatted是JS文件的链接,打断点调试可以看到,sign是通过m(‘翻译’ )生成的,token是通过 window.common.token生成。

    其中window.common.token在页面的源代码中有出现 ‘04a7c540f2a1e1d6be3dee208d1b7525’;第二个框的参数后面会用到。

    def parame():

    url = 'https://fanyi.baidu.com/?aldtype=16047'

    headers = {

    'Accept': '*/*',

    'Accept-Encoding': 'gzip, deflate, br',

    'Accept-Language': 'zh-CN,zh;q=0.9',

    'Connection': 'keep-alive',

    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',

    'Cookie': 'BIDUPSID=A0BE57EF0645F17DEC806F36F3E38844; PSTM=1531234350; BAIDUID=EEEDF0D3A7636804D4AF070CB10CC56A:FG=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BDUSS=VUTVlhSTlOdnhnN3pRRlNBdU0tT21KMnBUMUlJS3Z0ZlJRMzd5MlVVQU1zdmRiQVFBQUFBJCQAAAAAAAAAAAEAAAAl6sYTz8TM7LXEzqLQpk5WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwl0FsMJdBbZz; MCITY=-315%3A; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; H_PS_PSSID=1442_21095_28132_26350_27751_27244_27509; delPer=0; PSINO=1; locale=zh; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1545304167; to_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1545305626; from_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D',

    'Host': 'fanyi.baidu.com',

    'Origin': 'https://fanyi.baidu.com',

    'Referer': 'https://fanyi.baidu.com/',

    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',

    'X-Requested-With': 'XMLHttpRequest'

    }

    html = requests.get(url,headers=headers).text

    windows_gtk = re.findall(r';window.gtk = (.*?);', html)[0][1:-1]

    window_bdstoken = re.findall(r'window.bdstoken = (.*?);window.gtk', html)[0]

    token = re.findall(r"token: (.*?),", html)[0]

    logid = re.findall(r'logid: (.*?),', html)[0][1:-1]

    #print(window_bdstoken, windows_gtk, token, logid)

    return token,windows_gtk

    在来看m()函数,它的参数就是要翻译的内容,定位到5725-5727行,这三行是用来生成一个参数u,且u的值为window.gtk,也就是上一幅图第二个框框内的内容;为了使代码更加灵活,在构造js函数的时候,将参数u从定值转为m()函数的参数,这一部分进行调整。

    调整后的JS代码如下:

    function a(r) {

    if (Array.isArray(r)) {

    for (var o = 0, t = Array(r.length); o < r.length; o++)

    t[o] = r[o];

    return t

    }

    return Array.from(r)

    }

    function n(r, o) {

    for (var t = 0; t < o.length - 2; t += 3) {

    var a = o.charAt(t + 2);

    a = a >= "a" ? a.charCodeAt(0) - 87 : Number(a),

    a = "+" === o.charAt(t + 1) ? r >>> a : r << a,

    r = "+" === o.charAt(t) ? r + a & 4294967295 : r ^ a

    }

    return r

    }

    function e(r,u) {

    var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);

    if (null === o) {

    var t = r.length;

    t > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(t / 2) - 5, 10) + r.substr(-10, 10))

    } else {

    for (var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = 0, h = e.length, f = []; h > C; C++)

    "" !== e[C] && f.push.apply(f, a(e[C].split(""))),

    C !== h - 1 && f.push(o[C]);

    var g = f.length;

    g > 30 && (r = f.slice(0, 10).join("") + f.slice(Math.floor(g / 2) - 5, Math.floor(g / 2) + 5).join("") + f.slice(-10).join(""))

    }

    for (var d = u.split("."), m = Number(d[0]) || 0, s = Number(d[1]) || 0, S = [], c = 0, v = 0; v < r.length; v++) {

    var A = r.charCodeAt(v);

    128 > A ? S[c++] = A : (2048 > A ? S[c++] = A >> 6 | 192 : (55296 === (64512 & A) && v + 1 < r.length && 56320 === (64512 & r.charCodeAt(v + 1)) ? (A = 65536 + ((1023 & A) << 10) + (1023 & r.charCodeAt(++v)),

    S[c++] = A >> 18 | 240,

    S[c++] = A >> 12 & 63 | 128) : S[c++] = A >> 12 | 224,

    S[c++] = A >> 6 & 63 | 128),

    S[c++] = 63 & A | 128)

    }

    for (var p = m, F = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(97) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(54)), D = "" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(51) + ("" + String.fromCharCode(94) + String.fromCharCode(43) + String.fromCharCode(98)) + ("" + String.fromCharCode(43) + String.fromCharCode(45) + String.fromCharCode(102)), b = 0; b < S.length; b++)

    p += S[b],

    p = n(p, F);

    return p = n(p, D),

    p ^= s,

    0 > p && (p = (2147483647 & p) + 2147483648),

    p %= 1e6,

    p.toString() + "." + (p ^ m)

    }

    var i = null;

    至此整个流程就分析完了,下面来构造自己的翻译器把。顺便一说,百度翻译可以实现88种语言的互转噢。

    def translate(key,fro,to):

    node = execjs.get()

    file = '百度翻译.js'

    ctx = node.compile(open(file, encoding='utf-8').read())

    token,u=parame()

    js = 'e("{0}","{1}")'.format(key,u)

    sign = ctx.eval(js)

    print(sign)

    headers = {

    'Accept': '*/*',

    'Accept-Encoding': 'gzip, deflate, br',

    'Accept-Language': 'zh-CN,zh;q=0.9',

    'Connection': 'keep-alive',

    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',

    'Cookie':'BIDUPSID=A0BE57EF0645F17DEC806F36F3E38844; PSTM=1531234350; BAIDUID=EEEDF0D3A7636804D4AF070CB10CC56A:FG=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BDUSS=VUTVlhSTlOdnhnN3pRRlNBdU0tT21KMnBUMUlJS3Z0ZlJRMzd5MlVVQU1zdmRiQVFBQUFBJCQAAAAAAAAAAAEAAAAl6sYTz8TM7LXEzqLQpk5WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwl0FsMJdBbZz; MCITY=-315%3A; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; H_PS_PSSID=1442_21095_28132_26350_27751_27244_27509; delPer=0; PSINO=1; locale=zh; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1545304167; to_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1545307350; from_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D',

    'Host': 'fanyi.baidu.com',

    'Origin': 'https://fanyi.baidu.com',

    'Referer': 'https://fanyi.baidu.com/',

    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',

    'X-Requested-With': 'XMLHttpRequest'

    }

    data = {

    'from': fro,

    'to':to,

    'query': key,

    'transtype': 'translang',

    'simple_means_flag': '3',

    'sign': sign,

    #'token':'04a7c540f2a1e1d6be3dee208d1b7525'

    'token':token[1:-1]

    }

    url = 'https://fanyi.baidu.com/v2transapi'

    html = requests.post(url, data=data, headers=headers).json()

    html=html['trans_result']['data'][0]

    result={

    html['src']:html['dst']

    }

    print(result)

    return result

    import re

    def parame():

    url = 'https://fanyi.baidu.com/?aldtype=16047'

    headers = {

    'Accept': '*/*',

    'Accept-Encoding': 'gzip, deflate, br',

    'Accept-Language': 'zh-CN,zh;q=0.9',

    'Connection': 'keep-alive',

    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',

    'Cookie': 'BIDUPSID=A0BE57EF0645F17DEC806F36F3E38844; PSTM=1531234350; BAIDUID=EEEDF0D3A7636804D4AF070CB10CC56A:FG=1; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BDUSS=VUTVlhSTlOdnhnN3pRRlNBdU0tT21KMnBUMUlJS3Z0ZlJRMzd5MlVVQU1zdmRiQVFBQUFBJCQAAAAAAAAAAAEAAAAl6sYTz8TM7LXEzqLQpk5WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwl0FsMJdBbZz; MCITY=-315%3A; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; H_PS_PSSID=1442_21095_28132_26350_27751_27244_27509; delPer=0; PSINO=1; locale=zh; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1545304167; to_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1545305626; from_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D',

    'Host': 'fanyi.baidu.com',

    'Origin': 'https://fanyi.baidu.com',

    'Referer': 'https://fanyi.baidu.com/',

    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36',

    'X-Requested-With': 'XMLHttpRequest'

    }

    html = requests.get(url,headers=headers).text

    windows_gtk = re.findall(r';window.gtk = (.*?);', html)[0][1:-1]

    window_bdstoken = re.findall(r'window.bdstoken = (.*?);window.gtk', html)[0]

    token = re.findall(r"token: (.*?),", html)[0]

    logid = re.findall(r'logid: (.*?),', html)[0][1:-1]

    #print(window_bdstoken, windows_gtk, token, logid)

    return token,windows_gtk

    if __name__ == '__main__':

    #key=input('请输入要翻译的文字')

    dic = {'中文': 'zh', '日语': 'jp', '日语假名': 'jpka', '泰语': 'th', '法语': 'fra', '英语': 'en', '西班牙语': 'spa', '韩语': 'kor',

    '土耳其语': 'tr', '越南语': 'vie', '马来语': 'ms', '德语': 'de', '俄语': 'ru', '伊朗语': 'ir', '阿拉伯语': 'ara', '爱沙尼亚语': 'est',

    '白俄罗斯语': 'be', '保加利亚语': 'bul', '印地语': 'hi', '冰岛语': 'is', '波兰语': 'pl', '波斯语': 'fa', '丹麦语': 'dan',

    '菲律宾语': 'tl', '芬兰语': 'fin', '荷兰语': 'nl', '加泰罗尼亚语': 'ca', '捷克语': 'cs', '克罗地亚语': 'hr', '拉脱维亚语': 'lv',

    '立陶宛语': 'lt', '罗马尼亚语': 'rom', '南非语': 'af', '挪威语': 'no', '巴西语': 'pt_BR', '葡萄牙语': 'pt', '瑞典语': 'swe',

    '塞尔维亚语': 'sr', '世界语': 'eo', '斯洛伐克语': 'sk', '斯洛文尼亚语': 'slo', '斯瓦希里语': 'sw', '乌克兰语': 'uk', '希伯来语': 'iw',

    '希腊语': 'el', '匈牙利语': 'hu', '亚美尼亚语': 'hy', '意大利语': 'it', '印尼语': 'id', '阿尔巴尼亚语': 'sq', '阿姆哈拉语': 'am',

    '阿萨姆语': 'as', '阿塞拜疆语': 'az', '巴斯克语': 'eu', '孟加拉语': 'bn', '波斯尼亚语': 'bs', '加利西亚语': 'gl', '格鲁吉亚语': 'ka',

    '古吉拉特语': 'gu', '豪萨语': 'ha', '伊博语': 'ig', '因纽特语': 'iu', '爱尔兰语': 'ga', '祖鲁语': 'zu', '卡纳达语': 'kn', '哈萨克语': 'kk',

    '吉尔吉斯语': 'ky', '卢森堡语': 'lb', '马其顿语': 'mk', '马耳他语': 'mt', '毛利语': 'mi', '马拉提语': 'mr', '尼泊尔语': 'ne',

    '奥利亚语': 'or', '旁遮普语': 'pa', '凯楚亚语': 'qu', '塞茨瓦纳语': 'tn', '僧加罗语': 'si', '泰米尔语': 'ta', '塔塔尔语': 'tt',

    '泰卢固语': 'te', '乌尔都语': 'ur', '乌兹别克语': 'uz', '威尔士语': 'cy', '约鲁巴语': 'yo', '粤语': 'yue', '文言文': 'wyw',

    '中文繁体': 'cht'}

    key='为乐为魂之语与通〜'

    fro =dic['文言文']

    to=dic['英语']

    translate(key,fro,to)

    效果图如下:

    提前剧透一下,下一篇会介绍基于有道翻译的自制翻译器。。。敬请期待。

    所有代码都已经传到

    Github了(https://github.com/zuobangbang/javascript-decode)

    相关文章

      网友评论

        本文标题:python破解百度翻译反爬机制——自制翻译器

        本文链接:https://www.haomeiwen.com/subject/gnihlqtx.html