今天打算写最后一篇的反爬与反反爬的文章了,毕竟奇技淫巧不少,可是万变不离其宗,熟练掌握JS/HTML/CSS,了解HTTP协议,这是内功。熟练使用chrome,神箭手开发框架,这是称手的兵器。剩下的也就是惟手熟尔。ajax
后面打算开一个番外系列,很多人私信问我关于cnn识别验证码的问题,因此打算开一个系列跟你们一块儿看看我们用机器学习能解决多少验证码识别的问题。感兴趣的朋友欢迎关注我或者专栏:chrome
我:吴桐-神箭手CEO浏览器
专栏:数据黑板-知乎专栏安全
好了,废话很少说,先上以前的文章列表:app
爬虫中Cookie的伪造(非登陆)-反爬与反反爬的奇技淫巧机器学习
爬虫与汽车之家的Css:Content-反爬与反反爬的奇技淫巧post
爬虫与CloudFlare邮箱加密(cfemail)-反爬与反反爬的奇技淫巧
一眼望去已经有很多文章了,不过也应该只覆盖了全部套路的一部分吧,今天既然是压轴,咱们就来聊一个难的,诡异的,不同的,眼前一亮的。常规的单独套路显然就很难符合标准,今天我们要聊的是一个超级组合拳直接让人怀疑人生的反爬套路--商标局(商标检索平台)。
首先呢,咱们的文章只是技术探索的目的。商标局的网站反爬听说是一家专业安全企业的产品-瑞数 ,咱们不会在这篇文章中教你们完整去破解这套系统。咱们一块儿来经过研究这套系统,看看咱们有什么能够借鉴的地方,这套策略到底有什么牛逼的地方。同时提升咱们的反爬与反反爬的能力,固然最重要的是提升JS水平。
好了,既然是组合拳,我们就一个一个拳头来:
第一拳:防调试
我们依照套路,直接打开网站,右击打开调试面板。Boom!
直接断点,我们还啥都没作呢,点击继续,Boom!又断点。这还没上战场,就已经被打残了。
首先不得不说专业的就是专业的,这招简直是不战而屈人之兵。不少人走到这,就已经决定去用无头浏览器了(固然无头浏览器的坑也不少,更致命的是灵活性太差)
这里有一个不算完美的解决方案,就是我安利了无数篇文章的chrome snippets,这里能够明显看到,这个手法是内嵌了一个setinterval的函数,每个间隔时间,就调用一次debugger让浏览器断点,咱们只须要清楚掉这个interval便可,你们能够复制一下下面的代码在console中执行,或者直接保存成snippet每次断点后执行再点继续便可。
for (var i = 1; i < 99999; i++)
window.clearInterval(i);
第二拳:JS验证后跳转
闪过第一拳,第二拳迅速袭来,网页自己并非直接打开的,而是通过了一次JS跳转,跳转到了这样一个网址上:
http://wsjs.saic.gov.cn/txnT01.do?y7bRbP=KaltkM10zh10zh10triDHWegi3_iGKEpBPgY7GGba.A
JS跳转是不少网站验证真实浏览器的方式(好比还有搜狗搜索),固然商标网的这个JS跳转那也真是成精了。因为直接在Chrome中即便勾上preserved log也拿不到具体页面,咱们经过postman来提交一个请求看看真实的返回数据:
这代码看着也真实让人精神抖擞啊,关于这类JS的调试,我已经在上篇文章中,有着相对详细介绍,若是仍是没有掌握其中奥义的朋友们,能够自行学习,我就不详细讲了。这里特别注意几个细节:
1.这里不只仅纯粹JS须要执行,还有一个重要的meta标签和一个外部引用的JS文件都须要模拟到Snippets里去,并且必需要对应上,不然函数名就会错乱。
2.实际代码运行过程当中,还有两套JS的eval执行,谨记用console.log替换eval的套路。
3.代码中有部分代码调用了eval.call的方法,注意此方法会将context换成全局的context执行,模拟的时候务必弄清环境以避免变量错乱。
4.模拟真实浏览器环境的过程当中,相似携程的new Image()套路,这套反爬代码中也下了很多毒。好比navigator的hasOwnProperty,你们在模拟环境变量时必定作到真实模拟,好比内置变量尽可能使用定义prototype后new的形式,而不要直接定义一个变量:
Navigator.prototype = {"appVersion":"5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36",
"appCodeName":"Mozilla",
"appName":"Netscape",
"language":"zh-CN",
"platform":"Win32",
"productSub":"20030107",
"product":"Gecko",
"mimeTypes":[
{"type":"application/pdf","description":"","enabledPlugin":{"name":"PDF Viewer"}},
{"type":"application/x-shockwave-flash",suffixes:"swf",
"description":"Shockwave Flash","enabledPlugin":{"name":"Shockwave Flash","description":"Shockwave Flash 26.0 r0"}}
],
"userAgent":site.getUserAgent(),
"languages": ["zh-CN", "zh"],
"plugins":[
{"name":"Shockwave Flash","description":"Shockwave Flash 26.0 r0",length:2,filename:"pepflashplayer64_26_0_0_151.dll"}
]
};
navigator = new Navigator();
5.代码中有大量dom操做,可是咱们模拟环境是不可能模拟全部dom操做的(真所有模拟出来就是个无头浏览器了,这工做量不可想象)因此建议先写一个空dom函数的,看看具体的调用形式,好比document.getElementById之类,打印一下看看如何调用,而后在模拟具体场景下的使用,好比获取meta标签的content。
6.调试过程当中会发现正常运行能够,可是一旦调试则乱码,此处又是工程师下的剧毒,经过比对执行时间差来判断是不是有人在debug,此处解决方案可执行以下代码替换Date的默认执行来骗过JS:
Date.prototype._getTime = Date.prototype.getTime;
Date.prototype.getTime = function(){
if(!Date._lastTime){
var time = this._getTime();
Date._lastTime = time;
}
Date._lastTime = Date._lastTime+100;
return Date._lastTime;
}
7.耐心!耐心!耐心!因为此处套路之深让携程工程师都看不到底,因此调试的耐心很是重要。
第三拳:Cookie的定时刷新
其实若是我没猜错,第二拳打完,估计地上应该已经全是尸体了,不过记得当年游戏里的一句话:十人九不回,强者尸上行(又暴露年龄了)。
我们继续前行,看看这第三拳:Cookie定时刷新。此处套路已经要突破天际了,宇宙边缘才是这套路的终点。此处JS经过将点击行为,停留时间等等以加密形式存入Cookie中,并定时刷新,几乎作到让想要模拟的人走投无路,不过值得庆幸的是若是顺利挺过第二拳,这第三拳只须要加上一个对浏览器事件机制的模拟便可顺利过关。
第四拳:浏览器内置函数Hook
估计到了第四拳,很多内功差的朋友已经不知道我在说什么了。若是还能看懂的话,我们继续:
这套反爬最让咱们叹为观止的,就是这第四拳,真的是很是的优雅。又把安全作到了几乎是前段的极致。系统经过对XMLHttpRequest的Hook,将全部的Ajax请求都添加上了get参数,就算普通调试,甚至都彻底看不出来get参数是再什么地方加的。不过解决方案固然也很简单,就是对XMLHttpRequest先作一次Hook,在执行代码。
第五拳:表单提交代替连接
这个套路虽然不深,但确实也给调试带来了深深的影响,然而还好走到这的朋友估计已经对这套代码烂熟于心,只须要跳过表单提交,经过其余方案直接获取Url和get参数,同时经过Hook函数document.write就能够完美模拟出表单提交的效果。
话说后面两拳我就不展开了说了,躲过这几拳以后,剩下的就很是简单了,最后的页面连一个ajax都没有,直接xpath就能够所有解析出来。若是你们想把JS提高5678个档次,能够来尝试下商标局网的爬虫。这个爬虫写出来以后,你会发现携程爬虫真的也只算得上小学水平吧。
--------------------------------------------------最后说两句----------------------------------------------------------
我们反爬和反反爬系列就此告一段落了,仍是开头说了,套路不少,一一列举没啥意思,你们掌握思想精髓,作到触类旁通,才能真正通往大神之路。
欢迎你们继续关注我和个人专栏,下面开启一个新系列《验证码终结者》,跟你们一块儿经过新武器-人工智能来会会这个爬虫的老对手(参看爬虫中的验证码识别-反爬与反反爬的奇技淫巧)。
更多回答关注:吴桐-神箭手CEO
更多文章关注:数据黑板-知乎专栏