爬虫代码已复制

Python爬虫实战C05JS逆向实战练习案例解析

打开Python爬虫实战练习C05页面 爬虫实战练习C05,页面上只有一个拖动式验证码,这种页面我们经常会在电商网站上看到,只要把图片拖动到指定的位置就能够继续进行下一步的操作。

先看看这一关的目标数据是什么,点击 立即验证 ,发现是要求计算并提交各个航班机票价格的平均值。

这时候先按快捷键 F12 打开浏览器开发者工具,切换到 Network 标签,记得先清空掉 Network 里的内容避免干扰,这时候再拖动验证码,发现在加载数据的时候浏览器并没有对外发送请求。这说明数据已经在页面加载的时候一起加载了,我们需要把数据部分找出来,然后再看看是否有数据加密等等数据安全验证措施。

回到页面上,右键 -> 查看页面源码,把 html 都浏览一遍都没发现数据的标签,也没有见到有加密的数据,这就说明数据放在 JavaScript 文件里面。顺着这个思路在 html 源码的第 158 行发现了一个文件名为 c05.min.js 的 JavaScript 文件的引用,直接点击打开它。

在这个 JavaScript 文件中发现了一大片疑似 Base64 编码的字符串,按照以往的经验这里应该就是加密后的数据。先复制出来放到 Base64 编码解码工具 里尝试解码,注意复制的时候区分成对的单引号。发现数据解码成功了,但解码出来的是乱码,这说明数据加密了。

接下来的任务就是把加密混淆的JS代码浏览一遍,看看能不能找出数据使用的是哪一种加密算法,顺便也找找密钥。如果能找到加密算法跟密钥那么这个页面数据的爬虫就很好开发了。

出于习惯,在 html 代码里找了找 captch 相关的关键字,但没找到,那我们就先专注于 JS 文件。

一般拿到代码都会先做静态分析,不要盲目执行,要不然容易触发反爬虫保护,有可能会被封IP的,被封了IP的话就只能使用代理IP继续搞了。

静态分析可以把代码复制粘贴到 VSCode 这类的代码编辑器中,有代码格式化工具跟代码高亮,阅读起来会顺眼一点。

打开 JavaScript 代码之后第一行就是一个函数 function _0x2d8e(),里面有我们刚才发现的疑似加密的数据,而且还找到了一个字符串 mySecretKey123 ,这个很有可能就是加密解密数据的密钥。继续往下浏览代码,在84行发现了 CryptoJS 及 AES 的字符串,初步猜测数据是使用了 AES 加密,密钥是 mySecretKey123,调用的是 CryptoJS 库的函数。

拿着上面这些信息,打开我们的 AES 加密解密工具 ,把这些信息都填进去,点击解密,发现我们的数据就出来了。

接下来就是想办法把这个过程自动化了。

按照我们之前教的,都是使用 Python 截取字符串的形式把这些信息提取出来,再使用 Python 的 AES 算法进行解密,但这次我们使用一些不一样的方法:JavaScript 代码注入。

回到我们第一行 JS 代码,发现这个函数就是返回了一个字符串数据,这个数组的索引为31的就是密钥,索引为6的就是我们的待解密的数据。

在浏览器控制台写下以下代码并回车:

console.log(_0x2d8e()[6]);
console.log(_0x2d8e()[31]);

发现这个代码返回了我们预期的密钥跟待解密数据,接着就是使用这个页面已经引用了的 CryptoJS 对这个待解密数据进行解密。在浏览器控制台写下以下代码并回车:

const bytes = CryptoJS.AES.decrypt(_0x2d8e()[6], _0x2d8e()[31]);
console.log(bytes.toString(CryptoJS.enc.Utf8));

到这里就已经解密出我们需要的数据了,我们要想在 Python 调用以上代码的话,方法有很多,我们这里以 Selenium 进行 JS 代码注入的方式进行,注意的是,注入的 JS 代码需要使用 return 来返回给 Python 代码。

# Selenium JavaScript 代码注入
client = webdriver.Chrome()
print('Getting page...')
client.get(base_url)
time.sleep(3)

result = client.execute_script('''const bytes = CryptoJS.AES.decrypt(_0x2d8e()[6], _0x2d8e()[31]);
return bytes.toString(CryptoJS.enc.Utf8);''')
print(result)
client.quit()

使用 Selenium 的 execute_script 函数传入要执行的 JS 代码,JS 代码使用 return 返回数据,在 Python 中使用一个变量接收 JS 返回的数据即可。

获取到了数据就好办了,计算一下平均值就可以了。

除了 Selenium,其它常用的模拟浏览器如 PlayWright、Puppeteer、Chromedp 等都支持 JS 代码注入,使用方法大同小异。

使用 JS 代码注入的方式,我们就发现这一关我们根本就不需要去调试混淆后的 JS 代码,只是对代码做了个静态分析,得到了核心加密算法我们就直接拿到数据了,连 selenium 有没有被反爬都不用管,所以有时候使用这种方法能省很多事。遇到被遮挡的元素、或者一些被置灰不可用的元素,也可以注入一段 JS 代码去点击或者先把元素变成可点击状态。

完整的爬虫案例代码:爬虫案例代码