在这篇内容中,边肖为大家整理了关于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是未定义的。呵呵,好像没有传其他参数。继续往下看这个e(2,a)函数:
这是函数e(r,I,n,h,p)方法,可以直接运行获得加密参数。取出这个函数e(r,I,n,h,p)方法的所有代码,保存为js文件。
回到顶端
3 撸代码
3.1方案1
你以为找出生成x-uab的js代码就完事了吗?少年,你太年轻太单纯了!
如何运行这个js脚本是off (nan)键(dian)。
这个函数e(r,I,n,h,p)函数有将近40000行代码。重新实现Python中的难(就)度(时)有(不)点(可)和大(能)。所以我选择直接用Python来执行这个js脚本。
如何在python中执行js脚本?度娘会给你一堆资料。你自己检查一下。我在这里选了execjs。
因为在上面复制的脚本中,只定义了一个e(r,I,n,h,p)方法,并且没有调用这个方法,所以我准备在js文件的末尾添加一些代码来调用:
函数getParam() {
var a;
var param=e(2,a);
返回参数
};
然后,启动Python代码:
导入execjs
node=execjs.get()
file='eleme.js '
ctx=node.compile(打开(文件))。read())
js_encode='getParam()'
params=ctx.eval(js_encode)
打印(参数)
尝试执行,冷心,代码异常:
执行。_ exceptions . program error:type error:“window”未定义。
window对象估计是浏览器打开时创建的,包含了浏览器的信息,所以这段代码在Python中执行时,并没有这样的一对。本来我是想伪造window对象的,但是搜了一下发现js脚本里有上百个地方用到了window。这不是结局。代码混乱,下一关不够,无法溯源(这个地方困扰我很久了。如果哪位学长知道方法,请告诉我)。
后来从一位前辈那里学了一个绕过去的方法(感谢前辈)。这位前辈的方法是把execjs的引擎改成Phantomjs,一个无头浏览器(之前用的引擎是node.js),换句话说就是用Phantomjs来执行JS脚本。PhantomJS是浏览器,自然会创建窗口对象。
在使用PhantomJS之前,需要下载它的驱动,然后在统一目录下放下Python代码。之前的Python代码也进行了修改:
导入execjs
导入操作系统
OS . environ[' exec js _ RUNTIME ']=' phantom js '
node=execjs.get()
file='eleme.js '
ctx=node.compile(打开(文件))。read())
js_encode='getParam()'
params=ctx.eval(js_encode)
打印(参数)
果然,按照这个方法,成功获得了加密字符串。
3.2选项2
其实这个方案2是我在出现未定义窗口对象异常后尝试的第一个方法。但是因为js代码中添加的js脚本出现了问题,我觉得行不通,于是咨询了前辈,得到了方案一。
第二个方案的思路和第一个方案差不多,但更粗暴。不是因为不在浏览器中执行所以没有窗口对象吗?然后我会模拟浏览器来执行它。
在执行之前,还要修改js脚本,调用js文件末尾的E方法,并添加以下代码:
var a;
var param=e(2,a);
返回参数;
记住:不要放在任何函数里。我之前在函数中强制使用了这段代码,结果在浏览器中获得了加密字符串,但在Python中却没有。
selenium和chrome的webDriver进行浏览器模拟,代码如下:
从selenium导入web驱动程序
浏览器=webdriver。chrome(executable _ path=' chrome driver . exe ')
用open('eleme.js ',' r ')作为f:
js=f.read()
打印(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万行,一个加密函数有这么多代码。我不相信。这里面肯定有很多令人困惑的东西,但我已经尝试过调试和追踪了。我只能说,迷茫过后,我无法追寻,头晕目眩。我们如何简化这个脚本?
如果有学长能回答你的问题,请告诉我。我会很感激的!谢谢大家!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。