- A+
背景
近期由于工作上的需求,研究了一下反爬虫的工作。爬虫真是一种让人又爱又恨的存在,一方面搜索引擎的爬虫可以带来更多曝光率和更多流量,对公司是一件好事,但是也有一些个人或者竞争对手的爬虫,不但不会带来利润,反而会像DDos一样对服务器造成压力。
反爬虫一般存在于两个环节,一种是traffic层面,在爬虫访问到服务器之前进行识别、区分,减轻服务器的压力,一般CDN提供商会有相关的反爬虫服务可以购买;一种是在统计层面,防止爬虫对流量、性能分析的影响。这篇文章主要讨论统计层面的反爬虫。
日志!日志!
既然是统计层面,那么前端的日志必不可少。对每一条请求的日志,至少要包含
user-agent,即ua,提供浏览器、系统等信息
bev_id,与设备/浏览器相关,可以认为每个设备的bev_id都是独一无二的
ip,记录请求的ip地址
url,即该请求访问的网址
user_id,对可以登录的网站,该条目记录登录信息
timestamps,记录时间戳,精确到秒或毫秒
除此之外,最好还包含:
用户行为记录,比如该条request是搜索、登录、浏览信息还是支付等等。
另外由于日志的解析问题,可能会有一些日志比较奇怪。如果这种奇怪的日志数量较大,那么首先应该提高数据的质量,才能考虑后续的去爬虫。
爬虫特征
对爬虫的检测有好几种方法。但是问题在于,没有一种方法能保证不误伤真实用户,也不能保证完全检测出所有爬虫。这是因为理论上说,爬虫总是可以模仿真实用户,ua可以模拟,访问频率时间也可以模拟,甚至ip也可以申请多个来回切换。模拟的越真实,越难识别,但是相应的代价(金钱开销,时间成本,代码复杂度)也越高。因此一般爬虫不会用这么多复杂手段来反爬虫。常用的爬虫伪装手段都有:
基础手段:
模拟真实用户的ua。一般用脚本写http访问,脚本会默认用自己的ua,这样反爬虫的时候很容易识别;好在脚本也支持自定义ua,如果爬虫采用了浏览器的ua,伪装成浏览器,就不容易被识别出来。
进阶手段:
使用多个ua/bev_id,打乱并随机采用
分布式,将爬虫部署在多个机器上,采用不同的ip爬取数据
模拟用户登录行为,在cookie里带入真实用户的登录信息
继上一条,记录多个用户cookie,打乱并随机采用
丧心病狂手段:
解析js,模拟用户行为,比如点击、发送日志等
模拟用户浏览的行为,比如一天24小时以均匀速度访问网页的肯定不是正常人类行为;只大量访问数据页面没经过主页、搜索页面的大概率不是人类行为
所以说,爬虫检测真的是很麻烦的事情。
处理方法
针对爬虫的各种伪装,检测手段如下。
基础手段:
ua黑名单,分出自我标识的“善良的”爬虫
基于ua/bev_id/ip的统计手段:
ua行为检测,同一个ua下不同bev_id的访问次数,如果这个平均次数接近于1,意味着这是打乱bev_id但是没有打乱ua的爬虫
可疑的ip,如果某个ip的所有请求中,有大量不同的bev_id但是几乎没有登录用户(user_id),或者大量bev_id的访问时间很短,则认为这个ip可疑
打乱ip,如果一个bev_id的访问量过大,而且该bev_id对应的ip值很多,则说明该bev_id采用了打乱ip的方法,较可能为爬虫
基于用户行为
某个bev_id的所有访问集中在某几个/几类网页,则可能是爬虫
以上列出的都是些比较通用的方法。对于特定的网站,可能有一些特定的方法可以做进一步的爬虫检测。实际应用来看,上面的方法已经可以检测出较大比例的爬虫。
Ground-truth选取
爬虫检测的一大困难在于,没有一个真值可以作为参考。就像机器学习里面的无监督学习。上面列的所有的特征、规则都是基于经验的,就算一个请求被标记为爬虫,哪怕概率再高,我们也无法保证它真的是爬虫。
但是在实际应用中,还是可以有一些洞见可以为爬虫检测提供一些指引。这些洞见是基于爬虫和真实人类行为之间的差异,例如对携程来说,它的网站提供的是酒店、行程的预定,爬虫显然是不会下单付款的,而真实用户有较大的可能性会付款。那么基于这样的一个事实,可以构建一个“肯定是真实用户”的列表,如果某个bev_id被标记为爬虫,但是最终这个bev_id对应的用户付款了,那么相应的检测规则就有必要重新考量一下了。类似的情况在不同的网站不同的场景会有所不同,但出发点都是一样的——寻找爬虫与真实用户的不同。
后记
虽然前面列出的规则看起来都比较显而易见,但是想应用得好还得根据具体问题具体分析,设定相关的阈值。比如同一个ua/bev_id的访问量,多少算多?阈值的设定最好是基于统计的,即先对网站的数据做一个分析,然后按一定比例设定阈值,比如最大访问量的99%。这些探究过程比较耗时,但也比较有意思,在翻阅数据的时候可能会有一些有意思的发现。