python 爬虫如何实现百度翻译
环境
python版本号 | 系统 | 游览器 |
---|---|---|
python 3.7.2 | win7 | google chrome |
关于本文
本文将会通过爬虫的方式实现简单的百度翻译。本文中的代码只供学习,不允许作为于商务作用。商务作用请前往api.fanyi.baidu.com购买付费的api。若有侵犯,立即删文!
实现思路
在网站文件中找到隐藏的免费api。传入api所需要的参数并对其发出请求。在返回的json结果里找到相应的翻译结果。
百度翻译的反爬机制
- 由js算法生成的sign
- cookie检测
- token暗号
在网站文件中找到隐藏的免费api
进入百度翻译,随便输入一段需要翻译的文字。当翻译结果出来的时候,按下f12,选择到network,最后点进xhr文件。这个时候,网站文件都已经加载完了,所以要f5刷新一下。
刷新了之后,我们就能发现一个以v2transapi?开头的文件,没错,它就是我们要找的api接口。让我们验证一下,点进去文件-preview,我们就可以在json格式的数据里面找到翻译结果,验证成功。
另外,我们还需要获取我们的cookie和token,在之后的反爬机制中我们需要用到它们,位置如以下。
cookie位置:
token位置:
api信息
接口:...
请求方式:post
请求参数大全
参数 | 介绍 |
---|---|
from | 源语言 |
to | 目标语言 |
query | 翻译文本 |
sign | 由js算法生成的签名(反爬) |
token | 请求暗号 |
开始写代码
导入request和execjs库
import requests import execjs
- requests http库,用于爬虫
- execjs 用于调用js代码
反反爬虫
由于百度翻译有cookie识别反爬机制,所以我们设置好我们刚刚获取到的cookie来进行掩护网络蜘蛛身份。
headers = {'cookie':'请在这里输入你的cookie'}
另外,我们还要设置好token(暗号)。
token = '请在这里放置你的token'
最后只剩下sign反爬机制了,sign是由js算法给译文生成的一个签名。我在网上搜了一下,找到了相应的js算法,分享给大家。
var i = "320305.131321201" 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) { 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("")) } var u = void 0, l = "" + string.fromcharcode(103) + string.fromcharcode(116) + string.fromcharcode(107); u = null !== i ? i : (i = window[l] || "") || ""; 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) }
等等,我们不是在用python进行爬虫吗?那我们又不会js代码,怎么调用啊?
还好python有着强大的第三方库,当然也少不了调用js代码的库。调用js代码的库很多,但是本人还是推荐大家使用execjs,简单功能又完整。
在调用js算法代码之前,我们还需要让用户输入一段译文。
q = input('翻译:')
之后我们就能使用execjs的compile和call方法来获取sign了。
js = '''var i = "320305.131321201" 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) { 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("")) } var u = void 0, l = "" + string.fromcharcode(103) + string.fromcharcode(116) + string.fromcharcode(107); u = null !== i ? i : (i = window[l] || "") || ""; 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) } ''' sign = execjs.compile(js).call("e",q)
(以上代码获取了sign)
经过一系列的反反爬虫准备,我们就可以设置好的“源语言”和“目标语言”最后的这两个参数了。
from = 'en' to = 'zh'
(以上代码代表着英译中,若要进行其它语言的翻译,请输入语言对应的英文缩写,英文缩写对应表将会放到本文最后)
接着,我们就能构建参数json了。
data = {'from':from, 'to':to, 'query':q, 'sign':sign, 'token':'14b5f31e3c65d89a0b1c3f756e53942e'}
最后,我们就能请求数据并打印了。
text = requests.post(url,headers=headers,data=data).json() print(text)
我们发现打印出来的结果是个json字典,翻译结果就在其中,我们只需要翻译结果,所以我们可以索引翻译结果的位置再打印。
text = requests.post(url,headers=headers,data=data).json()['trans_result']['data'][0]['dst'] print(text)
运行结果:
完整代码:
import requests import execjs url = 'https://fanyi.baidu.com/v2transapi' headers = {'cookie':'你的cookie'} js = '''var i = "320305.131321201" 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) { 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("")) } var u = void 0, l = "" + string.fromcharcode(103) + string.fromcharcode(116) + string.fromcharcode(107); u = null !== i ? i : (i = window[l] || "") || ""; 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) } ''' from = '源语言' to = '目标语言' token = '你的token' q = input('翻译:') sign = execjs.compile(js).call("e",q) data = {'from':from, 'to':to, 'query':q, 'sign':sign, 'token':token} text = requests.post(url,headers=headers,data=data).json()['trans_result']['data'][0]['dst'] print(text)
语言英文缩写对应表
{ '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': '中文繁体' }
以上就是python 爬虫如何实现百度翻译的详细内容,更多关于python 爬虫实现百度翻译的资料请关注其它相关文章!