最近发现的一个爬虫练习网站,尝试着做了几道题,发现覆盖面很大,因此来记录分享一下自己的解题思路。
http://glidedsky.com/
JS加密
目标网址
打开开发者工具观察网络请求相应,发现该页面调用get方法传入参数得到的相应正是我们要获取的数据内容。
观察传参,发现三个参数:page,t,sign。page参数是请求的页数,t参数推测是一个时间戳,sign参数应该是加密后的参数,也就是本次的重头戏。
尝试在全局搜索了下t参数的值,但是有用的信息,直接搜索"sign"这个参数的英文名,
(这里可能需要开启反混淆设置,点击右上角的齿轮——勾选在匿名和脚本内容中搜索)
在列表中找到了疑似加密的函数,发现p,t,sign的获取方式都在这里了。
因为sign的加密涉及到了t参数,所以我们先观察t参数,
let t = Math.floor(($(‘main .container’).attr(‘t’) - 99) / 99);
$(‘main .container’).attr(‘t’)这个意思是从html页面container节点获取属性为t的值,尝试搜索下果然找到了这个t值。可以发现如果仅仅只有page一个参数的网页,不会携带有数据。
对我们要求的t值有两个方法:一是直接用execjs模拟js实现,二是使用python实现js的方法,这里我采用的是第一种方法,新建一个js文件,把这段代码写为一个函数,最后调用就能得到我们要求的t值。
//t.js
function get_t(t){
t= Math.floor((t - 99) / 99);
return t
}
对于sign参数的处理,
let sign = sha1(‘Xr0Z-javascript-obfuscation-1’ + t);
因为在复制它的js代码时会出现多层函数调用,而他这里的调用sha1函数只要不是自定义的加密函数的话,我们可以使用python中hashlib库来实现。经过对比发现,sha1函数正是安全哈希算法。
思路如下:
1.构造只带有page的请求,得到网页内容后,采用正则匹配到t的值,通过execjs调用获得加密后的t值
2.构造sign字符串,调用hashlib库函数实现加密
3.构造请求参数列表,发起请求得到数据。
实现代码
def crawler_javascript_obfuscation_1():
global sum
session=login()
for i in range(1,1001):
url='http://www.glidedsky.com/level/web/crawler-javascript-obfuscation-1?page={}'.format(i)
print(url)
req=session.get(url=url,headers=heads).text#第一次请求只带page参数
gz=re.compile('<div class="container" .*? t="(.*?)">',re.S)
t=gz.search(req).group(1)#正则匹配网页的t
with open('t.js','r') as f:
js=f.read()
ctx=execjs.compile(js)
t=str(ctx.call('get_t',t))#调用t.js中get_t函数
sha1 = hashlib.sha1()
data ="Xr0Z-javascript-obfuscation-1"+t#构造参数
sha1.update(data.encode('utf-8'))
sign = sha1.hexdigest()
data={
"page": i,
"t": t,
"sign": sign,
}
url='http://www.glidedsky.com/api/level/web/crawler-javascript-obfuscation-1/items'
req=session.get(url=url,params=data).text
req=json.loads(req)
print( req['items'])
for num in req['items']:
sum+=num