python爬取百度翻译结果,需要发送俩次请求。
一次是请求获取输入的语言类型,然后是拿着获取到的语言类型发送下一次请求,获取翻译的结果。
先输入英文“hello”,获取结果
可以发现,输入后返回的翻译结果在这个文件中,接着输入中文“爬虫”进行翻译
发现页面没有重新加载,所以这是由动态页面加载,网址只有from和to后面发生变化,可以猜测后面的元素就是原先语言的类型和想要翻译的类型,而且这是个post请求方式,所以查看一下post的数据部分
post的data部分俩个参数from和to,query就是自己输入的词语,查看上一个请求的内容:
也是返回json数据,其中就有一个参数lan,对应值为zh,可以猜测这个请求是返回此次输入词语的语言类型的。
首先请求获取语言类型:
post的data部分就是输入的词语:
当我们输入中文时会返回zh,所以对应的from值就为zh,to值就为en
-
def
get_lang(
self, lang_data):
# 获取语言类型
-
return lang_data[
"lan"],
"en"
if lang_data[
"lan"] ==
"zh"
else
"zh"
比较难的部分是翻译部分,请求获取到翻译后的结果:
试了几次后发现,这次请求的post数据部分的sign值和token值是必须要加的,且每次输入要翻译的词语后,sign值都会不一样,这时候找一下sign值是哪来的。浏览器控制台打开搜索:
很多都只是包含sign的词语而已,而不是sign,换成输入sign:
第3个有from,to,query,和sign值,和获取翻译结果的请求结果key值一样,所以试着在这里打上断点调试,重新刷新页面,而不是点击翻译:
执行到此处停下,然后进入这里的L函数里,一步一步执行:
这里就跳转到了e函数,而这里传入的参数r就是我们输入的词语,猜测这里的e函数有可能就是把我们输入的词语进行了加密后再输出,把这里e函数整个复制出来,然后在node.js中运行
这里报错说i未定义,回到浏览器找到源码:
这里的i值赋值给u,然后u的值为"320305.1313212101",不清楚i值是哪里来的,先看他是不是个变值,换了给词语搜索后重复步骤发先u值不变,所以就直接在js代码中直接定义一个i值给u,然后接着运行:
var i = "320305.131321201"
又说n未定义,回到浏览器继续执行下一步,找到了n函数,然后也复制进js代码,接着执行:
这时候返回了一个值,比较一下,和输入“爬虫”是返回的sign值一样,这时候爬虫代码基本可以实现出来了。
当输入一个词语时,翻译的结果在["dict_result"]["simple_means"]["word_means"]中,返回一个列表,列表中是这个词语的多个翻译结果:
但是当输入的是一句中文长句子时,程序会报KeyError错误,表明无法找到对应的key值,于是重新查看浏览器,发现原先的json数据中没有["dict_result"]["simple_means"]["word_means"]键值,猜测是百度翻译也对输入的内容进行了分类,如果输入的是句子,则定位到["trans_result"]["data"][0]["dst"]:
这里我用异常处理这里无法翻译中文句子的问题:
-
try:
-
print(
"翻译:" +
str(html_dict[
"dict_result"][
"simple_means"][
"word_means"]))
# 翻译单词:可以得到多个单词意思
-
except KeyError:
-
print(
"翻译:" +
str(html_dict[
"trans_result"][
"data"][
0][
"dst"]))
# 翻译句子
全部代码如下(代码中给了自己的注释):
BaiDuSpider.py:
-
import requests
-
import json
-
import execjs
-
"""爬百度翻译实现中英互译单词和句子(解决了输入中文句子无法翻译的bug),全部代码封装进类里"""
-
-
-
class
BaiDuFanYi:
-
def
__init__(
self):
-
self.lang_url =
"https://fanyi.baidu.com/langdetect"
-
self.trans_url =
"https://fanyi.baidu.com/v2transapi?from={}&to={}"
-
self.headers = {
"Accept":
"*/*",
-
"Accept-Encoding":
"gzip, deflate, br",
-
"Accept-Language":
"zh-CN,zh;q=0.9",
-
"Connection":
"keep-alive",
-
"Content-Length":
"137",
-
"Content-Type":
"application/x-www-form-urlencoded; charset=UTF-8",
-
"User-Agent":
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36",
-
"Cookie":
"BIDUPSID=6753787919BFC4FF60BAD5DC3900D4FA; PSTM=1646125121; BAIDUID=6753787919BFC4FF6E12938C140804C3:FG=1; FANYI_WORD_SWITCH=1; REALTIME_TRANS_SWITCH=1; HISTORY_SWITCH=1; SOUND_PREFER_SWITCH=1; SOUND_SPD_SWITCH=1; APPGUIDE_10_0_2=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BDUSS=JaMmUzTnhFVnFqS2JoUGJZQURVWkJuN3ZEM0lYU1cwWTZ5TC1UbUhLYmhta3BpSVFBQUFBJCQAAAAAAAAAAAEAAABBEVakZ3JlYXTC3dD91OUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOENI2LhDSNid1; BDUSS_BFESS=JaMmUzTnhFVnFqS2JoUGJZQURVWkJuN3ZEM0lYU1cwWTZ5TC1UbUhLYmhta3BpSVFBQUFBJCQAAAAAAAAAAAEAAABBEVakZ3JlYXTC3dD91OUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOENI2LhDSNid1; BDSFRCVID_BFESS=-pAOJexroG0RYrTD5hL5hMjtieKKUdrTDYLEOwXPsp3LGJLVgW2wEG0PtoWBG_u-K4eiogKK3gOTHxtF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tbke_It2tC03H48k-4QEbbQH-UnLqh8jJgOZ04n-ah02Vxo-5x8hjt0TM-cB-Pch-jnD-Jom3UTdsq76Wh35K5tTQP6rLt-J55Q4KKJxbpbAEJra5MckWMPOhUJiB5JMBan7XPbIXKohJh7FM4tW3J0ZyxomtfQxtNRJ0DnjtpChbC0RD5-hjTJM-l-X5to05TIX3b7EfKocKq7_bJ7KhUbQ0RrH2f0t2goMBp6_bnTqOpvabb5xQhFT5-nfXpOe-n7rKhc1QJ3Rh43HQT3m5-4iL4Jd-CriJIT0Wb3cWKOJ8UbS2bOPBTD02-nBat-OQ6npaJ5nJq5nhMJmb67JDMr0eGteJTttJbAs3t88KJjEe-Kk-PnVeIuQLtnZKRvHa2kjbfT-Qp-hjh4GMMc85-F8yPRPKnjn3N5rKl75yUJ5qKOsQU6d34-iDlJ405OTbIOU5q37b66vMb5YhPJvyTtsXnO7hn3lXbrtXp7_2J0WStbKy4oTjxL1Db3JKjvMtgDtVJO-KKCMMC0GDf5; BAIDUID_BFESS=9A8D3FB44C050878949771408EEDD45F:FG=1; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1646570203,1646646587,1646646601,1646646834; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1646646834; ab_sr=1.0.1_NGNlMzYwMGM2Y2IyMmFhNzA2N2E1YTUwYmJjN2NkMDMyYTM5NjgyOTM3NmUwYzZjOWUwZGVjZDE0MzY2MGM0ODU4NGMwYzY1NGZhZmEyYzUzYjIzNWRjMDBlNzdhZTkyMDEyMzQ3OTdiZjQ2ZGMyM2U0ZGY4NDBmZDdjYjM5YzZkZTFkZjUzMGM1ZDE2YzZiNTIxYWQ2MTJjNWEwZWEwNWZiZjZhMmZiZTYwYTRhZWEzZWM0YzNmMmFmMGQxZmI5",
-
"Host":
"fanyi.baidu.com",
-
"Origin":
"https://fanyi.baidu.com",
-
"Referer":
"https://fanyi.baidu.com/?aldtype=16047",
-
"sec-ch-ua":
'"Not A;Brand";v="99", "Chromium";v="98", "Google Chrome";v="98"',
-
"sec-ch-ua-mobile":
"?0",
-
"sec-ch-ua-platform":
'"Windows"',
-
"Sec-Fetch-Dest":
"empty",
-
"Sec-Fetch-Mode":
"cors",
-
"Sec-Fetch-Site":
"same-origin",
-
"X-Requested-With":
"XMLHttpRequest"}
-
-
def
parse_url(
self, url, post_data):
-
# print(url)
-
response = requests.post(url, headers=self.headers, data=post_data)
-
html_str = response.content.decode()
-
return json.loads(html_str)
-
-
def
get_lang(
self, lang_data):
# 获取语言类型
-
return lang_data[
"lan"],
"en"
if lang_data[
"lan"] ==
"zh"
else
"zh"
-
-
def
encryption_js(
self, word):
# 加密数据
-
with
open(
"baidufanyisign.js",
"r", encoding=
'utf-8')
as f:
# 读取js代码
-
js_code = f.read()
-
js_compile = execjs.
compile(js_code)
# 编译js代码
-
return js_compile.call(
"e", word)
# 调用js代码中e函数,传入参数word,返回sign值
-
-
def
save(
self, html_dict):
-
try:
-
print(
"翻译:" +
str(html_dict[
"dict_result"][
"simple_means"][
"word_means"]))
# 翻译单词:可以得到多个单词意思
-
except KeyError:
-
print(
"翻译:" +
str(html_dict[
"trans_result"][
"data"][
0][
"dst"]))
# 翻译句子
-
-
def
run(
self):
-
while
True:
-
word =
input(
"请输入一个单词或句子:")
-
if word ==
"!":
# 输入!退出程序
-
break
-
# 构造post请求头的数据
-
lang_post_data = {
"query": word}
-
# 构造url
-
lang_data = self.parse_url(self.lang_url, lang_post_data)
-
# 发送请求,获取语言类型
-
lang_from, lang_to = self.get_lang(lang_data)
-
# print("from:" + lang_from + "to:" + lang_to)
-
# 加密数据,获取sign值
-
sign = self.encryption_js(word)
-
# 构造翻译结果post请求头的数据
-
trans_post_data = {
"from": lang_from,
-
"to": lang_to,
-
"query": word,
-
"transtype":
"translang",
-
"simple_means_flag":
"3",
# 必须的参数。
-
"sign":
str(sign),
# 必须的参数。关键值:通过sign.js加密
-
"token":
"63671731f58420a45480f5badfff7b2c",
-
"domain":
"common"}
-
# 构造翻译url
-
self.trans_url.
format(lang_from, lang_to)
-
# 发送请求,获取翻译结果
-
html_dict = self.parse_url(self.trans_url, trans_post_data)
-
# 提取数据,输出
-
self.save(html_dict)
-
-
-
if __name__ ==
'__main__':
-
fanyi_spider = BaiDuFanYi()
-
fanyi_spider.run()
baidufanyisign.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)
-
}
-
-
console.
log(
e(
"爬虫"))
运行:
可以实现中英互译,并且可以支持翻译中英文句子。