? 优质资源分享 ?
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
? Python实战微信订餐小程序 ? | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
?Python量化交易实战? | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
Python爬虫之JS逆向案例
由于在爬取数据时,遇到请求头限制属性为动态生成,现将解决方式整理如下:
JS逆向有两种思路:
一种是整理出js文件在Python中直接使用execjs调用js文件(可见我的另一篇文章《 python爬虫之企某科技JS逆向》)。
一种是根据JS中的逻辑,使用Python重写相应的方法。
本文介绍的是第二种使用Python重写JS的方法
需求:爬取某区块链网站https://www.oklink.com/zh-cn/btc/tx-list?limit=20&pageNum=1数据
遇到的问题:目标网站的数据是通过ajax请求相应的接口获取数据,在请求头中需要携带x-apiKey(根据时间动态生成的),我们需要解决的就是整理出动态生成x-apiKey的方法。
解决思路:根据关键字"x-apiKey”在网站的JS中找到相应的定义,然后使用python重写方法,在请求接口时实时生成相应的x-apiKey
第一步:在浏览器中使用开发者工具找到相应的接口
请求地址:https://www.oklink.com/api/explorer/v1/btc/transactionsNoRestrict?t=1654916647499&limit=20&offset=0
请求类型:GET
请求头:x-apiKey:LWIzMWUtNDU0Ny05Mjk5LWI2ZDA3Yjc2MzFhYmEyYzkwM2NjfDI3NjYwMjc3NTg2MTAzNjk=
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TTShEzjL-1654923044961)(https://img2022.cnblogs.com/blog/505712/202206/505712-20220611111103875-443247577.png "UntitledImage.png")]
第二步:找到x-apiKey的定义方法
t.headers.common["x-apiKey"] = n.Z.getApiKey()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-drpJ3u2W-1654923044964)(https://img2022.cnblogs.com/blog/505712/202206/505712-20220611111720155-1052972427.png "UntitledImage.png")]
根据上面的代码中看到x-apiKey是由getApiKey这个方法返回的,通过getApiKey搜索找到相应的定义如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pO2aeMil-1654923044966)(https://img2022.cnblogs.com/blog/505712/202206/505712-20220611112224456-737630459.png "UntitledImage.png")]
1.接下就是解析这个getApiKey方法了。
{
key: "getApiKey",
value: function() {
var t = (new Date).getTime()
, e = this.encryptApiKey();
return t = this.encryptTime(t),
this.comb(e, t)
}
}
1).变量t就是获取当前时间戳
2).变量e是调用encryptApiKey这个方法
3).变量t是encryptTime(t)这个方法处理后的返回
4).最后通过comb(e,t)个方法生成最终的apiKey
2.encryptTime方法
key: "encryptApiKey",
value: function() {
var t = this.API\_KEY
, e = t.split("")
, r = e.splice(0, 8);
return e.concat(r).join("")
}
1).变量t是一个常量字符串API_KEY,往上找到初始化值为this.API_KEY = "a2c903cc-b31e-4547-9299-b6d07b7631ab"
2).变量e是将上面的t分隔成数组
3).变量r:从变量e中删除前8个字符串,并将e的前8个元素组成的数组赋值给r。同时变量e删除了前8个元素
4).最终将e和r合并在一起并转为字符串
3.encryptTime方法
key: "encryptTime",
value: function(t) {
var e = (1 * t + 1111111111111).toString().split("")
, r = parseInt(10 * Math.random(), 10)
, n = parseInt(10 * Math.random(), 10)
, o = parseInt(10 * Math.random(), 10);
return e.concat([r, n, o]).join("")
}
1).变量e为将入参t加上1111111111111然后转为字符串,分隔为数组
2).变量r、n、o三个是生成10以内的随机整数
3).最后返回的是e和[r,n,o]数组合并,转为字符串返回
4.comb方法
key: "comb",
value: function(t, e) {
var r = "".concat(t, "|").concat(e);
return window.btoa(r)
}
1).变量r是由入参t和e中间加上|然后拼在一起的
2).window.btoa是返回的base64加密编码
3)comb方法最终返回的就是我们需要的x-apiKey的值了
5.将上面的JS逻辑转为Python代码如下:
def get\_api\_key():
cur\_time = int(time.time() * 1000)
api\_key = 'a2c903cc-b31e-4547-9299-b6d07b7631ab'
key\_1 = api\_key[0:8]
key\_2 = api\_key[8:]
encrypt\_api\_key = key\_2 + key\_1
string = str(cur\_time + 1111111111111)
r = random.randint(0, 9)
n = random.randint(0, 9)
o = random.randint(0, 9)
encrypt\_time = '%s%s%s%s' % (string, r, n, o)
new\_key = encrypt\_api\_key + '|' + encrypt\_time
# 转为bytes-like object
new\_key = new\_key.encode('utf-8')
# 将bytes-like object转成字符串类型
return str(base64.b64encode(new\_key), encoding='utf-8')
至此,我们就得到了动态生成的x-apiKey,接下来继续操作吧。
转载请注明:xuhss » python爬虫之JS逆向