谷歌翻译-爬虫-JS解密

测试了下,并没有完全跟网页中一致,只是有输入单词的翻译,没有联想、词性等

嗯,等以后看看再优化吧!
现在就直接看代码吧。

目标地址(谷歌翻译国内)

# google_fy.py
from urllib import parse
import requests
import execjs


def get_tk(q: str):
    with open('google_fy.js', 'r', encoding='utf-8') as f:
        JS = f.read()
    j = execjs.compile(JS)
    return j.call('zo', q).replace('&tk=', '')


class Translate(object):
    def __init__(self):
        self.headers = {
            'referer': 'https://translate.google.cn/',
            # 'sec-fetch-mode': 'cors',
            # 'sec-fetch-site': 'same-origin',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36',
            # 'x-client-data': 'CIe2yQEIpLbJAQjBtskBCKmdygEI4qjKAQjKr8oBCJywygEIzrDKARj1sMoB'
        }
        # self.session = requests.session()


class GoogleTranslate(Translate):
    def __init__(self, q: str):
        super().__init__()
        url = 'https://translate.google.cn/translate_a/single'
        data = {'client': "webapp", 'sl': 'auto', 'tl': 'zh-CN', 'hl': 'zh-CN', 'dt': 'at', 'otf': '2', 'ssel': '3',
                'tsel': '0', 'kc': '1', 'tk': get_tk(q), 'q': q}
        url = url + '?' + parse.urlencode(data)
        print(url)
        response = requests.get(url, headers=self.headers)
        print(response.text)


GoogleTranslate('Agent')

JS 代码

<!-- google_fy.js -->
var vo = function (a, b) {
    try {
        return JSON.parse(a)
    } catch (d) {
        var c = Im.M();
        b.js = a;
        b.error = d.message;
        c.log("jsonParseErr", b);
        throw d;
    }
};
var wo = function (a) {
        return function () {
            return a
        }
    },
    xo = function (a, b) {
        for (var c = 0; c < b.length - 2; c += 3) {
            var d = b.charAt(c + 2);
            d = "a" <= d ? d.charCodeAt(0) - 87 : Number(d);
            d = "+" === b.charAt(c + 1) ? a >>> d : a << d;
            a = "+" === b.charAt(c) ? a + d & 4294967295 : a ^ d
        }
        return a
    },
    yo = '436280.2672482813',
    zo = function (a) {
        var b = yo;

        var d = wo(String.fromCharCode(116));
        c = wo(String.fromCharCode(107));
        d = [d(), d()];
        d[1] = c();
        c = "&" + d.join("") + "=";
        d = b.split(".");
        b = Number(d[0]) || 0;
        for (var e = [], f = 0, g = 0; g < a.length; g++) {
            var k = a.charCodeAt(g);
            128 > k ? e[f++] = k : (2048 > k ? e[f++] = k >> 6 | 192 : (55296 === (k & 64512) && g + 1 < a.length && 56320 === (a.charCodeAt(g + 1) & 64512) ? (k = 65536 + ((k & 1023) << 10) + (a.charCodeAt(++g) & 1023), e[f++] = k >> 18 | 240, e[f++] = k >> 12 & 63 | 128) : e[f++] = k >> 12 | 224, e[f++] = k >> 6 & 63 | 128), e[f++] = k & 63 | 128)
        }
        a = b;
        for (f = 0; f < e.length; f++) {
            a += e[f];
            a = xo(a, "+-a^+6");
        }
        a = xo(a, "+-3^+b+-f");
        a ^= Number(d[1]) || 0;
        0 > a && (a = (a & 2147483647) + 2147483648);
        a %= 1E6;
        return c + (a.toString() + "." + (a ^ b))
    };

分析过程:按F12 -> network -> 输入待翻译内容,应该直接就能看到响应。
在这里插入图片描述
下面是具体参数,我是在键入不同词翻译 对比参数发现,大部分参数都是固定的。主要就是【tk】这个参数。没换一个词 tk 就会有变化。
那么接下来的工作主要就是找到 tk 赋值或则加密的地方了。
在这里插入图片描述
复制响应URL(不带参数的)
进入Sources界面 按照下图操作,将上一步URL 添加到断点。这里是设置浏览器在请求该网址之前暂停,进入调试状态。
在这里插入图片描述
然后就回到翻译输入框中键入想翻译的内容。

可以看到下图中间就是js代码了。不过代码全都集中在一起(我这里是点击了格式化代码按钮 【一对大括号】在截图左下角 line处)。
这里简单说明下吧,暂停处就是即将发送请求的地方(看到send应该就懂了),
图右边函数调用栈就是在运行到暂停处之前调用的函数。
函数调用栈框里,函数调用过程是下面的调用上面的,依此类推。
在这里插入图片描述
既然这样就可以看看整个调用栈中 具体在哪一步对参数进行加密了。
从上开始往下看吧,点击调用栈处下一个函数。
在这里插入图片描述
经过观察后,我发现在Sj 函数即将return的时候。是可以看到 k.send(a, c ,d ,e) 中的 a 就是URL中的参数。并且 a 中就有 tk 。

a = "/translate_a/single?client=webapp&sl=auto&tl=zh-CN&hl=zh-CN&dt=at&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&clearbtn=1&otf=1&ssel=0&tsel=3&kc=2&tk=687182.840818&q=open"

非常棒,已经找到入口了。
接下来 再往下看 。直到在函数中的参数没有发现 tk 为止。因为只有上一个函数没有 tk 但是后面一个函数中又出现了 tk ,这才能确定 tk 是在哪个函数中添加到URL参数中的。

经过一些排查后确定 wp函数并没有 出现 tk ,而 tp 中则有 tk。
下图最下方调用 tp 函数传递的 r 就是URL,但这个并没有包含任何参数。
在这里插入图片描述
上图 于 下图对比 发现 tp 接收的第二个参数 本来是没有带参数的,而到了 tp 运行完后要调用 Sj 的时候 tp 第二个参数 多了很多内容。
在这里插入图片描述
在 tp 进入后第一行、最后一行 添加断点, 将其他断点移除。从新调试,当停在tp函数内后,就要小心点了最好用步进,避免错过了。
在这里插入图片描述
可以看到上图中就已经有 tk 的值了,是 sp(d)获取的。
一直深入下去就找到 tk 以及其他参数的根源在哪了。
tk 加密的则是在 sp(d)函数中调用的 zo(q)函数中。
在这里插入图片描述
经过调试上面 zo 函数,并定义一些固定值 就形成了文章开头部分的JS代码。
完!!!
第一次写博客,排版随意弄的,请见谅!!!

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值