Python新世界python热爱者

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

2018-12-26  本文已影响1人  48e0a32026ae

这篇文章的主要目的还是破解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)

上一篇下一篇

猜你喜欢

热点阅读