python 爬虫js加密(一)之破解有道翻译(超详细)
绪论
- 本文献给那些初学js破解的小伙伴,本人在刚刚开始学习js破解时也是一头雾水,使用浏览器调试都不会,网上调试资源又欠缺,走了很多弯路,今天恰巧兴起接触有道,所以写一篇文章帮助那些不了解js破解流程的小伙伴,同时也帮助自己更好的总结
一、分析网页
- 打开有道翻译网页 并按F12进入开发者模式
- 输入要翻译的内容 你好 查看提交的表单,检查发现提交了一个post表单数据,这个相应中返回了我们翻译的结果 hello
- 接着找到消息头观察发现请求地址为 http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule 是post请求,于是找到post请求的参数
- 参数如下,通过多次请求并重复上面的检查步骤,我们发现了如下几个参数为重要参数
i:我们输入的关键字
salt与ts: 这么大长串的数字又是以1569***开头的推断为时间戳,或者时间戳经过一定的处理的字符串
sign与bv: 通过观察这两个参数均为32位的字符串,可以初步推断为md5加密的字符串,并且sign会经常变化,所以我们需要找到sign值的加密规则。
二、 破解js加密参数
- 找参数又两种方法,一种找到翻译按钮,通过浏览器调试一步一步找到加密规则,另一种是找到加密的js文件,进入文件中找到加密的代码。现在查看器中查看源代码,然后找到翻译按钮,返现这是一个js请求,单机冒泡发现是下面的这一段js代码执行的翻译,于是我们按照步骤进入到js文件中
- 进来后发现进入了fanyi.min.js文件中,是这个文件发送请求去翻译的,而我们观察发现这个js文件中只有一行很长的代码无法阅读,所有我们右键美化一下代码,便于我们观察(这就是火狐强大的地方)
- 美化源代码后我们现在就开始寻找我们要的sign这个关键字在哪里了,在键盘上按Ctrl + F 调出搜索框,然后在搜索框中输入sign按下回车搜索,搜索发现有11个符合要求的sign,通过寻找我们发现第二个sign发送了一个post请求,从而从服务器获取数据,而sign是o对象的一个属性,于是我们向上寻找,找到了生成o对象的地方,o对象是有一个generateSaltSign()方法生成的,现在这里打上三个断点,扥到以后调试用
4. 现在我们就要找到generateSaltSign方法在js中的位置,于是我们全局搜索这个对象,同样的是按Ctrl + F,在搜索框中输入generateSaltSign按下回车,于是找到4个位置出现了这个方法,我们发现一个t.translate = function (e, t)这个方法中疑是翻译发送的方法,所以我们在下面分别打上3个断点,然后调试一波
- 在调试时新手在调试过程中容易混乱,再此做一下说明,了解调试后需要在搜索框中输入要翻译的单词,然后回车
- 回车后发现跳到了断点处我们点击步进按钮进入到函数内部,
- 进入后我们发现了下面这几段代码,发现了加密规则(这里笔者之前搜索sign时就应该发现了,之前已经在sign这里打上断点了,但是写了这么多了,偷个懒就不改了),分析代码可以发现t是使用md5加密的一个字符串"5.0 (Windows)",r是当前的时间戳(python中的 int(time.time()*1000) ), i是 r 加上0-10的整数,而这几个参数又分别对应了我们要找的参数,在图中可以看出
ts ----------> r
bv -----------> t
salt ------------> i
sign -----------> sign
- 这里我们已经发现了3个参数,就差一个sign了,而sign时通过md5加密的,使用到了一个变量e 和 i, 而 i 在上面我们发现其实就是当前时间戳加上0-9的一个整数,现在就差一个e了,于是我们在8313行打上断点继续调试,经过多次跨越调试后,我么将鼠标放到参数e上发现当前e是我们输入要翻译的单词,于是所有参数已经真相大白了,我们可以写python代码模拟这一个过程了。
三、python代码实现
def youdao(keyword):
"""
有道翻译
:param keyword: 需要翻译的单词
:return: 翻译的结果
"""
import requests
import time
import random
# 翻译的地址
url = "http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule"
# 伪装请求头
headers = {
'Host': 'fanyi.youdao.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate', 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest', 'Content-Length': '262', 'Connection': 'keep-alive',
'Referer': 'http://fanyi.youdao.com/',
'Cookie': 'YOUDAO_MOBILE_ACCESS_TYPE=1; OUTFOX_SEARCH_USER_ID=1378414660@10.108.160.19; JSESSIONID=aaaBTGxpwV4EQfnO_Oy1w; ___rl__test__cookies=1569154996426; OUTFOX_SEARCH_USER_ID_NCOO=752434577.0207007'
}
# 获取当前的时间戳,模仿js的(new Date).getTime()
ts = int(time.time()*1000)
# 构建salt参数
salt = ts + random.randint(0, 9)
# 构建bv参数(通过自定义的md5方法)
bv = md5("5.0 (Windows)")
# 构建sign参数(通过自定义的md5方法)
sign = md5(f'fanyideskweb{keyword}{str(salt)}n%A-rKaT5fb[Gy?;N5@Tj')
# 所有参数字典
data = {
"i": keyword,
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
"salt": salt,
"sign": sign,
"ts": salt,
"bv": bv,
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_CLICKBUTTION"
}
# 请求翻译
try
res = requests.post(url=url, headers=headers, data=data, timeout=10).json()
print(res.get("translateResult")[0][0].get("src"), "----->", res.get("translateResult")[0][0].get('tgt'))
return res.get("translateResult")[0][0]
except Exception as e:
print(f"抱歉有道翻译已经升级了!{e}")
return None
def md5(keyword):
"""
自定义的md5加密
:param keyword:待加密的字符串
:return: 加密后的32位字符串
"""
import hashlib
# 创建md5对象
m = hashlib.md5()
# 将字符串转为byte
b = keyword.encode(encoding='utf-8')
# 加密字符串
m.update(b)
# 获取加密结果(32位字符串)
str_md5 = m.hexdigest()
# 返回结果
return str_md5
if __name__ == '__main__':
data = youdao("你好")
print(data)
到这里有道的js已经完成了。