python 爬蟲 打造【百度翻譯】

環(huán)境
| python版本號(hào) | 系統(tǒng) | 游覽器 |
|---|---|---|
| python 3.7.2 | win7 | google chrome |
關(guān)于本文
本文將會(huì)通過爬蟲的方式實(shí)現(xiàn)簡(jiǎn)單的百度翻譯。本文中的代碼只供學(xué)習(xí),不允許作為于商務(wù)作用。商務(wù)作用請(qǐng)前往api.fanyi.baidu.com購買付費(fèi)的api。若有侵犯,立即刪文!
實(shí)現(xiàn)思路
在網(wǎng)站文件中找到隱藏的免費(fèi)api。傳入api所需要的參數(shù)并對(duì)其發(fā)出請(qǐng)求。在返回的json結(jié)果里找到相應(yīng)的翻譯結(jié)果。
百度翻譯的反爬機(jī)制
由js算法生成的sign
cookie檢測(cè)
token暗號(hào)
在網(wǎng)站文件中找到隱藏的免費(fèi)api
進(jìn)入 百度翻譯 ,隨便輸入一段需要翻譯的文字。當(dāng)翻譯結(jié)果出來的時(shí)候,按下F12,選擇到NETWORK,最后點(diǎn)進(jìn)XHR文件。這個(gè)時(shí)候,網(wǎng)站文件都已經(jīng)加載完了,所以要F5刷新一下。

刷新了之后,我們就能發(fā)現(xiàn)一個(gè)以v2transapi?開頭的文件,沒錯(cuò),它就是我們要找的api接口。讓我們驗(yàn)證一下,點(diǎn)進(jìn)去文件-preview,我們就可以在json格式的數(shù)據(jù)里面找到翻譯結(jié)果,驗(yàn)證成功。
另外,我們還需要獲取我們的cookie和token,在之后的反爬機(jī)制中我們需要用到它們,位置如以下。
cookie位置:

token位置:

api信息
接口:https://fanyi.baidu.com/v2tra...
請(qǐng)求方式:post
請(qǐng)求參數(shù)大全
| 參數(shù) | 介紹 |
|---|---|
| from | 源語言 |
| to | 目標(biāo)語言 |
| query | 翻譯文本 |
| sign | 由js算法生成的簽名(反爬) |
| token | 請(qǐng)求暗號(hào) |
開始寫代碼
導(dǎo)入request和execjs庫
requests
execjs
requests HTTP庫,用于爬蟲
execjs 用于調(diào)用js代碼
反爬蟲
由于百度翻譯有cookie識(shí)別反爬機(jī)制,所以我們?cè)O(shè)置好我們剛剛獲取到的cookie來進(jìn)行掩護(hù)網(wǎng)絡(luò)蜘蛛身份。
headers = {'cookie':'請(qǐng)?jiān)谶@里輸入你的cookie'}另外,我們還要設(shè)置好token(暗號(hào))。
token = '請(qǐng)?jiān)谶@里放置你的token'
最后只剩下sign反爬機(jī)制了,sign是由js算法給譯文生成的一個(gè)簽名。我在網(wǎng)上搜了一下,找到了相應(yīng)的js算法,分享給大家。
i =
(r, o) {
( t = ; t < o.length - ; t += ) {
a = o.charAt(t + );
a = a >= ? a.charCodeAt() - : (a), a = === o.charAt(t + ) ? r >>> a : r << a, r = === o.charAt(t) ? r + a & : r ^ a
}
r
}
(r) {
o = r.match();
( === o) {
t = r.length;
t > && (r = + r.substr(, ) + r.substr(.floor(t / ) - , ) + r.substr(, ))
} {
( e = r.split(), C = , h = e.length, f = []; h > C; C++) !== e[C] && f.push.apply(f, a(e[C].split())), C !== h - && f.push(o[C]);
g = f.length;
g > && (r = f.slice(, ).join() + f.slice(.floor(g / ) - , .floor(g / ) + ).join() + f.slice().join())
}
u = , l = + .fromCharCode() + .fromCharCode() + .fromCharCode();
u = !== i ? i : (i = [l] || ) || ;
( d = u.split(), m = (d[]) || , s = (d[]) || , S = [], c = , v = ; v < r.length; v++) {
A = r.charCodeAt(v);
> A ? S[c++] = A : ( > A ? S[c++] = A >> | : ( === ( & A) && v + < r.length && === ( & r.charCodeAt(v + )) ? (A = + (( & A) << ) + ( & r.charCodeAt(++v)), S[c++] = A >> | , S[c++] = A >> & | ) : S[c++] = A >> | , S[c++] = A >> & | ), S[c++] = & A | )
}
( p = m, F = + .fromCharCode() + .fromCharCode() + .fromCharCode() + ( + .fromCharCode() + .fromCharCode() + .fromCharCode()), D = + .fromCharCode() + .fromCharCode() + .fromCharCode() + ( + .fromCharCode() + .fromCharCode() + .fromCharCode()) + ( + .fromCharCode() + .fromCharCode() + .fromCharCode()), b = ; b < S.length; b++) p += S[b], p = n(p, F);
p = n(p, D), p ^= s, > p && (p = ( & p) + ), p %= , p.toString() + + (p ^ m)
}
等等,我們不是在用python進(jìn)行爬蟲嗎?那我們又不會(huì)js代碼,怎么調(diào)用啊?
還好python有著強(qiáng)大的第三方庫,當(dāng)然也少不了調(diào)用js代碼的庫。調(diào)用js代碼的庫很多,但是本人還是推薦大家使用execjs,簡(jiǎn)單功能又完整。
在調(diào)用js算法代碼之前,我們還需要讓用戶輸入一段譯文。
q = input('翻譯:')之后我們就能使用execjs的compile和call方法來獲取sign了。
js =
n(r, o) {
(var t = ; t < o.length - ; t += ) {
var a = o.charAt(t + );
a = a >= ? a.charCodeAt() - : Number(a), a = === o.charAt(t + ) ? r >>> a : r << a, r = === o.charAt(t) ? r + a & : r ^ a
}
return r
}
e(r) {
var o = r.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
( === o) {
var t = r.length;
t > && (r = + r.substr(, ) + r.substr(Math.floor(t / ) - , ) + r.substr(, ))
} {
(var e = r.(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = , h = e.length, f = []; h > C; C++) !== e[C] && f.push.apply(f, a(e[C].())), C !== h - && f.push(o[C]);
var g = f.length;
g > && (r = f.slice(, ).() + f.slice(Math.floor(g / ) - , Math.floor(g / ) + ).() + f.slice().())
}
var u = void , l = + .fromCharCode() + .fromCharCode() + .fromCharCode();
u = !== i ? i : (i = window[l] || ) || ;
(var d = u.(), m = Number(d[]) || , s = Number(d[]) || , S = [], c = , v = ; v < r.length; v++) {
var A = r.charCodeAt(v);
> A ? S[c++] = A : ( > A ? S[c++] = A >> | : ( === ( & A) && v + < r.length && === ( & r.charCodeAt(v + )) ? (A = + (( & A) << ) + ( & r.charCodeAt(++v)), S[c++] = A >> | , S[c++] = A >> & | ) : S[c++] = A >> | , S[c++] = A >> & | ), S[c++] = & A | )
}
(var p = m, F = + .fromCharCode() + .fromCharCode() + .fromCharCode() + ( + .fromCharCode() + .fromCharCode() + .fromCharCode()), D = + .fromCharCode() + .fromCharCode() + .fromCharCode() + ( + .fromCharCode() + .fromCharCode() + .fromCharCode()) + ( + .fromCharCode() + .fromCharCode() + .fromCharCode()), b = ; b < S.length; b++) p += S[b], p = n(p, F);
return p = n(p, D), p ^= s, > p && (p = ( & p) + ), p %= , p.toString() + + (p ^ m)
}
sign = execjs.compile(js).(,q)
(以上代碼獲取了sign)
經(jīng)過一系列的反反爬蟲準(zhǔn)備,我們就可以設(shè)置好的“源語言”和“目標(biāo)語言”最后的這兩個(gè)參數(shù)了。
From =
To =
(以上代碼代表著英譯中,若要進(jìn)行其它語言的翻譯,請(qǐng)輸入語言對(duì)應(yīng)的英文縮寫,英文縮寫對(duì)應(yīng)表將會(huì)放到本文最后)
接著,我們就能構(gòu)建參數(shù)json了。
data = {,
,
,
,
}最后,我們就能請(qǐng)求數(shù)據(jù)并打印了。
= requests.post(url,headers=headers,=).json()
(text)
我們發(fā)現(xiàn)打印出來的結(jié)果是個(gè)json字典,翻譯結(jié)果就在其中,我們只需要翻譯結(jié)果,所以我們可以索引翻譯結(jié)果的位置再打印。
text = requests.post(url,headers=headers,data=data).json()[][][][]
print(text)
運(yùn)行結(jié)果:

完整代碼:
import requests
import execjs
url = :
headers = {你的cookie'}
js = var i =
function n(r, o) {
(var t = ; t < o.length - ; t += ) {
var a = o.charAt(t + );
a = a >= ? a.charCodeAt() - : Number(a), a = === o.charAt(t + ) ? r >>> a : r << a, r = === o.charAt(t) ? r + a & : r ^ a
}
r
}
function e(r) {
var o = r.(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);
(null === o) {
var t = r.length;
t > && (r = + r.substr(, ) + r.substr(Math.floor(t / ) - , ) + r.substr(-, ))
} {
(var e = r.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/), C = , h = e.length, f = []; h > C; C++) !== e[C] && f.push.apply(f, a(e[C].split())), C !== h - && f.push(o[C]);
var g = f.length;
g > && (r = f.slice(, ).join() + f.slice(Math.floor(g / ) - , Math.floor(g / ) + ).join() + f.slice(-).join())
}
var u = void , l = + .fromCharCode() + .fromCharCode() + .fromCharCode();
u = null !== i ? i : (i = window[l] || ) || ;
(var d = u.split(), m = Number(d[]) || , s = Number(d[]) || , S = [], c = , v = ; v < r.length; v++) {
var A = r.charCodeAt(v);
> A ? S[c++] = A : ( > A ? S[c++] = A >> | : ( === ( & A) && v + < r.length && === ( & r.charCodeAt(v + )) ? (A = + (( & A) << ) + ( & r.charCodeAt(++v)), S[c++] = A >> | , S[c++] = A >> & | ) : S[c++] = A >> | , S[c++] = A >> & | ), S[c++] = & A | )
}
(var p = m, F = + .fromCharCode() + .fromCharCode() + .fromCharCode() + ( + .fromCharCode() + .fromCharCode() + .fromCharCode()), D = + .fromCharCode() + .fromCharCode() + .fromCharCode() + ( + .fromCharCode() + .fromCharCode() + .fromCharCode()) + ( + .fromCharCode() + .fromCharCode() + .fromCharCode()), b = ; b < S.length; b++) p += S[b], p = n(p, F);
p = n(p, D), p ^= s, > p && (p = ( & p) + ), p %= , p.toString() + + (p ^ m)
}
= '源語言'
To = '目標(biāo)語言'
token = '你的token'
q = input('翻譯:')
sign = execjs.compile(js).call(,q)
data = {':,
':To,
':q,
':sign,
':token}
text = requests.post(url,headers=headers,data=data).json()[']['][][']
print(text)
語言英文縮寫對(duì)應(yīng)表
{
: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: ,: }喜歡的話點(diǎn)在看支持一下唄~
