网络爬虫技术的定义与反爬虫方法剖析
优采云 发布时间: 2020-05-11 08:03Web是一个开放的平台,这也奠定了Web从90年代初诞生直到明日将近30年来蓬勃的发展。然而,正所谓成也萧何败也萧何,开放的特型、搜索引擎以及简单易学的HTML、CSS技术促使Web成为了互联网领域里最为流行和成熟的信息传播媒介;但现在作为商业化软件,Web这个平台上的内容信息的版权却毫无保证,因为相比软件客户端而言,你的网页中的内容可以被太低成本、很低的技术门槛实现出的一些抓取程序获取到,这也就是这一系列文章将要阐述的话题——网络爬虫。
有很多人觉得Web应该一直秉持开放的精神,呈现在页面中的信息应该毫无保留地分享给整个互联网。然而我觉得,在IT行业发展至明天,Web早已不再是当初那种和PDF一争高下的所谓“超文本”信息载体了,它早已是以一种轻量级客户端软件的意识形态的存在了。而商业软件发展到明天,Web也不得不面对知识产权保护的问题,试想假如原创的高质量内容得不到保护,抄袭和盗版横行网路世界,这显然对Web生态的良性发展是不利的,也很难鼓励更多的优质原创内容的生产。
未授权的爬虫抓取程序是害处Web原创内容生态的一大诱因,因此要保护网站的内容,首先就要考虑怎样反爬虫。
从爬虫的攻守角度来讲
最简单的爬虫,是几乎所有服务端、客户端编程语言都支持的http恳求,只要向目标页面的url发起一个http get恳求,即可获得到浏览器加载这个页面时的完整html文档,这被我们称之为“同步页”。
作为逼抢的一方,服务端可以按照http请求头中的User-Agent来检测客户端是否是一个合法的浏览器程序,亦或是一个脚本编撰的抓取程序,从而决定是否将真实的页面信息内容下发给你。
这其实是最小儿科的防御手段,爬虫作为逼抢的一方,完全可以伪造User-Agent数组,甚至,只要你乐意,http的get方式里, request header的 Referrer 、 Cookie 等等所有数组爬虫都可以轻而易举的伪造。
此时服务端可以借助浏览器http头指纹,根据你申明的自己的浏览器厂商和版本(来自 User-Agent ),来分辨你的http header中的各个数组是否符合该浏览器的特点,如不符合则作为爬虫程序对待。这个技术有一个典型的应用,就是PhantomJS1.x版本中,由于其底层调用了Qt框架的网路库,因此http头里有显著的Qt框架网路恳求的特点,可以被服务端直接辨识并拦截。
除此之外,还有一种愈发变态的服务端爬虫检查机制,就是对所有访问页面的http请求,在 http response 中种下一个 cookie token ,然后在这个页面内异步执行的一些ajax插口里去校准来访恳求是否富含cookie token,将token回传回去则表明这是一个合法的浏览器来访,否则说明刚才被下发了那种token的用户访问了页面html却没有访问html内执行js后调用的ajax恳求,很有可能是一个爬虫程序。
如果你不携带token直接访问一个插口,这也就意味着你没恳求过html页面直接向本应由页面内ajax访问的插口发起了网路恳求,这也似乎证明了你是一个可疑的爬虫。知名电商网站amazon就是采用的这些防御策略。
以上则是基于服务端校准爬虫程序,可以玩出的一些套路手段。
基于客户端js运行时的测量
现代浏览器赋于了强悍的能力,因此我们可以把页面的所有核心内容都弄成js异步恳求 ajax 获取数据后渲染在页面中的,这也许提升了爬虫抓取内容的门槛。依靠这些方法,我们把对抓取与反抓取的对抗战场从服务端转移到了客户端浏览器中的js运行时,接下来说一说结合客户端js运行时的爬虫抓取技术。
刚刚提到的各类服务端校准,对于普通的python、java语言编撰的http抓取程序而言,具有一定的技术门槛,毕竟一个web应用对于未授权抓取者而言是黑盒的,很多东西须要一点一点去尝试,而耗费大量人力物力开发好的一套抓取程序,web站作为逼抢一方只要轻易调整一些策略,攻击者就须要再度耗费同等的时间去更改爬虫抓取逻辑。
此时就须要使用headless browser了,这是哪些技术呢?其实说白了就是,让程序可以操作浏览器去访问网页,这样编撰爬虫的人可以通过调用浏览器曝露下来给程序调用的api去实现复杂的抓取业务逻辑。
其实近些年来这早已不算是哪些新鲜的技术了,从前有基于webkit内核的PhantomJS,基于Firefox浏览器内核的SlimerJS,甚至基于IE内核的trifleJS,有兴趣可以瞧瞧这儿和这儿 是两个headless browser的搜集列表。
这些headless browser程序实现的原理虽然是把开源的一些浏览器内核C++++代码加以整修和封装,实现一个简易的无GUI界面渲染的browser程序。但这种项目普遍存在的问题是,由于她们的代码基于fork官方webkit等内核的某一个版本的主干代码,因此难以跟进一些最新的css属性和js句型,并且存在一些兼容性的问题,不如真正的release版GUI浏览器。
这其中最为成熟、使用率最高的应当当属PhantonJS了,对这些爬虫的辨识我之前曾写过一篇博客,这里不再赘言。PhantomJS存在众多问题,因为是单进程模型,没有必要的沙箱保护,浏览器内核的安全性较差。
如今Google Chrome团队在chrome 59 release版本中开放了headless mode api,并开源了一个基于Node.js调用的headless chromium dirver库,我也为这个库贡献了一个centos环境的布署依赖安装列表。
headless chrome堪称是headless browser中独树一帜的大杀器,由于其自身就是一个chrome浏览器,因此支持各类新的css渲染特点和js运行时句型。
基于这样的手段,爬虫作为逼抢的一方可以绕开几乎所有服务端校准逻辑,但是这种爬虫在客户端的js运行时中仍然存在着一些纰漏,诸如:
基于plugin对象的检测
基于language的检测
基于webgl的检测
基于浏览器hairline特点的检测
基于错误img src属性生成的img对象的检测
基于以上的一些浏览器特点的判定,基本可以通杀市面上大多数headless browser程序。在这一点上,实际上是将网页抓取的门槛提升,要求编撰爬虫程序的开发者不得不更改浏览器内核的C++代码,重新编译一个浏览器,并且,以上几点特点是对浏览器内核的改动虽然并不小。
更进一步,我们还可以基于浏览器的UserAgent数组描述的浏览器品牌、版本机型信息,对js运行时、DOM和BOM的各个原生对象的属性及技巧进行检验,观察其特点是否符合该版本的浏览器所应具备的特点。
这种方法被称为浏览器指纹检测技术,依托于小型web站对各机型浏览器api信息的搜集。而作为编撰爬虫程序的逼抢一方,则可以在headless browser运行时里预注入一些js逻辑,伪造浏览器的特点。
另外,在研究浏览器端借助js api进行robots browser detect时网络爬虫 技术,我们发觉了一个有趣的小技巧,你可以把一个预注入的js函数,伪装成一个native function,来瞧瞧下边代码:
爬虫进攻方可能会预注入一些js方式,把原生的一些api外边包装一层proxy function作为hook,然后再用这个假的js api去覆盖原生api。如果防御者在对此做检测判定时是基于把函数toString以后对[native code]的检测,那么都会被绕开。所以须要更严格的检测,因为bind(null)伪造的方式,在toString以后是不带函数名的。
反爬虫的手炮
目前的反抓取、机器人检测手段,最可靠的还是验证码技术。但验证码并不意味着一定要逼迫用户输入一连串字母数字,也有好多基于用户键盘、触屏(移动端)等行为的行为验证技术,这其中最为成熟的当属Google reCAPTCHA。
基于以上众多对用户与爬虫的辨识分辨技术,网站的防御方最终要做的是封禁ip地址或是对这个ip的来访用户施以高硬度的验证码策略。这样一来,进攻方不得不订购ip代理池来抓取网站信息内容,否则单个ip地址很容易被封造成难以抓取。抓取与反抓取的门槛被提升到了ip代理池经济费用的层面。
机器人协议
除此之外,在爬虫抓取技术领域还有一个“白道”的手段,叫做robots协议。你可以在一个网站的根目录下访问/robots.txt,比如使我们一起来瞧瞧github的机器人合同,Allow和Disallow申明了对各个UA爬虫的抓取授权。
不过,这只是一个君子合同,虽具有法律效益,但只能够限制这些商业搜索引擎的蜘蛛程序,你没法对这些“野爬爱好者”加以限制。
写在最后
对网页内容的抓取与反制,注定是一个魔高一尺道高一丈的猫鼠游戏,你永远不可能以某一种技术彻底封死爬虫程序的街网络爬虫 技术,你能做的只是增强攻击者的抓取成本,并对于未授权的抓取行为做到较为精确的据悉。