JavaScript学习笔记二 (学自拉勾教育崔大神)

逆向思路:通过XHR断点,确定发送XHR请求的位置。然后通过执行栈,找到构造参数的JavaScript代码所在位置。将JavaScript构造参数的逻辑用python实现,从而构造加密参数值,实现正确的url请求。

爬取的网页为:https://dynamic6.scrape.cuiqingcai.com/

首先列表页的请求url为,第一页与第二页的分别为:

JavaScript学习笔记二 (学自拉勾教育崔大神)_第1张图片

JavaScript学习笔记二 (学自拉勾教育崔大神)_第2张图片

能够看出列表页url需要构建的参数为limit,offset,token。其中limit为每页的个数为10,offset可以看作是它的偏移量。第一页为0,第二页10,第三页20。这两个参数可以自己直接构造。主要是token值的构建。

首先我们打一个XHR断点,首先确定发送XHL定位位置。因为对于发送Ajax请求来说,找到列表页url请求发送的位置,就可以往前寻找,一步步找到构建url里边参数的位置。

因url中包含/api/movie,因此我们可以将此作为打断点的内容。

JavaScript学习笔记二 (学自拉勾教育崔大神)_第3张图片

然后通过刷新页面,确定发送XHR(url)的位置。

JavaScript学习笔记二 (学自拉勾教育崔大神)_第4张图片

现在已经确定了请求发送的位置,现在我们只要通过Call Stack找到token构建的位置即可。因为url肯定是构建完token,才能获得完整url然后去请求的。

现在我们给条发送请求的位置打上断点,然后去Call Stack去找token构建位置。打上断点后刷新页面,记得每次打断点之前将原先打的断点先取消。

JavaScript学习笔记二 (学自拉勾教育崔大神)_第5张图片

此时我们就可以一步一步往前走。寻找参数构建位置。通过从上往下依次点击,找到 了在onFetchData中存在token的构建。

JavaScript学习笔记二 (学自拉勾教育崔大神)_第6张图片

可以看到token对应的值为_0x39f52。然后我们去寻找_0x39f52,可以看到其构造过程为

我们可以从onFetchData开头打上断点。一步步调试可以发现每个变量的结果是怎么样的。当调试至上边表达式时,将this后的圈住发现,其指代的就是/api/movie。所以现在我们的主要目的就是前边这个函数了。其实我们要得到的就是_0x376c60['a']的值

JavaScript学习笔记二 (学自拉勾教育崔大神)_第7张图片

我们可以在watch内去查看这个函数,找到函数的位置。将_0x376c60添加入watch内。便可以看到其函数的location。点击便可以跳转到函数所在的位置。

JavaScript学习笔记二 (学自拉勾教育崔大神)_第8张图片

其函数定位至:

JavaScript学习笔记二 (学自拉勾教育崔大神)_第9张图片

也就是说_0x376c60['a']的值就是_0x31b852()的返回值。我们将这个函数用python实现出来也就得到了这个值。

同样在函数开始打断点,一步步看函数的执行过程。播放键右边那个即是单步调试按钮。

JavaScript学习笔记二 (学自拉勾教育崔大神)_第10张图片

我们可以先单步点击,一步步执行完整个函数,可以在scope中看到每个变量执行完的结果。首先观察最前边的 _0x320ba5。可以看到其逻辑大概为一个时间戳的值除以1000四舍五入最后转为字符串。能够看到其执行完后值为159468934。需要注意的是在javascript中的时间戳为毫秒级,而python中的time.time()得到的时间戳为秒级,所以直接使用time.time()就可以,不需要再除以1000。

其python实现过程便为:_0x320ba5 = str(int(time.time()))

继续进行单步调试可以发现:_0x4fef38的值为['/api/movie'],后边随着代码继续运行,,将这个值,与得到的时间戳放在一起,即同一个列表中。其结果也可以通过单步调试发现。

JavaScript学习笔记二 (学自拉勾教育崔大神)_第11张图片

然后开始计算_0x216573:

此句大致意思为将刚刚得到的_0x4fef38,用‘,’将列表里的元素隔开,然后转化为utf-8后再进行sha1加密最后转成十六进制。

这需要注意的逻辑是先执行完(_0x4fef38['join'](',')),后应该先进行encode(),才能进行sha1加密。因此大致逻辑为先用逗号隔开_0x4fef38,然后将其encode为utf-8,然后进行sha1,最后想起结果转为16进制。其Python实现为

JavaScript学习笔记二 (学自拉勾教育崔大神)_第12张图片

之后程序为 ,即将刚才计算出来的结果,与第一步计算的时间戳放在一个列表中用逗号隔开。

最后观察_0x3fc8fd,其为实现一个base64编码的过程。

JavaScript学习笔记二 (学自拉勾教育崔大神)_第13张图片

所以最终_0x93d0aa的值为将_0x322162用‘,’隔开后进行encode()最后进行base64编码,即为最终结果。其Python实现为

base64.b64encode(','.join(_0x322162).encode('utf-8')).decode('utf=8')。

最终便得到了_0x376c60['a']的返回值。即最终的token的值。

得到token后我们列表页url中所有的参数也就算是得到了。通过构建完整的url即可获得详情页的信息。

                                                                                                                                                             

                                                                                                                                                                         小胖胖的猪崽

你可能感兴趣的:(爬虫)