爬虫,是大家获取互联网公开数据的有效手段。爬虫、反爬虫技术、反-反爬虫技术随着互联网的不断发展,也在不断发展更新, 本文简要介绍现代的爬虫/BOT对抗技术,如有疏漏,多谢指正!
一、反爬虫/BOT技术1.1 Robots.txt
Robots.txt是一个古老的爬虫协议文件,他的位置位于域名根目录下。譬如http://example.com/robots.txt 。 严格来讲Robots.txt并不算一个反爬虫技术,而是一个由爬虫遵守的协议。它通过几个简单的命令告知遵守Robots.txt的爬虫哪些可以被爬取,哪些不能。一般的搜索引擎爬虫会遵守这个协议,而对于上升到爬虫技术对抗的层次来说,这个文件毫无意义。
1.2 IP层/网络层
网络层是反爬虫技术涉及到的最下层,再下的链路层信息在IP报文的传输过程中会被三层交换机丢弃,没有任何意义。IP报文带有的最重要的信息就是IP请求的来源地址, 来源地址极难(近乎不可能)伪造的特性, 使得这个字段成为反爬虫策略中最重要的字段。 封杀IP/IP段是网站可以执行的最严厉的惩罚。由于国内的ISP大量的使用了NAT技术,导致大量用户共用IP的情况越来越多, 内容提供方在做IP封杀时会越来越谨慎, 因为这样做会导致极高的误杀率,以至影响正常用户的网站访问。 但是即使如此, 源IP也是反爬虫策略中最为核心的数据,反爬策略的执行动作一般都要围绕源IP进行。
1.3 HTTP层
HTTP协议层有几个有趣的HTTP头,它们是制定反爬虫策略的常用数据。
1.3.1 X-Forwarded-For
X-Forwarded-For(XFF)是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。 Squid 缓存代理服务器的开发人员最早引入了这一HTTP头字段,并由IETF在HTTP头字段标准化草案中正式提出。
XFF头由普通HTTP代理服务器添加, 在用户通过普通HTTP代理访问网站时, 用户的IP地址会被添加到这个头中。 一些新手程序员在写代码时,往往会把这个的IP地址当做用户的真实IP地址使用,从而被爬虫利用。
1.3.2 Referer
Referer是浏览器在页面跳转时带入的HTTP头,指示用户上一个页面的URL, 一般来说,网站90%以上的流量应该带有Referer头, 在一些常见的反爬策略中, 大量的不带Referer头的源IP请求会触发"要求输入验证码"策略。
1.3.3 User-Agent
User-Agent 是一个古老的HTTP头,指示用户浏览器的版本、操作系统等基本信息, UserAgent伪装已经在其他的文章里有过充分的讨论,故本文不再赘述。
1.4 应用层/浏览器层
在HTTP层之上是应用层,HTTP层上的数据最终会交由浏览器或者APP去渲染、执行。 本文重点讨论基于现代浏览器的应用层反爬、及反反爬技术。
1.4.1 应用层反爬虫/BOT技术简介
1.4.1.1 验证码
验证码(CAPTCHA)是一种古老而有效的方式,用来判别请求方是否是人类。从最初的简单数字验证码、到后来的中文验证码,到现代的图片验证码, 验证码是应用层最普遍,也最核心的爬虫对抗技术。 对于一些简单的数字、字母验证码, 随着近几年机器学习、神经网络的快速发展,已经近乎于无效。有人训练出基于LSTM的模型可以达到80~90%的识别正确率。 对于图片验证码, 也有灰产专门用人工打码平台来处理,所以单凭验证码很难有效处理爬虫问题, 过多的验证码也会导致正常用户的体验受到影响。
1.4.1.2 JS渲染(Ajax / SPA)
众所周知, Ajax技术在2004年左右开始迅速发展,成为重要的浏览器端技术, 也让爬虫从静态爬虫转化为动态爬虫。 从此,爬取网站的数据不再是简单的一个HTTP请求, 然后解析HTML页面就可以了。大量的网站使用ajax来构建网站前端,也使得解析数据变得越来越困难。 在网站完全不设防的状态,爬虫也不止需要解析HTML页面, 亦需要解析Ajax接口返回的数据。
1.4.1.3 接口加密与JS混淆
一般Ajax接口返回的是一个JSON/XML数据格式,除了给爬虫工程师制造一点点的麻烦以外,并没有任何的反爬虫作用, 只需一点点的前端逆向能力(利用Chrome Debug工具, 找到网络请求),就可以找到ajax接口,并通过对应的库解析出数据。但是如果前端通过JS混淆、并把ajax接口通过token进行加密的话,事情就变得比较麻烦了。 这种做法的思路是, ajax接口除了正常的HTTP请求参数外,额外还要接受一个Token参数,这个token参数是前端的js脚本通过其他的参数加密出来的, 它可能是xor、md5、或者是sha256等等。参数可以是用户名、ip、cookies的sessionid、甚至是用户的操作流程(支付宝的做法)再加上前端把js的函数调用层层嵌套、隐藏、 再加上js脚本混淆,令破解者无法方便的逆向出token计算的流程, 就可以达到一定的反爬目的。
1.4.1.4 数据混淆
爬虫的目的是获取到有效的数据。对于许多应用来说,获取到错误的数据往往比获取不到数据更加致命。(想象一下比价网站拿到的都是错误数据的场景)。这个思路的核心就是,当爬虫命中反爬规则之后,使用错误的数据代替正确的数据返回给爬虫, 这种方式非常隐蔽,又可以对对手造成足够的麻烦, 可以说非常的猥琐、也相当的有效。
1.4.1.5 行为分析
用户的操作轨迹与爬虫的操作轨迹是不同的。举个例子, 在电商网站上,用户可能会浏览100个或者更多相似的商品,最终选择一个进行下单。而爬虫的行为可能是浏览100000个商品,且它们之间彼此关联度很低, 最终也不会有任何购买动作。从这个维度来说,就可以判断出这个请求来源是客户还是爬虫。 结合其他的反爬手段,就可以对爬虫造成有效干扰。低级的行为分析基于规则,高级的行为分析基于机器学习。 对于用户操作比较多的网站来讲,是一种很可靠的反爬手段。
1.4.1.6 存储跟踪与flash Storage
Cookies是众所周知的浏览器保持状态的一种机制。 除了Cookies,现代的浏览器还支持localStorage。以目前国内用户的使用习惯,绝大多数用户不会设置拒绝Cookies保持。所以,拒绝Cookies跟踪的客户端可以认为就是爬虫。通过Cookies,就可以跟踪用户的行为轨迹。 除此之外,如果用户使用浏览器模拟技术,一定在每次请求时会清空Cookies。 Cookies被清空之后,我们仍然有机会使用flash来继续跟踪用户。今天的(2017年)Flash确实是一个夕阳技术,但仍然保持极高的市场占用率,在PC端,90%以上的国内视频网站依然采用flash作为播放器的客户端。所以,一个以PC端流量为主的网站,可以使用flash来进行用户跟踪。值得高兴的是,在flash插件中,通过Capabilities.serverString可以获取到非常多的系统信息,包括操作系统、语言、系统分辨率、DPI等等等等。这些系统信息与JS上下文、UserAgent、用户访问日志进行一起分析,就可以判断是否是伪装为爬虫的浏览器。举个例子,如果是正常的用户, 从flash、js上下文、useragent拿到的参数应该是一致的,而如果伪造过UA(不那么高明的伪造),则肯定会有纰漏。正所谓一个谎言需要用十个谎言去掩盖。
1.4.1.7 navigator对象
浏览器中的window.navigator对象保持了很多的操作系统、浏览器信息。navigator对象的信息配合Useragent、flash,可以用来判断是否是伪装浏览器。
1.4.1.8 假链陷阱
假链陷阱作为反爬手段,多见于半静态网站。 它的思路主要是构建一个不可见的a标签, 如果爬虫跟踪所有的页面链接,势必会掉到构造好的陷阱,导致爬虫命中反爬策略。
1.4.1.9 浏览器指纹
浏览器指纹技术常用于客户端跟踪及反机器人的场景。核心思路是, 不同浏览器、操作系统、以及操作系统环境,会使得canvas的同一绘图操作流程产生不同的结果。如果是相同的运行环境,同一套Canvas操作流程会产生相同的结果。 浏览器指纹的优势是不需要浏览器保持本地状态,即可跟踪浏览器。 由于国内特色的Ghost系统安装,这种方式的误杀率并不低,
1.4.1.10 JS引擎指纹
这种思路是,不同的JS引擎在执行相同的JS语句时,会有不同的结果。 举个例子来说,eval.toString().length,在Safari浏览器中的结果是 37 , 在IE中是39 , 在Chrome 中的结果是33. 通过判断JS引擎的动作和UserAgent中声称的浏览器类型,可以判断是否是伪造浏览器。
1.4.2 应用层反反爬虫/BOT方案简介
1.4.2.1 前端逆向
前端逆向,就是利用前端所有代码、数据都是暴露给客户端的特点, 通过分析HTML、JS等源码来获取数据的技术。 常用的前端逆向工具就是Chrome Debug 工具。前端逆向分析通常用来分析那些动态渲染的网站。 如果分析透彻,可以避免使用浏览器模拟的方式来进行爬取。
1.4.2.2 浏览器模拟
浏览器模拟指利用真实的浏览器去请求、执行页面和脚本。应用场景是爬取带有复杂JS和接口加密的网站、也被BOT用于复杂网站。常见的浏览器模拟框架有Selenium WebDriver、 PhatomJS。 Selenium 是通过浏览器的debug接口进行浏览器的远程操控API。PhantomJS是一个嵌入了浏览器内核的js渲染服务,这种技术可以用来对抗动态渲染和接口加密。所有的渲染和加密过程都由浏览器内核完成。 高级的做法是用CEF(Chrome Embedded Framework)进行二次开发。通过二次开发CEF,可以获得很强的灵活性, 比如在页面加载之前劫持JS对象、用C++代码hook native js api等等。这种技术的主要劣势是低下的性能。 与纯粹的HTTP请求代码来说, 这种方案要多吃50~500倍的CPU。 也就是说, 它的效率要下降数十倍到数百倍左右。
1.4.2.2 字符识别
光学字符识别(OCR)用于对抗简单的数字、字母验证码。初级的OCR基于模板。高级的字符识别基于神经网络,比如[这个项目],它基于LSTM模型,可以提供更好的识别率。
1.4.2.4 行为模拟
行为模拟是指在爬虫和BOT的过程中,有意的留下Cookie,并请求一些与需要爬取数据无关的接口或者做一些动作,用来模拟一般用户的动作, 用于对抗行为分析。 在BOT场景下,这种方式也用来模拟用户的活跃度和留存率。 一般来说,行为模拟的主要依据来源于前端逆向的工作, 破解者需要确定究竟有哪些HTML元素和用户行为事件被网站所关注,并针对性的做出想要模拟的行为。 大多数情况下,爬虫的行为模拟是请求某个日志上报接口, 而一些比较特殊的网站(比如支付宝), 用户行为数据附着在请求普通接口的参数中,并经过高度混淆。
1.4.2.6 打码平台
打码平台用来对抗强度比较高的验证码和人机验证方案。正常的验证码流程是,由网站生成一张图片传递给用户,用户输入这张图片的信息传回网站,完成人机验证。 破解者通过对接打码平台,将用户识别信息的环节放到打码平台去做,打码平台组织一群专职人员,进行验证码的识别工作,并传回爬虫,完成验证码的识别工作。高级的打码平台还会利用这些海量的打码数据进行模型训练。
1.4.2.7 JS Hook
这种方式主要用来对抗js上下文的跟踪和分析。做法是,在页面加载前,通过替换JS上下文的对象,将JS上下文中的对象和方法替换掉。 例如,将window.screen对象替换, 使网站的js代码获取到替换后的屏幕分辨率。 JS Hook一般在CEF二次开发中实现,也可以通过劫持普通浏览器的流量完成js hook。
二、IP层反反爬虫技术2.1 代理服务器
对于爬虫的客户端编程来说,利用代理服务器进行源IP更改,是最简单易行的方式。 代理服务器分为HTTP代理和Socks代理两类。HTTP又分为HTTP和HTTPS代理, Socks又分为Socks4和Socks5两类。
2.2.1 HTTP代理
HTTP代理是一种常见的代理服务类型。常用80、8080端口, 它的协议在RFC 7230 中定义。 对于连接到它的客户端来说,它是服务端;对于要连接的服务端来说,它是客户端。它就负责在两端之间来回传送 HTTP 报文。 根据XFF头部的添加与否, 分为普通代理和高匿代理两类。 普通代理会把请求方的源IP添加在HTTP请求头, 而高匿代理不会。对于服务端程序员来说,通过XFF头判断用户的源IP来源是一种十分 Too Young , sometimes naive 的行为,因为服务端完全没有能力判断这个XFF头是由请求方伪造的,还是由代理服务器添加的。 网上流传的一些Java代码,会首先判断XFF头,如果有则将XFF头作为源IP处理,这种方式基本没有任何反爬虫作用。
2.2.2 Socks代理
SOCKS是另外一种常见的代理服务。SOCKS是"SOCKetS"的缩写[1]。这个协议最初由David Koblas开发,而后由NEC的Ying-Da Lee将其扩展到版本4。最新协议是版本5,与前一版本相比,增加支持UDP、验证,以及IPv6。根据OSI模型,SOCKS是会话层的协议,位于表示层与传输层之间。 也就是说,Socks通过TCP连接作为隧道进行代理。 Socks代理中,Socks5代理最为常见。
接下来我会介绍其他的的IP层反-反爬虫方案。
目录如下
2.2 VPN
2.3.1 简单 VPN
2.3.2 混合网络VPN
2.3 VPS
2.4 单机PPP拨号
2.5 并发PPP拨号
三、并发PPP连接技术简介
3.1 PPP协议栈简单介绍
3.2 PPP连接和ADSL的关系
3.3 城域网技术简介
3.4 并发PPP连接方案的适用范围
3.5 国内并发PPP连接服务提供商
四、Linux路由
4.1 Linux基础路由简介
4.2 Linux高级路由简介