网络爬虫之记一次js逆向解密经历
1 引言
数月前写过某网站(请原谅我的掩耳盗铃)的爬虫,这两天需要重新采集一次,用的是scrapy-redis框架,本以为二次爬取可以轻松完成的,可没想到爬虫启动没几秒,出现了大堆的重试提示,心里顿时就咯噔一下,悠闲时光估计要结束了。
仔细分析后,发现是获取店铺列表的请求出现问题,通过浏览器抓包,发现请求头参数中相比之前多了一个X-Shard和x-uab参数,如下图所示:

X-Shard倒是没什么问题,一看就是兴趣点的经纬度,但x-uab看过之后就让人心里苦了,js加密啊,只能去逆向解密了。
2 js逆向求解
最直接的思路是根据“x-uab”关键字在所有关键中查找(chrome浏览器-source中按ctrl + shift + F快捷键),结果如下所示:

接下来,打个断点调试一下:在数字那里点一下,数字位置出现蓝点,表示添加断点成功,然后刷新获取店铺列表的页面,程序会在断点处停下。如下所示:

在控制台调试o.getUA()函数,看一下输出:

果然是,证明猜测没错,就是这个o.getUA()函数负责生成请求头中的x-uab参数。
继续向下查看这个getUA()函数的引用(把光标放在要查看的函数上,就可以查看这个函数的引用),就是下图这个函数:

图中的s就是我们要的x-uab参数,下图在控制台输出可以证明:

所以,u-xab是这里的e生成的,而函数e传入的参数中,第一个是常量2,第二个参数a是undefined,呵,看起来没有传其它参数。继续向下找这个e(2,a)函数:

就是这个function e(r, i, n, h, p) 方法,直接运行可以获取加密后的参数。把这个function e(r, i, n, h, p) 方法全部代码取出来,另存为一个js文件。
3 撸代码
3.1 方案一
你以为上面找出生成x-uab的js代码,就大功告成了吗?少年,you are too young too simple!
怎么把这段js脚本运行起来,才是关(nan)键(dian)。
这个function e(r, i, n, h, p) 函数有近4万行代码,重新用Python实现难(jiu)度(shi)有(bu)点(ke)大(neng)。所以,我选择直接用Python来执行这段js脚本。
怎么用python执行js脚本,度娘会给你一堆资料,自己查吧。我这里选择的是execjs。
因为在上面复制出来的脚本中,只单单定义了一个e(r, i, n, h, p)方法,并没有调用这个方法,所以,我要要在js文件的末尾添加一些代码来调用:
function getParam() {
var a;
var param = e(2,a);
return param
};
然后,开始撸Python代码吧:
import execjs node = execjs.get()
file = 'eleme.js'
ctx = node.compile(open(file).read())
js_encode = 'getParam()'
params = ctx.eval(js_encode)
print(params)
尝试执行,心凉,代码异常:
execjs._exceptions.ProgramError: TypeError: 'window' 未定义
window对象估计是浏览器打开是创建的,蕴含浏览器的信息,所以用Python来执行这段代码时,没有这个对西乡。本来想尝试伪造window对象,但查找之后发现js脚本中上百个地方用到window,这还没完,代码经过混淆,在下水平不够,没法追根溯源(这地方困扰了我许久,哪位前辈如果知道方法,请告知)。
后来,从一个前辈那里(感谢前辈)获知一个方法绕过去。这个前辈的方法是将execjs的引擎换成PhantomJS这个无头浏览器(之前用的引擎是node.js),换句话说就是用PhantomJS来执行js脚本,PhantomJS是一个浏览器,自然就会创建window对象。
使用PhantomJS之前,需要下载它的驱动,然后放下Python代码统一目录下。对之前的Python代码也进行修改:
import execjs import os
os.environ["EXECJS_RUNTIME"] = "PhantomJS"
node = execjs.get()
file = 'eleme.js'
ctx = node.compile(open(file).read())
js_encode = 'getParam()'
params = ctx.eval(js_encode)
print(params)
果然,按照这个方法,成功获取加密字符串。
3.2 方案二
事实上,这个方案二才是我在出现未定义window对象异常后首先尝试的方法,不过因为往js代码中添加的js脚本有问题,以为行不通,所以请教前辈,得到了方案一。
方案二的思路和方案一类似,不过更加粗暴一些。不是因为没在浏览器执行,造成没有window对象吗?那我就模拟浏览器来执行。
在执行之前,同样要修改js脚本,在js文件末尾调用e方法,添加如下代码:
var a;
var param = e(2,a);
return param;
切记:不要放在任何函数里面,我之前就是因为将这段代码放在函数里头强制执行,导致的结果就是在浏览器里可以获取加密字符串,但是在Python中获取到的却是None。
模拟浏览器用的selenium和chrome的webDriver,代码如下:
from selenium import webdriver browser = webdriver.Chrome(executable_path='chromedriver.exe')
with open('eleme.js', 'r') as f:
js = f.read()
print(browser.execute_script(js))
这个方法也是可以获得加密之后的字符串。
最后,有必要说一下的是,如果需要获取大量的x-uab,采用方案二效率会高一下,因为采用方案二的话,可以自打开一个浏览器(都调用一个webdriver对象),然后快速执行js,返回加密字符串。
4 总结
一次js逆向解密,算是完成了吧。但是也留下了一些问题:
(1)使用chrome断点调试时,js脚本都是压缩混淆之后的,通过chrome的pretty print功能(也就是说那对花括号)可以格式美化,但是,有的时候却会失败,就像下图,格式化后,还是一团糟:

这个问题耽搁了我很长时间,没法调试啊!
(2)在下js基础不行,很困惑为什么运行时,先通过o.getUA()调用e函数内的嵌套函数,然后e函数内部嵌套函数中调用e方法本身,这是什么操作?函数调用不都应该先外层函数,然后再调用嵌套函数吗?
(3)如果不适用浏览器执行js的方法,就只能替换window对象,这该如何操作?
(4)这个e函数有近4万行,一个加密函数这么多代码,我可不信,里面肯定很多事混淆视听用的,但我尝试调试追踪过,只能说混淆之后让我无从追踪,头晕。怎么才能简化这段脚本呢?
如果哪位前辈可以解惑,请一定告知,不胜感激!拜谢!
网络爬虫之记一次js逆向解密经历的更多相关文章
- python爬虫之企某科技JS逆向
python爬虫简单js逆向案例在学习时需要用到数据,学习了python爬虫知识,但是在用爬虫程序的时候就遇到了问题.具体如下,在查看请求数据时发现返回的数据是加密的信息,现将处理过程记录如下,以便大 ...
- 爬虫必看,每日JS逆向之爱奇艺密码加密,今天你练了吗?
友情提示:优先在公众号更新,在博客园更新较慢,有兴趣的关注一下知识图谱与大数据公众号,本次目标是抠出爱奇艺passwd加密JS代码,如果你看到了这一篇,说明你对JS逆向感兴趣,如果是初学者,那不妨再看 ...
- 网络爬虫养成记(第一天)——安装Scrapy
古人云:工欲善其事,必先利其器.在网络爬虫中,Scrapy无疑是一把利器,那么,今天我们来谈谈Scrapy的安装. 幸运的是,Scrapy已经支持Python3.4+了,也就是说,我们可以在pytho ...
- python爬虫之JS逆向
Python爬虫之JS逆向案例 由于在爬取数据时,遇到请求头限制属性为动态生成,现将解决方式整理如下: JS逆向有两种思路: 一种是整理出js文件在Python中直接使用execjs调用js文件(可见 ...
- python爬虫之JS逆向某易云音乐
Python爬虫之JS逆向采集某易云音乐网站 在获取音乐的详情信息时,遇到请求参数全为加密的情况,现解解决方案整理如下: JS逆向有两种思路: 一种是整理出js文件在Python中直接使用execjs ...
- 爬虫05 /js加密/js逆向、常用抓包工具、移动端数据爬取
爬虫05 /js加密/js逆向.常用抓包工具.移动端数据爬取 目录 爬虫05 /js加密/js逆向.常用抓包工具.移动端数据爬取 1. js加密.js逆向:案例1 2. js加密.js逆向:案例2 3 ...
- 浅谈网络爬虫爬js动态加载网页(二)
没错,最后我还是使用了Selenium,去实现上一篇我所说的问题,别的没有试,只试了一下firefox的引擎,总体效果对我来说还是可以接受的. 继续昨天的话题,既然要实现上篇所说的问题,那么就需要一个 ...
- 这个爬虫JS逆向加密任务,你还不来试试?逆向入门级,适合一定爬虫基础的人
友情提示:在博客园更新比较慢,有兴趣的关注知识图谱与大数据公众号吧.这次选择苏宁易购登录密码加密,如能调试出来代表你具备了一定的JS逆向能力,初学者建议跟着内容调试一波,尽量独自将JS代码抠出来,实在 ...
- 兄弟,你爬虫基础这么好,需要研究js逆向了,一起吧(有完整JS代码)
这几天的确有空了,看更新多快,专门研究了一下几个网站登录中密码加密方法,比起滑块验证码来说都相对简单,适合新手js逆向入门,大家可以自己试一下,试不出来了再参考我的js代码.篇幅有限,完整的js代码在 ...
随机推荐
- HTML5对表单的约束验证
在HTML5中增加了许多新的功能,用于表单提交到服务器之前对表单进行数据的验证(抢了javascript的饭碗),有了这些功能,即便是javascript没有加载进来还是可以确保基本的验证.换句话说, ...
- Learning Python 002 print() 和 input()
Python print() 和 input() print()函数 print()函数可以向终端中输入指定的内容. 输出当个字符串 .py文件中,输入下面的代码,并保存: print('hello ...
- Git for Windows,TortoiseGit支持WinXP的最后版本及下载方法
TortoiseGit兼容Windows XP和Windows Server 2003的最后版本: TortoiseGit 1.8.16.0 (https://download.tortoisegit ...
- ASP.NET Core 身份认证 (Identity、Authentication)
Authentication和Authorization 每每说到身份验证.认证的时候,总不免说提及一下这2个词.他们的看起来非常的相似,但实际上他们是不一样的. Authentication想要说明 ...
- Struts2学习第三课 Action
action VS Action类 action:代表一个Struts2的请求 Action类:能够处理struts2请求的类. 属性的名字必须遵守与JavaBean属性名相同的命名规则. 属性的 ...
- Linux常用知识点汇总
常用命令 1.ls 列出目录下的所有文件及文件夹 2.pwd 打印出当前所在目录 3. ./ 执行 .sh 文件命令 4.ip addr 查看ip地址 5.sudo service network ...
- ASP.NET MVC中的 _ViewStart.cshtml文件的作用【摘抄】
ViewStart 在前面的例子中,每一个视图都是使用Layout 属性来指定它的布局.如果多个视图使用同一个布局,就会产生冗余,并且很难维护. _ViewStart.cshtml 页面可用来消除这种 ...
- The Little Prince
Chapter 1 That is why, at the age of six, I gave up what might have been a magnificant career as a p ...
- 教大家一个看电视局免广告的方法--由UWP想到的
将近一年(10个月)来一直在学习.NET技术,这其中包括C#.WPF.WCF和ASP.NET MVC,目前学习即将结束. 本人在学习WPF的过程中,也了解到有UWP这门技术,UWP技术目前来说主要是应 ...
- Educational Codeforces Round 64 (Rated for Div. 2)D(并查集,图)
#include<bits/stdc++.h>using namespace std;int f[2][200007],s[2][200007];//并查集,相邻点int find_(in ...