python 百度翻译爬虫(可翻译句子及文章)(偷偷说一句,保姆级教程哦)

  • 声明:本文 仅限爬虫学习 ,不得 将本文代码商用侵权删
  • 如果喜欢本文的话,可不可以给我 点个关注点个赞评论 + 收藏 (☆▽☆)

创作背景

  • 本菜鸡最近要整个 批量翻译词组和句子 ,准备调用 百度翻译 的接口,以前也搞过,用的 这个接口,但是只能 翻译单词 ,没法满足需求,所以就需要重新搞。
  • 其实以前我就对 这个接口 念念不忘,但是因为当时啥也不会(虽然现在也是),为了图省事儿就没搞,今天 必须拿下 !!!

思路讲解

本文 js 逆向 参考 这个大佬的这篇文章

第一步 寻找接口

无非是 按 F12 打开开发者工具寻找对应的接口 ,具体情况在此不多赘述。

第二步 查看参数

该请求是 POST 请求。

插入图片描述
其中

  • from 参数是 源语言 ,即 被翻译的文本的语言
  • to 参数是 目标语言 ,即 要翻译成的语言
  • query 参数是 要翻译的文本
  • transtype 参数是 翻译类型 ,置为 translang 即可;
  • simple_means_flag 参数不知道干啥,不用管,置为 3 即可;
  • sign 参数是 标志 ,代表 要翻译的内容的标志号 ,生成方法见后续;
  • token 参数是 记号 ,每次请求网页源码都会携带 token ,见下图;
    在这里插入图片描述
  • domain 也不用管,置为 common 即可。

第三步 构造 sign

因为 sign 参数是根据 要翻译的文本 生成的,不同的内容对应不同的 sign ,所以我们需要找到生成 sign 的方法。

1. 找到生成 sign 的文件

这时,我们需要使用 全局搜索 查找生成 sign 的地方,如下图。
在这里插入图片描述

  • 每个文件大致看一遍,我就确认了 sign 生成的函数在 这个文件 中。
    • 这个文件地址和上述博主文章中的地址不太一样,是因为我想根据我自身的情况实际实践一下,当然,也可以直接使用博主文章中的地址,如果你想看看自己本地的文件,去找 https://fanyi-cdn.cdn.bcebos.com/static/translation/pkg 这个文件夹,我用的 火狐 ,在 调试器 中可以找到
      在这里插入图片描述
    • 然后找到图中的的文件,文件名取决于 全局搜索 的结果,我的结果是这个,至此,这一步结束。
2. 找到生成 sign 的函数

上一步 copy 完代码后,我放入 Pycharm 中分析,当然,也可以放到其他编辑器中。
这时,还是 全局搜索 sign ,会搜索出很多 assign 或者 signal ,所以我们需要甄别一下,甄别过后,包含有 sign 的地方有 处,如下图。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
根据图中代码我们很好判别,第一张第二张 图属于一类,代码逻辑相似,第三张图第四张图 类似,所以我们就分析 第一张第三张 的代码。

第一张图片

Pycharm 编辑器中,我们按住 ctrl 点击 d (因为这时候 sign 是根据 d 生成的),我们就跳转到 d 定义的位置了。
在这里插入图片描述可以看见,是根据函数 n 传参 s 得到,而 s 是函数 t 传参一大堆生成,点击 t 的话,如下图。
在这里插入图片描述匿名函数 的参数,如果全局搜索 传递给函数 t 的一大堆的参数 的话也发现不了什么,所以,这条线索 断了

第二张图片

我们同样是点击 L ,就跳转到了 L 的生成位置,如下图。
在这里插入图片描述
这时我们再搜索函数 t 的参数,如下图。
在这里插入图片描述
这时我们会发现有这个模块的定义,其中,define 函数的解释请见 这篇文章
说明,模块 translation:widget/translate/input/pGrab 即为生成 sign 的模块。也 符合上述博主的文章

3. 分析生成 sign 的函数

通过分析源码,我们可以了解代码逻辑,其中,u 是最终生成 sign 的关键。
不过有个问题,我们看 u 的生成方法:

u = null !== i ? i : (i = window[l] || "") || "";

其中,i 很好得到,因为这个函数下边有 i 的定义:

var i = null;

这样的话,那按照代码逻辑,上边 u 的定义应该是这样:

u = (i = window[l] || "") || ""; 

这时候,关键就在于参数 ll 的定义在上一句:

var u = void 0, l = "" + String.fromCharCode(103) + String.fromCharCode(116) + String.fromCharCode(107);

l 是个字符串,通过 console.log() 输出一下 l 的值,是
在这里插入图片描述

  • 对了,插一句,在 Pycharm 中运行 js 代码应该安装 Nodejs ,稍后我会专门写一篇文章。
    我们在 Pycharm 中无法查看 window 的值,所以我们就在浏览器的控制台输入 window ,查看它的值:
    在这里插入图片描述
    诶,还真被我找到了值,那我们就可以把这个值赋给 i ,这样 u 直接就是 i ,也就是图中的数据。
4. 使用生成 sign 的函数

既然只有这个函数是对我们来说有用的,那就把它 copy 到一个 js 文件中,使用 python 的第三方库 execjs 执行 js 代码,即:

var i = "320305.131321201";

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) {
    var o = r.match(/[�-�][�-�]/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(/[�-�][�-�]/), 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);
    console.log("l:", l);
    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)
}

既然有函数,那我们就不必具体分析,直接用就好了。
测试一下:
在这里插入图片描述
在这里插入图片描述
一模一样!!!
使用 execjs 测试,测试代码如下:

import execjs

with open('sign.js', encoding='utf-8') as f:
    js_code = f.read()
create_sign = execjs.compile(js_code)
print(create_sign.call('e', 'year'))

在这里插入图片描述
成功!!!

第四步 进行翻译

请求的时候有 反爬,所以 CookieUser-Agent 一个都不能少,代码如下:

import json
import execjs
import requests

with open('sign.js', encoding='utf-8') as f:
    js_code = f.read()
    
create_sign = execjs.compile(js_code)

def translate(kw):
    data = {
        'from': 'en',
        'to': 'zh',
        'query': kw,
        'transtype': 'translang',
        'simple_means_flag': 3,
        'sign': create_sign.call('e', kw),
        'token': '【用自己的】',
        'domain': 'common'
    }
    headers = {
        'Cookie': '【用自己的,别想白嫖我的】',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:80.0) Gecko/20100101 Firefox/80.0'
    }
    res = requests.post('https://fanyi.baidu.com/v2transapi?from=en&to=zh', data=data, headers=headers)
    print(res.json())
    
translate('year')

结果如下:
在这里插入图片描述
特别多,我们只要想要的数据,一般是 data 列表中的 第一个数据

print(res.json()['trans_result']['data'][0])

结果如下:
在这里插入图片描述
成功完成任务!!!

一些问题的解决

总结

这是本菜鸡 第一次 成功的完成 js 逆向逆向 之路,道阻且跻,但我仍要不断前行。




结尾

有想要一起学习 python 的小伙伴可以 私信我 进群哦。

以上就是我要分享的内容,因为学识尚浅,会有不足,还请各位大佬指正。
有什么问题也可在评论区留言。
在这里插入图片描述

  • 19
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 22
    评论
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值