快捷搜索:  汽车  科技

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段我们在了解代码的功能的时候,一般使用 JavaScript 调试工具(例如 DevTools)通过设置断点的方式来中断或阻止脚本代码的执行,而断点也是代码调试中最基本的了。此时网页暂停加载,自动跳转到 Source 页面并打开了一个 JS 文件,在右侧可以看到 “Debugger paused”,在 Call Stack 中还有一些调用信息,如下图:对于有的网站,如果你继续运行文件,会不停地有调用信息出现在 Call Stack 中,同时不断地消耗内存,最终导致浏览器卡死崩溃。为什么会有这种情况呢?这是前端工程师们做了一点手脚,避免他人进行调试。那就没有解决办法了吗?还是有的,至于怎么做,往下看吧。入门Python其实很容易,但是我们要去坚持学习,每一天坚持很困难,我相信很多人学了一个星期就放弃了,为什么呢?其实没有好的学习资料给你去学习,你们是很难坚持的,这是小编收集的Python入门学


python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(1)


一、前言

在我们爬取某些网站的时候,会想要打开 DevTools 查看元素或者抓包分析,但按下 F12 的时候,却出现了下面这一幕:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(2)

此时网页暂停加载,自动跳转到 Source 页面并打开了一个 JS 文件,在右侧可以看到 “Debugger paused”,在 Call Stack 中还有一些调用信息,如下图:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(3)

对于有的网站,如果你继续运行文件,会不停地有调用信息出现在 Call Stack 中,同时不断地消耗内存,最终导致浏览器卡死崩溃。为什么会有这种情况呢?这是前端工程师们做了一点手脚,避免他人进行调试。那就没有解决办法了吗?还是有的,至于怎么做,往下看吧。

入门Python其实很容易,但是我们要去坚持学习,每一天坚持很困难,我相信很多人学了一个星期就放弃了,为什么呢?其实没有好的学习资料给你去学习,你们是很难坚持的,这是小编收集的Python入门学习资料关注,转发,私信小编“01”,即可免费领取!希望对你们有帮助

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(4)


二、反调试

1.关于调试

我们在了解代码的功能的时候,一般使用 JavaScript 调试工具(例如 DevTools)通过设置断点的方式来中断或阻止脚本代码的执行,而断点也是代码调试中最基本的了。

2.关于反调试

反调试就是在检测到用户打开 DevTools 的时候,就会调用相应的函数,以阻止用户进行调试。在反调试中,有时候会将函数进行重定义,并且改变其行为,就会将某些信息隐藏起来或者改变其中的一部分信息。

三、示例

1.示例一

第一个简单的例子就是直接使用 debugger 的,一打开 DevTools 就无限 debugger:

setInterval(function() { debugger } 100);

这种问题解决起来还是很容易的,总结起来就是四个字: 禁止断点

在 Source 页面右侧按钮找到“Deactivate breakpoints”,或者使用快捷键 Ctrl F8,如下图:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(5)

除了这种解决方案,还可以找到 debugger 那一行,然后右键选择“Never pause here”,就会出现一盒黄色的箭头,如下图:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(6)

设置完之后,继续运行代码就行了。

不过这种方案和代码的编写风格有关系,例如下面这种情况,设置“Never pause here”就没用了。

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(7)

2.示例二

第二个稍微复杂一点,不是直接在代码中加入 debugger 了,而是将其隐藏起来,这样就不会很轻易地被人发现了:

function t() {     try {         var a = ["r"  "e"  "g"  "g"  "u"  "b"  "e"  "d"].reverse().join("");         ! function e(n) {             (1 !== (""   n / n).length || 0 === n) && function() {}             .constructor(a)()             e( n)         }(0)     } catch (a) {         setTimeout(t  500)     } }

这段代码首先是设置变量 a 表示字符串“debugger”,然后使用 constructor() 来实现调用 debugger 方法,再使用 setTimeout 实现每0.5秒中断一次。

要解决这种问题,除了使用前面说的禁止断点,还可以 将反调试具名函数重新定义一遍 ,然后重新打开 DevTools,就能进行调试了。对于上面的例子,可以在控制台中输入以下内容:

t = function() {}

通过下面的截图可以发现我们确实已经修改了对于 t 的定义,因而也就不会进入 debugger 了:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(8)

四、实战

1.目标站点

淘大象: https://taodaxiang.com/credit2

2.页面分析

打开 DevTools,出现“Paused in debugger”,并自动跳转到相应代码位置,如下:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(9)

此时按下 Ctrl F8 禁止断点,然后 F8 继续运行,网页退出 debugger 并正常加载,切换到 NetWork 选项再选择 XHR,可以找到如下请求:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(10)

很明显这个 sign 是经过加密的,全局搜索“sign”看能不能找到可疑内容,出现了四个结果,其中有三个是 JS 文件:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(11)

通过一番查找,可以在 app_init.js 中找到如下内容:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(12)

这是一个发送请求的方法,包含了请求地址“url”、请求方式“type”和数据内容“data”等,而“data”中的内容也和前面的截图相对应,因此可以确定就是这个了。接下来就是解密得到这个 sign 值了。

3.解密过程

首先要找到定义 “_0x5219a6” 的地方:

python3网络爬虫开发实战第二版:突破反爬之应对前端反调试手段(13)

然后可以知道“_0x4168('0x7e0' 'hL^z')”的结果是"dPfhd",再找到“_0x3150ad”的定义:

View Code

因而得到“_0x3150ad[_0x4168('0x7e0' 'hL^z')]”对应的结果为:

function _0x242913(_0x3e2093 _0xbed53d) {

return _0x3e2093(_0xbed53d);

}

经过查找可以知道“_0x292082”对应为 md5,加密方法在一个 JS 文件中,该文件地址为: https://taodaxiang.com/core/modules/common/statics/js/md5.min.js?ver=20190249

那括号里的“_0x5219a6”又是什么呢?需要定位到这几段代码:

case '10': for (var _0x125187 = 0x0; _0x3150ad[_0x4168('0x80b' 'qt7#')](_0x125187 0x20); _0x125187 ) { _0x5219a6 = _0x3150ad[_0x4168('0x80c' 'F#Im')](_0x3150ad[_0x4168('0x80d' 'VFJz')](_0x3150ad[_0x4168('0x80e' 'TwUd')](_0x3150ad[_0x4168('0x80f' 'Uua%')](_0x55322f[_0x4168('0x810' 'E3]P')](_0x125187) _0x3150ad[_0x4168('0x811' 'B([!')](_0x3150ad[_0x4168('0x812' 'LGls')](_0x55322f[_0x4168('0x813' '28mt')](_0x125187) _0x55322f[_0x4168('0x814' 'YKO#')](_0x125187)) 0x20)) _0x3d3ded[_0x4168('0x815' '(]pS')](_0x125187)) _0x3150ad[_0x4168('0x816' 'ONTj')](_0x125187 _0x125187)) 0x9); } continue; case '11': var _0x3d3ded = _0x3150ad[_0x4168('0x817' 'yN7^')](_0x292082 _0x3150ad[_0x4168('0x818' '^^9o')](_0x3150ad[_0x4168('0x819' '#a#K')](_0x3150ad[_0x4168('0x81a' '!Ior')](_0x2acbce _0x55322f) _0x2acbce) _0x2bae27[_0x4168('0x81b' '0!ku')])); continue; View Code

这里得先求“_0x3d3ded”的值,经过一番调试知道“_0x3d3ded”是通过md5加密得到的,加密的字符串的结构为:

account 7176a337dffebf0ff2d30d65fda5af78  account type

最终得到的“_0x3d3ded”的值如下:

f81765c208bcc1a6892863af77bb4fae 

将这个值带入前面的代码中进行运算就能得到“_0x5219a6”了,最后再用 md5 加密一下,就得到我们需要的 sign 了!

猜您喜欢: