爬虫js逆向之加密参数破解--抖音第三方数据分析平台的坑

爬虫js逆向系列
我会把做爬虫过程中,遇到的所有js逆向的问题分类展示出来,以现象,解决思路,以及代码实现,这三方面解析,供大家参考

爬虫认知
在程序猿所有的方向中,爬虫是离money最近的一个方向,你的明白?而且爬虫可发展的方向很多,前可走大数据,人工智能,后可转后端。而且爬虫做得好,要求的技术栈还是比较全面的。如果你对爬虫有兴趣,欢迎加V:13809090874,一起沟通交流

免责申明:
此内容仅供学习交流使用,不用于商业用途,如果涉及侵权,联系作者删除

1. 分析请求头


请求头内容如下:

POST /api/tiktok/ranking/tiktok_goods_sales_rank?ts=1602072436550&he=wqdvbhcTvwD2hXibw4L5RyPHeCsEZ8f7wrD2w4Sh&sign=5e1501c104122454 HTTP/1.1
Host: api.douchacha.com
Connection: keep-alive
Content-Length: 258
dcc-href: https://www.douchacha.com/cable
d-v: NCxaZGJRd3BDVFBzZmlaa1Z4WkhibXdvUUtVc2ZldzZsZ2hkZkR3b09UdWpWeGVPUk13NzlUd3F2VG54SHJLaFlVTkhibUU4YkVHa3BsdzYlMkZVcDhmYVNzZkN3NjhWajhmMkhpY1ROUThNZGtEd1prclV2MlEyVmlNJTJGQ2RiZXc1WkpSMzNVdVNjVHJIZkt3NVlUbzhiYlprZDVaaENVclZ3TWRrVk13cktVb3NiMFprUE13NXAlMkJ3cmNVdmglM0QlM0Q=
Authorization: eyJhbGciOiJIUzI1NiJ9.eyJ0eXBlIjoiUEMiLCJleHAiOjE2MDI2Njg2NDksInVzZXJJZCI6MTI5OTIyNjYzOTc0OTc1MDc4NCwiY3JlYXRlRGF0ZSI6IjIwMjAtMTAtMDcgMTc6NDQ6MDkifQ.ppW18NruEU9gpgRJgbYIaEUkvD7cTmfcRBXgOQ8vamE
Content-Type: application/json;charset=UTF-8
Accept: application/json, text/plain, */*
s-id: 371
dcc-r: https://www.douchacha.com/cable
d-t: 1602072436550
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36
j-id: sem
Origin: https://www.douchacha.com
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://www.douchacha.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
  1. url中有两个加密参数he与ts,ts看着就像是时间戳(毫秒级)
  2. 请求头中有几个加密参数:d-v,Authorization,d-t

大家有没有发现一个问题,就是这个网站没有用cookies。对的,它没有用cookies做身份校验,而是用Authorization来做用户校验,所以我们必须要找到Authorization的加密方式。

2.寻找加密参数封装的地方

对于去寻找目标网站的加密参数,有几个思路跟大家分享一下:

  1. 直接搜关键词,我们要找he,d-v这样的加密参数,直接在js中搜,看是否能搜到,这也是最常用,最直接的办法
  2. 对于一些完全混淆过的js,直接搜是无法搜到的,那么就看它的调用栈,一层层断点打进去。

对于我要爬的网站,还算友好,我直接搜he,d-v就搜到了相对应的代码部分,如下图


从这段代码中,我们可以发现所有请求头的加密参数都是在这里封装的。第6489行代码:

t.url = "".concat(t.url, "?ts=").concat(e, "&he=").concat(s, "&sign=").concat(c);
1

这是url的封装参数,ts与he,ts=e,he=s,sign=c

return i && (t.headers.common["Authorization"] = i),
            t.headers.common["d-t"] = e,
            u && (t.headers.common["j-id"] = u),
            d && (t.headers.common["s-id"] = d),
            g && (t.headers.common["dcc-href"] = g),
            t.headers.common["dcc-r"] = document.referrer || "",
            t

这是请求头的封装参数。
找到这里后,我们就要去找这些值是怎么生成的。
ts:

e = (new Date).getTime() + 1 * sessionStorage.getItem("diffDate") || 0
1

ts就是当前时间戳+session里一个时间差,这个时间差通过阅读源码可以发现,这是页面加载的时间,可以自己随机生成一下
he:

i = JSON.parse(localStorage.getItem("token"))
s = window.he(i ? "uid" : "dt")
12

判断localStorage中的token是否存在,存在就调用window.he(uid),不存在就调用window.he(“dt”),window对象的原生方法中没有he这个方法,那么he()就是他们自定义的方法,我们后面着重去找这个方法就可以了。
sign:

e = (new Date).getTime() + 1 * sessionStorage.getItem("diffDate") || 0
n = t.url.split("https://api.douchacha.com")[1];
o = n + e
c = window.sh(o)
1234

从这里也可以看出sign值加密的方式,主要是找sh生成方法。o参数,我们可以模拟出来。
d-v:

l = window.btoa(window.v() + "," + window.hi("dt"));
t.headers.common["d-v"] = l
12

d-v这个参数就是主要找v()和hi()这两个方法的声明。
Authorization:

i = localStorage.getItem("token")
return i && (t.headers.common["Authorization"] = i),
12

token就是登录时的账号验证信息

3.继续潜入,找到加密方法生成方法

我们之前说过这个网站的主要加密地方为app.js和s.js。通过搜索方法名,我们可以很快的找到这些方法声明的地方


我们搜到了这个方法的地方,但是这里都是十六进制的加密,破解起来非常麻烦。这个js文件还好,只有400多行,把它完全破解,也还好,没那么费力。但是要是上万行,几万行,那就要了老命了。
我们可以通过hook的方式,黑盒的方式来解决这个问题,没必要搞定它是怎么加密的。把这个js下载下来,利用python的execjs这个包去直接调用js函数。就可以解决问题。
注意:运行execjs包的时候,需要先安装nodejs,不然会没有js的运行环境
execjs包的安装:

pip install PyExecJs
1

python代码:

import execjs
js = execjs.compile(open(r"s_my_press.js").read())
url = 'https://api.douchacha.com/api/tiktok/ranking/user_list_gain'
diffdate = 0
n = str(int(round(time.time()*1000)) + diffdate)
# n = '1599562900780'
print('n:'+str(n))
e = url.split('https://api.douchacha.com')[1]
o = e+str(n)
r = js.call('he','1299226639749750784')
r = encode_b64_url(r)
print('he',r)
s = js.call('sh',o)
url = url+'?ts={}&he={}&sign={}'.format(n,r,s)
hi = encode_b64_url(js.call('hi',n))
print('hi:'+hi)
d_v = base64.b64encode((str(4) + ',' + hi).encode())
print('d_v'+str(d_v))

headers ={
                'Host': 'api.douchacha.com',
                'Connection': 'keep-alive',
                'Content-Length': '101',
                'dcc-href': 'https://www.douchacha.com/uppoint',
                'd-v': d_v,
                'Authorization': "eyJhbGciOiJIUzI1NiJ9.eyJ0eXBlIjoiUEMiLCJleHAiOjE1OTk4MjA1NjQsInVzZXJJZCI6MTI5OTIyNjYzOTc0OTc1MDc4NCwiY3JlYXRlRGF0ZSI6IjIwMjAtMDktMDQgMTg6MzY6MDQifQ.KCrYYx4hEqzv6CTJw2NlvD8pp-iRMw7IBgud_XwHHRE",
                'Content-Type': 'application/json;charset=UTF-8',
                'Accept': 'application/json, text/plain, */*',
                's-id': '371',
                'dcc-r': 'https://www.douchacha.com/uppoint',
                'd-t': str(n),
                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.83 Safari/537.36',
                'j-id': 'sem',
                'Origin': 'https://www.douchacha.com',
                'Sec-Fetch-Site': 'same-site',
                'Sec-Fetch-Mode': 'cors',
                'Sec-Fetch-Dest': 'empty',
                'Referer': 'https://www.douchacha.com/uppoint',
                'Accept-Encoding': 'gzip, deflate, br',
                'Accept-Language': 'zh-CN,zh;q=0.9'
            }
    data = {"page_no":1,"page_size":20,"params_data":{"label_name":"","period":"DAY","period_value":"20200907"}}
    r1 = sess.post(url,json=data, headers=headers, verify=False)
    print(r1.text)
1234567891011121314151617181920212223242526272829303132333435363738394041424344

这样就可以成功的抓取到数据了。
当然这里面会有一些小坑。

  • js中的window对象在execjs中运行会报错,因为execjs没有浏览器这个对象,所以我们必须要把window对象里面的方法拎出来,用python去执行,比如window.btoa这是js中base64加密方法,必须用python的base64去重新生成
  • js中默认的编码方式iso-8859-1,而python中不是,在调用python中base64加密时得要表明编码方式为 iso-8859-1

至此,我们前期破解的工作已经完成。至于该网站的登录问题,比较简单,就不写了。也很容易拿到token。后续会更新的,记得给我关注哦!

此文转载文,著作权归作者所有,如有侵权联系小编删除!

原文地址:https://blog.csdn.net/happiness0617/article/details

完整项目源代码点这

猜你喜欢

转载自blog.csdn.net/weixin_43881394/article/details/108996614