- 目标站点:
aHR0cHM6Ly90aW55dXJsLmNvbS95ZnhkYmJrNA==
- 需求背景: 抓取该页面资讯列表
首先打开目标站点,开启F12刷新,一顿好找发现资讯列表数据是在 /api/pc/list/feed
这个请求返回的,然后右键请求复制为cURL,在postman导入发请求,发现有数据返回,迈出了成功的第一步。
接着对Headers和Params一项一项排除,这一步是为了去掉非必要的请求头和查找关键加密参数,发现Headers中除了user-agent外都可以去掉,连cookie都不需要了。Params寥寥无几的参数就留着它吧,通过和别的页面对比,发现token是自媒体的标识,无需变动,那么答案就只剩一个了,关键加密参数是_signture,去除后果然得不到数据返回了,这就是求而不得。
把命运寄托在不知道什么时候会过期的_signture上是不可能的,知道它是怎么生成的,自己生成才是硬道理,正所谓授人以鱼不如授人以渔。让我们在控制台Ctrl+Shift+F全局搜索_signture,哦豁,在index.js里面,点进去并格式化输出看看,果然是你_signture: r
,而r
又是I(n, e)
生成的,啥也别说的,在var r = I(n, e);
这行打个断点,刷新!嚯,果然在断点处暂停了,让我们进入函数 I
看看里面是个啥,按F11即可进入函数内部,然后按F9单步调试,一步两步,约莫18步后就跳进了acrawler.js里面,先不管这里,Shift+F11跳出acrawler.js回到方才那处先,跳回函数I
后 发现已经执行到函数末尾了,上面那行var i
生成的一串字符就是函数I
的返回值也就是_signture了!
到了这里,知道我们想要的是啥了吗,没错,就是那行var i
的生成方法,不过这多个三目运算符堆在一起有点骚啊,我们梳理一下,找主干,看赋值符号=,抽象出 var i = (n=window.byted_acrawler),(r=n.sign),r.call(n,o);
这还不简单,四舍五入就是 var i = window.byted_acrawler.sign(o);
完美,下一步就是把加密方法sign
抠出来,等等!sign
还有一个参数o
是个啥,稳住,从debug输出来看是目标站点的url, o = {url: '...'}
,万无一失了。
现在我们要把window.byted_acrawler.sign
找出来,虽然直觉上我们知道大概率就是刚才跳转进的acrawler.js文件,但还是要顺藤摸瓜,把它的生成过程找出来,才可以模拟。接着Ctrl+Shift+F全局搜索window.byted_acrawler,发现除了在index.js里面,它还在网页源代码里,去看看,只有一行 window.byted_acrawler && window.byted_acrawler.init
,很遗憾,我们已经找不到window.byted_acrawler变量是在哪里声明并赋值的了,但是从源码上一行引用了acrawler.js和刚才debug是跳进acrawler.js推断出,window.byted_acrawler就是acrawler.js里面的函数,去到acrawler.js,发现就只有一个glb变量,假定window.byted_acrawler = glb.byted_acrawler,那window.byted_acrawler.sign = glb.byted_acrawler.sign,try!
我们新开一个浏览器进入控制台Console界面,把acrawler.js的内容复制到Console执行,没报错,那就直接来吧,glb.byted_acrawler.sign({url: '目标站点'});
,成功输出_signture!复制回postman发请求试试,ok,成功返回内容,成功了。