ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

有道翻译——JS解密

2021-02-22 00:00:34  阅读:371  来源: 互联网

标签:youdao salt 有道 解密 JS data fanyi sign com


爬虫兴起的同时,反爬虫手段也在不断更新,今天以有道翻译http://fanyi.youdao.com/为例,介绍破解JavaScript加密的反爬虫基本流程。

分析网页

我们进入网站,随便输入一个内容(比如spider),会在network的XHR下发现一个translate开头的动态加载文件,查看一下它的标头:

在这里插入图片描述

这是一个POST请求,URL为http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule。再看一下响应:

在这里插入图片描述

可以惊喜的发现这个请求的响应恰好就是我们要的东西,那直接获取这个URL的响应内容解析一下不就行了?不妨先试一试:

import requests


url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    'Connection': 'keep-alive',
    'Content-Length': '240',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'OUTFOX_SEARCH_USER_ID=-1655056227@10.108.160.102; JSESSIONID=aaaLbl1vQGP7LaMN6GeFx; OUTFOX_SEARCH_USER_ID_NCOO=516404572.3890775; ___rl__test__cookies=1613910186738',
    'Host': 'fanyi.youdao.com',
    'Origin': 'http://fanyi.youdao.com',
    'Referer': 'http://fanyi.youdao.com/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68',
    'X-Requested-With': 'XMLHttpRequest'
}

data = {
    'i': 'spider',
    'from': 'AUTO',
    'to': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '16139101867430',
    'sign': 'b5b2bfdc381df9c9b104a03f2244bdaf',
    'lts': '1613910186743',
    'bv': 'a68be4fa7a0372e7ae83662b495a6f4c',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_REALTlME'
}

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

print(req.text)

查看一下运行结果:

在这里插入图片描述

嗯哼,这不是已经获取到了我们需要的结果了吗!!!难道今天就要到此为止了?

想一想我们要写这样一个脚本的初衷是什么?当然是为了想输入什么内容就能得到想要的信息,而不是仅仅获取一个spider的含义。不妨将data里面的'i': 'spider'换成'i': 'translate',,查看一下translate是什么意思。

import requests


url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    'Connection': 'keep-alive',
    'Content-Length': '240',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'OUTFOX_SEARCH_USER_ID=-1655056227@10.108.160.102; JSESSIONID=aaaLbl1vQGP7LaMN6GeFx; OUTFOX_SEARCH_USER_ID_NCOO=516404572.3890775; ___rl__test__cookies=1613910186738',
    'Host': 'fanyi.youdao.com',
    'Origin': 'http://fanyi.youdao.com',
    'Referer': 'http://fanyi.youdao.com/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68',
    'X-Requested-With': 'XMLHttpRequest'
}

data = {
    'i': 'translate',
    'from': 'AUTO',
    'to': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': '16139101867430',
    'sign': 'b5b2bfdc381df9c9b104a03f2244bdaf',
    'lts': '1613910186743',
    'bv': 'a68be4fa7a0372e7ae83662b495a6f4c',
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_REALTlME'
}

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

print(req.text)

查看一下运行结果:

在这里插入图片描述

emmm,刚才还是好好的,现在为什么就返回不到信息了呢?事实上,有道翻译是存在JS加密的,这是一个比较高级的反爬虫手段。其中的奥妙就在我们“看不懂”的那些参数里面,什么salt,sign,lts等等。所以下面要做的就是弄懂那些看不懂的数据。

JS加密破解

JS加密,顾名思义就是通过JavaScript脚本来实现加密。既然是JS加密,那必然存在js文件啊,我们可以在网页源代码里面找一找。

在这里插入图片描述

网页源代码里面有三个js文件。我们猜测一下我们需要的js文件是第二个。访问http://shared.ydstatic.com/api/fanyi-web/assets/index.min.js看一看是不是真的是这个文件。

在这里插入图片描述

好吧,这个页面被“丑化”过了,我们百度使用JS美化将它美化一下:

在这里插入图片描述

现在的代码还是不太方便查看,我们不妨将它复制到Sublime Text中,点击右下角的plain text,选择JavaScript,这样代码就高亮了。

在这里插入图片描述

好了,我们可以通过Ctrl+F发现salt,sign,lts这几个字符串都不在这个文件里面,所以这个文件大概率不是所需文件。

再查看一下第三个,使用同样的方法,真的在这个js文件里面找到了这几个字符串。所以这个文件正是我们所需要的,现在开始分析这个文件。

我们的出发点是破解salt,sign等几个键的含义,关注点也必然要放在js文件里面的这几个字符串上。不断通过Ctrl+F查找salt,会发现下面的代码:

在这里插入图片描述

这个data的格式不就是我们POST请求是传入data的格式吗?我们分析一下这几个键值对的含义。

猜测含义
i我们输入的待翻译内容
client前面已得知是’fanyideskweb’
salt未知
sign未知
ts(lts)未知
bv未知
from可以自行设置,默认为AUTO自动识别
to可以自行设置,默认为AUTO自动识别
tgt未知,但是请求时貌似不需要这个参数

因此,可以认为需要破解的参数就是salt,sign,ts,bv这四个,可能外加一个tgt,也正是这几个参数导致了爬虫的不成功。继续分析,会发现下面的代码:

在这里插入图片描述

salt就是时间戳加上一个0~10之间的随机整数,ts是字符串格式的时间戳。但是现在不知道这个e是什么,所以无法确定sign。

继续分析bv和sign,会发现下面的代码:

在这里插入图片描述

也就是说我们最终关注的内容将是generateSaltSign(n)函数,或者说是这个r。

这个r我们在上面的分析中看到过,在前一个图片中就有,当时我们不知道e是什么,现在对比一下我们得知了e就是输入的待翻译的内容,由此可以知道sign=md5("fanyideskweb" + 待翻译的内容 + salt的内容 + "Tbh5E8=q6U3EXe+&L[4c@")

最后只剩下bv了,bv=n.md5(navigator.appVersion),我们在控制台里面输入navigator.appVersio会发现其实它是我们所用浏览器的版本号。

在这里插入图片描述

总结一下四个参数的内容:

参数内容
salt时间戳加上一个0~10之间的随机整数
ts(lts)字符串格式的时间戳
signmd5(“fanyideskweb” + 待翻译的内容 + salt的内容 + “Tbh5E8=q6U3EXe+&L[4c@”)
bvmd5(所用浏览器的版本号),这是固定的

对应的python代码:

import hashlib
import random
import time

i = input('请输入要翻译的内容:')
salt = str(time.time()*1000)   # JS中的时间戳是毫秒级的,time.time()的时间戳是秒级的
lts = salt + str(random.randint(0,10))
# hashlib.md5()里面传入的内容必须是bytes格式,所以默认为unicode格式的字符串要做一个转换
temp1 = "fanyideskweb" + i + salt + "Tbh5E8=q6U3EXe+&L[4c@"
sign = hashlib.md5(temp1.encode('utf-8')).hexdigest()
temp2 = "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68"
bv = hashlib.md5(temp2.encode('utf-8')).hexdigest()

我们再运行下列代码试试:

import requests
import hashlib
import random
import time



url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    'Connection': 'keep-alive',
    'Content-Length': '240',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'OUTFOX_SEARCH_USER_ID=-1655056227@10.108.160.102; JSESSIONID=aaaLbl1vQGP7LaMN6GeFx; OUTFOX_SEARCH_USER_ID_NCOO=516404572.3890775; ___rl__test__cookies=1613910186738',
    'Host': 'fanyi.youdao.com',
    'Origin': 'http://fanyi.youdao.com',
    'Referer': 'http://fanyi.youdao.com/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68',
    'X-Requested-With': 'XMLHttpRequest'
}

i = input('请输入要翻译的内容:')
salt = str(time.time()*1000)   # JS中的时间戳是毫秒级的,time.time()的时间戳是秒级的
lts = salt + str(random.randint(0,10))
# hashlib.md5()里面传入的内容必须是bytes格式,所以默认为unicode格式的字符串要做一个转换
temp1 = "fanyideskweb" + i + salt + "Tbh5E8=q6U3EXe+&L[4c@"
sign = hashlib.md5(temp1.encode('utf-8')).hexdigest()
temp2 = "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68"
bv = hashlib.md5(temp2.encode('utf-8')).hexdigest()

data = {
    'i': i,
    'from': 'AUTO',
    'to': 'AUTO',
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': salt,
    'sign': sign,
    'lts': lts,
    'bv': bv,
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_REALTlME'
}

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

print(req.text)

运行结果:

在这里插入图片描述

我们已经实现了JS破解,剩下的内容就是解析响应的内容了,这里就不再赘述,直接上全部代码:

#-*- coding = utf-8 -*-
# @Time: 2021/2/19 11:01 
# @Auther: 卫佳
# @File: 测试.py
# @Software: PyCharm

import requests
import hashlib
import random
import time



url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"

headers = {
    'Accept': 'application/json, text/javascript, */*; q=0.01',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
    'Connection': 'keep-alive',
    'Content-Length': '240',
    'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'OUTFOX_SEARCH_USER_ID=-1655056227@10.108.160.102; JSESSIONID=aaaLbl1vQGP7LaMN6GeFx; OUTFOX_SEARCH_USER_ID_NCOO=516404572.3890775; ___rl__test__cookies=1613910186738',
    'Host': 'fanyi.youdao.com',
    'Origin': 'http://fanyi.youdao.com',
    'Referer': 'http://fanyi.youdao.com/',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68',
    'X-Requested-With': 'XMLHttpRequest'
}

i = input('请输入要翻译的内容:')
salt = str(time.time()*1000)   # JS中的时间戳是毫秒级的,time.time()的时间戳是秒级的
lts = salt + str(random.randint(0,10))
# hashlib.md5()里面传入的内容必须是bytes格式,所以默认为unicode格式的字符串要做一个转换
temp1 = "fanyideskweb" + i + salt + "Tbh5E8=q6U3EXe+&L[4c@"
sign = hashlib.md5(temp1.encode('utf-8')).hexdigest()
temp2 = "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.68"
bv = hashlib.md5(temp2.encode('utf-8')).hexdigest()

data = {
    'i': i,
    'from': 'zh-CHS',    # 设置成中文
    'to': 'en',        # 设置成英文
    'smartresult': 'dict',
    'client': 'fanyideskweb',
    'salt': salt,
    'sign': sign,
    'lts': lts,
    'bv': bv,
    'doctype': 'json',
    'version': '2.1',
    'keyfrom': 'fanyi.web',
    'action': 'FY_BY_REALTlME'
}

req = requests.post(url,headers=headers,data=data)
resp = req.json()
if "translateResult" in resp:
    translateResult = resp["translateResult"][0][0]["tgt"]
    print('translateResult = %s'%translateResult)
if "smartResult" in resp:
    print('smartResult = ', end='')
    smartResult = resp["smartResult"]["entries"]
    for i in smartResult:
        if i:
            r = i.strip('\n').strip('\r')
            print(r,end='\t')

测试几个结果:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

祝愿看到这里的人变得越来越强,再会~~~

标签:youdao,salt,有道,解密,JS,data,fanyi,sign,com
来源: https://blog.csdn.net/weixin_44141520/article/details/113926162

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有