破解有道字典查询JS加密算法:
基础知识:
一般的网页爬虫,都有三个阶段的爬虫难度:
第一:是直接通过已经渲染好的HTML代码爬取内容;
第二:是通过抓包的方式获取ajax异步加载的json数据格式
第三:就是通过加密的js参数来破解加密的js文件来爬取数据
分析网页:
- 通过监视查询的提交过程的抓包可知:网页是通过如下网址,通过
POST
的提交方式查询的:
http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule
- 并且提交以下一系列的表单元素:
- 通过分析可知:除
salt
和sign
和查询内容i
之外所有的参数都是固定不变的;因此需要得到这个两个参数的变化的值;
加密参数的产生一种是由客户端产生并提交给服务器的,另一种是由服务器产生然后赋予给客户端,例如cookie
- 在分析网页无其他特殊请求之后,参数的产生即为
js
加密生成的参数;在网页的源代码中搜索.js
,查找引用的js
文件:
- 在如上的
http://shared.ydstatic.com/api/fanyi-web/assets/index.min.js
的js
文件中存在salt
和sign
的生成过程,用站长工具-在线代码格式化将经过简化的js
代码文件格式化分析js
代码;
分析JS文件:
在经过格式化的js文件中找到如下代码段:
...
function(e, t) {
var n = e("./jquery-1.7"),
r = e("./utils");
e("./md5");
var i = r.deEight("rY0D^0'nM0}g5Mm1z%1G4"),
o = "" + ((new Date).getTime() + parseInt(10 * Math.random(), 10));
t.recordUpdate = function(e) {
var t = e.i,
r = n.md5("fanyideskweb" + t + o + i);
n.ajax({
type: "POST",
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
url: "/bettertranslation",
data: {
i: e.i,
client: "fanyideskweb",
salt: o,
sign: r,
tgt: e.tgt,
modifiedTgt: e.modifiedTgt,
from: e.from,
to: e.to
},
...
1.分析salt参数:
- 可以找到
salt
参数是被o
参数定义,也就是被如下定义:
o = "" + ((new Date).getTime() + parseInt(10 * Math.random(), 10));
- 事实上参数
o
就是毫秒格式的时间戳类型并且加上一个0~10的随机数
2.分析sign参数:
-
sign
参数被r
参数定义,接受四个参数并采用md5
的加密算法:
r = n.md5("fanyideskweb" + t + o + i)
...
sigh = r
参数
fanyideskweb
为固定参数参数
t
即i
,为用户查询的内容字符串参数
o
即为salt
参数
deEight: function(e) {
var t, n = new Array,
r = e.split("\\");
if (1 == r.length) return r[0];
for (t = 1; t < r.length; t++) n += String.fromCharCode(parseInt(r[t], 8));
return e = n
},
- 参数
i
被属性定义:var t = r.deEight("rY0D^0'nM0}g5Mm1z%1G4")
,在JS
的文件当中,找到deEight
方法;方法的作用就是去除\\
的符号,当传入的固定值为rY0D^0'nM0}g5Mm1z%1G4
,返回的值依然是这个
破解加密:
1.生成一个毫秒的timestamp的参数:
- 在
Python
中生成一个这样的参数类型:
improt random
improt time
...
timestamp = int(time.time()*1000) + random.randint(0,10)
...
2.通过md5
的解密算法获得sign参数:
import hashlib
...
u = 'fanyideskweb'
o = 'hello'
a = str(timestamp)
t = "rY0D^0'nM0}g5Mm1z%1G4"
sign = hashlib.md5((u+o+a+t).encode('utf-8')).hexdigest()