前言
如果再说IP请求次数检测、验证码这种最常见的反爬虫技术,可能大家听得耳朵都出茧子了。当然,也有的同学写了了几天的爬虫,觉得爬虫太简单、没有啥挑战性。所以特地找了三个有一定难度的网站,希望可以有兴趣的手动实践一下。
此篇文章只作知识扩展和思路引导,其中涉及的网站反爬技术,仅做技术学习探讨。
字体加密
字体加密总结成一句话:你看到的不是你看到的。
地址
猫眼电影:https://maoyan.com/films/343568
问题还原
最近的哥斯拉大战金刚看了没啊,好看不,评分高不高,票房多少了?让我们去猫眼看一看吧。

这一看问题就来了:为什么评分和票房在源码里都是"口口"?在页面中看到的评分和票房去哪儿了?
追根溯源
话不多说,先看源码:

看完更疑问了,这个&#x又是啥?这个其实是html中的转义序列,表示后面跟着的是十六进制,处理后在控制台打印一下,如图:

这些数字和票房目前是一分钱关系都没有。那就想办法让他们有所关联。
从网页中找到了以下代码:

其实这就是在css中使用@font-face通过woff文件自定义了字体,源码中的十六进制数字必须通过这个字体映射才能正确显示。就像UTF-8和GBK的关系,编码和解码一致才不会出现乱码。
这里我将woff字体文件下载到本地并用工具打开。

从网页上看到票房是5.74亿,这里就主要关注数字5。从上图可以看出5对应的是glyph11。
使用工具将woff文件转换成xml格式:

glyph11对应的是id=11的glyph,其对应的name为uniE8CD。接着在xml中找到uniE8CD对应的十六进制:

如图,uniE8CD对应的是0xe8cd,也就是说数字5对应的是0xe8cd,正是在控制台输出的第一个数字。
eval() & JS加密
js被加密后放在eval()中执行。如果想还原js,在开发者控制台使用console.log()输出解密后的js。因为不论是eval()还是log(),js解析执行最终都依赖于浏览器内核。
地址
TV猫:https://www.tvmao.com/program/CCTV
问题还原
在频道剧集页,分为早间、午间、晚间节目。如图:

在发起请求获取频道剧集数据的时候,发现返回内容只有早间节目数据,12点以后的剧集数据获取不到。
查看网页源码:

追根溯源
我们在控制台的请求中,搜索网页中的关键字"熊熊乐园",害,果不其然,还真搜着了。

这个响应结果是一个数组,下标0代表标志位:1代表获取到了数据,0代表没有获取到数据;下标1是数据位,对应接口的返回数据。
解析此响应结果的代码比较繁杂,需要对多余内容进行替换。
代码如下:

其实上面代码它并不重要!!接着我们顺着网线去看他的请求部分:

从请求头中可以看出,请求就一个参数p,1、2、3… 整整186位,你看这个参数它又长悠长,像那寂寥的雨巷。虽然等不来那撑着油纸伞的姑娘,但是至少可以先看看这个参数p是怎么生成的。
在搜索框搜索api和pg关键字,找到下面代码:

别管其他,带有ajax字样十有八九就是ajax请求了,参数p的值是变量a,在生成变量a的代码处设置断点,点击页面中的"查看更多"按钮触发断点,接着进入A.d()方法:

往上翻,查看js上部分:

其实到这里就已经可以结束了,你看在d()中又调用了w(),w()也调用了A中其他方法,将这个js中方法调用链搞清楚,将每个方法代码都内联起来,最后计算出参数p,就可以了。
那么,说好的eval呢,说好的加密的js呢?

少侠莫慌,这就带您继续看下去。如果你仔细看,你就会发现上面的js的文件名是匿名/临时的,所以说这不是网站原有的js文件,而是浏览器内核解析后的js。
那该怎么找到原来的js文件?
不知少侠可知搜索功能,你看上面的js中有keyStr这个关键字,咱不妨搜索一波。

这不,如图,eval()有了,加密js也有了,拷贝成文本如下:
eval(function(h, b, i, d, g, f) {
g = function(a) {
return (a < b ? "" : g(parseInt(a / b))) + ((a = a % b) > 35 ? String.fromCharCode(a + 29) : a.toString(36))
}
;
if (!"".replace(/^/, String)) {
while (i--) {
f[g(i)] = d[i] || g(i)
}
d = [function(a) {
return f[a]
}
];
g = function() {
return "\\w+"
}
;
i = 1
}
while (i--) {
if (d[i]) {
h = h.replace(new RegExp("\\b" + g(i) + "\\b","g"), d[i])
}
}
return h
}('5 A={z:"1o+/=",1b:"1l=1k",J:j(a){5 b="";5 c,L,M,14,16,O,N;5 i=0;a=A.1g(a);1t(i<a.R){c=a.S(i++);L=a.S(i++);M=a.S(i++);14=c>>2;16=((c&3)<<4)|(L>>4);O=((L&15)<<2)|(M>>6);N=M&Q;9(1f(L)){O=N=18}K 9(1f(M)){N=18}b=b+y.z.C(14)+y.z.C(16)+y.z.C(O)+y.z.C(N)}8 b},H:j(a){a=a.1G();5 b=\'\';Z(5 i=0;i<a.R;i++){b+=y.1b[a.C(i)]}Z(5 i=0;i<a.R;i++){b+=y.z[a.C(i)]}8 b},1g:j(a){a=a.1B(/\\r\\n/g,"\\n");5 b="";Z(5 n=0;n<a.R;n++){5 c=a.S(n);9(c<P){b+=I.G(c)}K 9((c>1x)&&(c<1w)){b+=I.G((c>>6)|1q);b+=I.G((c&Q)|P)}K{b+=I.G((c>>12)|1p);b+=I.G(((c>>6)&Q)|P);b+=I.G((c&Q)|P)}}8 b},E:j(a){$(\':U[V="19"]\',a).10(A.J(\'l\'+$(".19",a).10()+\'o\'))},B:j(a){5 b=(1c 1d()).1i();9(a!=m)8 A.J(a+\'|\'+b);K 8 A.J(\'\'+b)},e:j(u){5 x=1;5 f=$(\'T\').13();5 a=f.W("U[11=\'1j\']");9(a!=m){x=2}K 9(u!=m){x=u}9(f==m)8 x;8 f.D(\'a\')},c:j(e){5 v;5 f=$(\'T\').13();9(f==m)8"";5 s=f.W("*[17=\'1m\']");9(s==m){v=f.W("U[11=\'1n\']");9(v==m)8"";v=e}v=s.D(\'Y\');8 v},d:j(p,h){5 v=A.w(h);5 a=$("1r.1s");5 x=a||p;9(a!=m){x=h||$("s.1h")}x=A.c();5 b=1c 1d();5 c=b.1u();5 d=b.1v();5 i=d==0?7:d;i=i*i;5 F=y.z.C(i);8 F+A.J(x+"|"+A.e(p))+v},w:j(v){5 t=$("1y");5 a="|";9(t==m){X="/"}K{X=v}5 r=A.J(a+k(X));8 r},s:j(a,b){5 c=y.z.C(1z);8 A.J(c+a)}};5 k=j(a){5 f=$(\'T\').13();9(f==m)8"";5 b=f.D(\'Y\');9(b==m)f.D(\'Y\',a);8 f.D(\'q\')};$(j(){5 b=$(\'<U 17="1A" V="1a"/>\');b.10(A.B());$(\'T[V="1C"]\').1D(b);$(\'a[11^="1E"]\').1F(j(){5 a=$(y).D("1e")+"&1a="+1H(A.B());$(y).D("1e",a)})});', 62, 106, "|||||var|||return|if||||||||||function|||undefined||||||||||||this|_keyStr|||charAt|attr|||fromCharCode||String||else|chr2|chr3|enc4|enc3|128|63|length|charCodeAt|form|input|name|find|tl|id|for|val|class||first|enc1||enc2|type|64|ed|ek|_keyStr2|new|Date|href|isNaN|_C|fix1|getTime|baidu|DVGO|KQMFS|submit|qq|ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789|224|192|div|fix|while|getUTCDate|getDay|2048|127|head|37|hidden|replace|frmlogin|append|by|each|toString|encodeURIComponent".split("|"), 0, {}))
在控制台中将eval()中的加密js使用console.log()打印出来,结果和之前的匿名js一样。
如图:

setCookie & 混淆加密
其实setCookie是一个js混淆加密,但是我之所以叫他setCookie,是因为它的代码起点和核心围绕着一个setCookie函数。
地址
智联招聘:https://jobs.zhaopin.com/beijing
问题还原

当对上面网址发起请求,发现返回的网页内容是一堆看不懂的"乱码"。
如图:

这里我把响应内容复制了出来,供大家阅读。
<html><script src="//aeu.alicdn.com/waf/antidomxss.js"></script&

本文详细揭示了三个网站的复杂反爬策略,包括字体加密、混淆加密、setCookie技术,提供了解密和实战学习路径
最低0.47元/天 解锁文章

3702

被折叠的 条评论
为什么被折叠?



