美文网首页虫虫程序员python爬虫
Python破解百度翻译反爬机制---自制翻译器

Python破解百度翻译反爬机制---自制翻译器

作者: 天善智能 | 来源:发表于2019-01-03 14:32 被阅读66次

    欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定!

    对商业智能BI、大数据分析挖掘、机器学习,python,R等数据领域感兴趣的同学加微信:tstoutiao,邀请你进入数据爱好者交流群,数据爱好者们都在这儿。

    作者:zuobangbang
    微信公众号:zuobangbang

    这篇文章的主要目的还是破解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 = (.*?);</script>', html)[0][1:-1]
       window_bdstoken = re.findall(r'<script>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 = (.*?);</script>', html)[0][1:-1]
       window_bdstoken = re.findall(r'<script>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的爱好者社区历史文章大合集

    Python的爱好者社区历史文章列表


    关注后在公众号内回复“ 课程 ”即可获取:

    小编的转行入职数据科学(数据分析挖掘/机器学习方向)【最新免费】

    小编的Python的入门免费视频课程

    小编的Python的快速上手matplotlib可视化库!

    崔老师爬虫实战案例免费学习视频。

    陈老师数据分析报告扩展制作免费学习视频。

    玩转大数据分析!Spark2.X + Python精华实战课程免费学习视频。

    相关文章

      网友评论

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

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