python爬百度翻译-爬虫 python爬取百度翻译接口 超详细附源码

前言

今天教大家如何利用 firefox 分析百度翻译的接口,并用python爬取接口。大家学会后可以干一些有趣的事情,比如做一个自己的翻译软件。

bbcc857dff3e492b877aef8696c80295

90cae3fda0514a929528905b247330de

具体内容

1 - 找到URL接口

进入百度翻译的网址,F12进入调式模式,点击Network,选择XHR

409c80ebe8624eb5bb1cf7ca04d5ab28

点击网页上的 翻 译我们会看见,多了两个XHR记录,这两个记录就是请求服务器获取翻译结果的请求。

e181ab3879254683aac25545c8f9c82d

我们点击第二条查看,点击Response (服务器返回的数据), 可以看见这个连接返回的东西就是我们想要的数据。接下来我们获取这个请求的url,模拟发送请求试试。

868809b8a0b54d44ac899011235a4848

2 - 分析参数

我们可以看到这个记录请求的url便是图上这个,方法是post。我们接下来查看请求的参数

a33370203e644f9e894a70f51097c25e

这个便是我们请求的参数了,可以看见有from:原语言 ,to:翻译的语言,query:翻译的字符串,

然后是transtype:翻译类型,simple_means_flag:意思尚不清楚,不过不重要,sign:这个我们后面在解释,token:这个是用来识别浏览器的,知道这些参数之后我们就可以开始写代码了。

7909a0e62ce64a96bbae6ba09a930486

2 - 写代码

import requests

url = "https://fanyi.baidu.com/v2transapi"

headers = {

'User-Agent':

'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'

}

queryString = "人生苦短,我用python"

data = {

'from': 'en',

'to': 'zh',

'query': queryString,

'simple_means_flag': 3,

'sign': "289133.35420",

'token': "2876e8473cf85fcd7fc00daf00aa0551",

}

r = requests.post(url, data, headers=headers)

print(r.text)

运行结果如下如

ae1ab97b48e84515b70ed815da6afecc

结果并没有出现我们想要的数据,并返回

错误997:sign值不对

其实这是因为百度翻译做了反爬处理,上述传过去的sign的值是js动态生成的,随时变化的。那么,目前有两个方案,一是通过手机百度翻译的接口爬取,因为手机端的翻译不需要传入sign值。二是通过分析js源码,得到这个sign值得生成方法,然后自己生成sign值。第一个方案目前百度有很多例子,我就不讲了,我主要讲讲第二个方案。

获取sign得生成方法,我们可以看看js代码

function a(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

}

var C = null;

var token = function(r, _gtk) {

var o = r.length;

o > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(o / 2) - 5, 10) + r.substring(r.length, r.length - 10));

var t = void 0,

t = null !== C ? C: (C = _gtk || "") || "";

for (var e = t.split("."), h = Number(e[0]) || 0, i = Number(e[1]) || 0, d = [], f = 0, g = 0; g < r.length; g++) {

var m = r.charCodeAt(g);

128 > m ? d[f++] = m: (2048 > m ? d[f++] = m >> 6 | 192 : (55296 === (64512 & m) && g + 1 < r.length && 56320 === (64512 & r.charCodeAt(g + 1)) ? (m = 65536 + ((1023 & m) << 10) + (1023 & r.charCodeAt(++g)), d[f++] = m >> 18 | 240, d[f++] = m >> 12 & 63 | 128) : d[f++] = m >> 12 | 224, d[f++] = m >> 6 & 63 | 128), d[f++] = 63 & m | 128)

}

for (var S = h,

u = "+-a^+6",

l = "+-3^+b+-f",

s = 0; s < d.length; s++) S += d[s],

S = a(S, u);

return S = a(S, l),

S ^= i,

0 > S && (S = (2147483647 & S) + 2147483648),

S %= 1e6,

S.toString() + "." + (S ^ h)

}

函数token便是我们需要得sign值得生成方法。在python中调用js需要用到execjs 库。请同学们自己去安装一下pip install execjs。

我们可以看到这个js token 函数需要传入两个值queryString 和 gtk。那么什么是gtk呢?我们去源码里看看。

我们可以输入百度翻译的网址查看源码,crtl+f 搜索 gtk,可以得到一条记录

window.gtk = '320305.131321201'

那么我们在调用翻译接口之前,得请求百度翻译html,然后用正则匹配gtk这个值,改改我们得代码再试一试。

407904c09d834699a80925c3ff156fa9

为了简便我们把代码封装成函数

27d463c06a1d4e4fb125761f2ddf5375

我们运行看看

1241660c30584a198bb4589ce19a967f

出现了{"error":998,"from":"zh","to":"en","query":"\u4f60\u597d"}

998错误是为什么呢?

998错误:token值不对

我们刚才看过了传过去的参数有个token,其实token也是根据浏览器动态生成的,不过这个和gtk 一样,在html 源码可以使用正则表达式找到

dbdffe904f2e4c2c930e3237779de613

我们在更新一下我们的程序,将get_gtk重构了一下,编程get_params

b217394097764aa8bc576f11c3067fb8

运行看看

084c39cacd7448149382fc732e58f696

我们可以看到还是

998 错误

???这是为什么呢(黑人问号脸)

有大神说了,这样的token不是最新的,我们得加载两次首页才行。我们在改一次代码吧

f0f198531ac5420a97fd18ec87a92abd

只需要运行两次get_params() 访问两次首页,然后token和gtk去第二次的值就行了我们的结果也出现了! 搞了这么久,终于成功了!是不是有点激动呢。。。返回的结果是一个json格式的,我们只需要提取里面的信息就行了。

c29a6e8e3cbd4f069d3a7ed7bff1b1a8

最后我们将这个程序用类封装一下:

bd30e45fc45a4a4c9756330f1dd613f3

这个我的字典程序就弄好了!

源码给大家

import requests.sessions

import re

import execjs

class BaiDuFanYi():

def __init__(self):

self.homeUrl = "https://fanyi.baidu.com/"

self.transUrl = "https://fanyi.baidu.com/v2transapi"

self.headers = {

'User-Agent':

'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'

}

self.gtk = None

self.token = None

self.s = requests.Session()

self.get_params()

self.get_params()

def get_sign(self, query_string):

JS_CODE = """

function a(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

}

var C = null;

var token = function(r, _gtk) {

var o = r.length;

o > 30 && (r = "" + r.substr(0, 10) + r.substr(Math.floor(o / 2) - 5, 10) + r.substring(r.length, r.length - 10));

var t = void 0,

t = null !== C ? C: (C = _gtk || "") || "";

for (var e = t.split("."), h = Number(e[0]) || 0, i = Number(e[1]) || 0, d = [], f = 0, g = 0; g < r.length; g++) {

var m = r.charCodeAt(g);

128 > m ? d[f++] = m: (2048 > m ? d[f++] = m >> 6 | 192 : (55296 === (64512 & m) && g + 1 < r.length && 56320 === (64512 & r.charCodeAt(g + 1)) ? (m = 65536 + ((1023 & m) << 10) + (1023 & r.charCodeAt(++g)), d[f++] = m >> 18 | 240, d[f++] = m >> 12 & 63 | 128) : d[f++] = m >> 12 | 224, d[f++] = m >> 6 & 63 | 128), d[f++] = 63 & m | 128)

}

for (var S = h,

u = "+-a^+6",

l = "+-3^+b+-f",

s = 0; s < d.length; s++) S += d[s],

S = a(S, u);

return S = a(S, l),

S ^= i,

0 > S && (S = (2147483647 & S) + 2147483648),

S %= 1e6,

S.toString() + "." + (S ^ h)

}

"""

return execjs.compile(JS_CODE).call('token', query_string, self.gtk)

def get_params(self):

r = self.s.get(self.homeUrl, headers=self.headers)

self.gtk = re.findall(r"window.gtk = '(.*?)';", r.text)[0]

self.token = re.findall(r"token: '(.*?)',", r.text)[0]

def translate(self, query_string):

sign = self.get_sign(query_string)

data = {

'from': 'zh',

'to': 'en',

'query': query_string,

'simple_means_flag': 3,

'sign': sign,

'token': self.token,

}

res = self.s.post(url=self.transUrl, data=data, headers=self.headers)

return res.json()['trans_result']['data'][0]['dst']

if __name__ == '__main__':

words = input("请输入原文: ")

mydict = BaiDuFanYi()

print(f"翻译结果是: {mydict.translate(words)}")

总结

百度翻译错误

997 : sign值不对(动态生成js)

998: token值不是最新的或者没有(一般需要获取两次,取最第二次)

6f51448d149c46ebb7d418d200882132

  • 7
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值