关于网络爬虫的那些事:干掉伪装的爬虫

2009-08-12 |  作者:佚名 |  来源:TechWeb |  查看原文

摘要升职加薪是我们每一个在职场打拼的人所期望的,可是以下6种人恐怕难有升职加薪的机会。其共同的特点是不能正确处理自己和他人的关系,缺乏自信心,从而使主观能动性受到挫伤。

在关于网络爬虫的那些事(一)提到,如果爬虫伪装自己的User-Agent信息,就必须寻找新的办法来封杀爬虫了。事实上对网站来说,最大的挑战就是如何准确的甄别一个IP发起的请求,究竟是真实用户访问还是爬虫访问呢?

先说点题外话,在很多年以前(2000年),我就做过网站流量统计系统。主流的网站流量统计系统不外乎两种策略:一种策略是在网页里面嵌入一段js,这段js会向特定的统计服务器发送请求的方式记录访问量;另一种策略是直接分析服务器日志,来统计网站访问量。

在理想的情况下,嵌入js的方式统计的网站流量应该高于分析服务器日志,这是因为用户浏览器会有缓存,不一定每次真实用户访问都会触发服务器的处理。但实际情况是,分析服务器日志得到的网站访问量远远高于嵌入js方式,极端情况下,甚至要高出10倍以上。

现在很多网站喜欢采用awstats来分析服务器日志,来计算网站的访问量,但是当他们一旦采用Google Analytics来统计网站流量的时候,却发现GA统计的流量远远低于awstats,所以开始怀疑GA的准确性。其实GA的统计确实会略低于真实的用户访问量,但数据的真实性比较靠谱,不会偏差特别大。之所以略低是因为GA的服务器有时候用户访问不到,还有一种情况是访问JavaEye的用户所在公司使用了白名单,他能访问JavaEye却无法访问GA服务器,此外也有可能用户还没有等到GA加载就跳转到下一页了,所以统计量没有被GA计算。

那么为什么GA和awstats统计会有这么大差异呢? 罪魁祸首就是把自己伪装成浏览器的网络爬虫。一些网络爬虫为了避免被网站以识别User-Agent的方式封杀,就修改了自己的User-Agent信息,通常伪装成WindowsXP上的IE6浏览器,也有伪装成Firefox浏览器的。这种情况下awstats无法有效的识别了,所以awstats的统计数据会虚高。不过说句公道话,这也怪不了awstats,只怪爬虫太狡猾,不但awstats无法有效识别,就算我们肉眼去查看日志,也往往无法有效识别。

因此作为一个网站来说,如果希望了解自己的网站真实访问量,希望精确了解网站每个频道的访问量和访问用户,开发自己的网站流量统计系统就显得非常有必要性。JavaEye网站就开发了自己的网站流量统计系统,采用在页面里面嵌入js的方式来实现网站流量统计。因此我们可以精确的掌握登录用户和非登录用户的比例,不同的访问偏好,JavaEye每个频道精确的流量和比例,真实的用户数量和分布等GA无法提供的有价值的信息。

JavaEye自己的流量统计系统尽管并不是为了甄别爬虫而编写的,但是他可以帮助甄别网络爬虫。我们知道只有用户使用浏览器访问页面的时候才会执行js,而爬虫并不会执行页面里面的js,所以rails的production.log里面出现的IP地址,却并没有相应的流量统计系统记录这个IP地址,我们可以99%的断定这个IP是个爬虫。如果爬虫编写者专门伪装真实IP向流量统计服务器发起请求的话,流量统计系统也有自己的防范作弊的机制,以及数据分析机制来甄别异常的访问请求,这点就不展开讨论了。

总之有了JavaEye流量统计系统提供的真实IP作为参考标准,我们就可以拿日志里面出现的IP地址进行比较,如果日志里面某个IP发起了大量的请求,在流量统计系统里面却根本找不到,或者即使找得到,可访问量却只有寥寥几个,那么这无疑就是一个网络爬虫,我们可以直接用iptables封杀该C段地址了。

根据这种策略,我们可以重新调整封杀方案。首先统计production.log,统计访问最多的200个C段地址,这仅仅需要一条shell命令:

grep Processing production.log | awk ‘{print $4}’ | awk -F‘。’ ‘{print $1“。”$2“。”$3“.0”}’ | sort | uniq -c | sort -r -n | head -n 200 》 stat_ip.log

这200个C段地址就是我们需要重点考察的对象,网络爬虫就混迹在这200个C段地址之内。它的格式大致如下,显示访问请求最多的C段IP地址和请求次数:

99650 203.208.60.0

55813 123.125.66.0

21131 221.235.58.0

18360 72.14.199.0

14632 121.0.29.0

11789 202.165.185.0

10539 61.135.216.0

10153 65.55.106.0

7001 65.55.211.0

4240 65.55.207.0

3789 219.133.0.0

3721 194.8.74.0

然后我们还需要流量统计系统提供的真实IP地址的C段地址作为参考,这已经由流量统计系统提供给我们了。

接着我们还需要准备一个白名单列表,比方说Google和百度的爬虫IP地址段,对于这些爬虫,我们给予放行,究竟放行哪些爬虫,就需要完全根据自己网站的情况而定了。例如JavaEye现在的白名单(还在不断添加中):

60.28.204.0 抓虾

61.135.163.0 百度

61.135.216.0 有道

65.55.106.0 微软

65.55.207.0 微软

65.55.211.0 微软

66.249.66.0 Google

72.14.199.0 Google

121.0.29.0 阿里巴巴

123.125.66.0 百度

124.115.10.0 腾讯搜搜

124.115.11.0 腾讯搜搜

124.115.12.0 腾讯搜搜

203.208.60.0 Google

209.85.238.0 Google

219.239.34.0 鲜果

220.181.50.0 百度

220.181.61.0 搜狗

最后我们还需要准备一个IP地址库,对于那些被我们揪出来的爬虫,我们还需要甄别一下他的身份,它究竟是一个恶意的爬虫,还是一个未被我们放入白名单的合法爬虫呢?IP地址库很容易从互联网下载一份,所以也不展开讨论了。总之有了这些素材,我们要甄别网络爬虫就十分简单了,仅仅十几行ruby代码就搞定了:

whitelist = []

IO.foreach(“#{RAILS_ROOT}/lib/whitelist.txt”) { |line| whitelist 《《 line.split[0].strip if line }

realiplist = []

IO.foreach(“#{RAILS_ROOT}/log/visit_ip.log”) { |line| realiplist 《《 line.strip if line }

iplist = []

IO.foreach(“#{RAILS_ROOT}/log/stat_ip.log”) do |line|

ip = line.split[1].strip

iplist 《《 ip if line.split[0].to_i 》 3000 && !whitelist.include?(ip) && !realiplist.include?(ip)

end

Report.deliver_crawler(iplist)

代码的实现很简单,就是读入访问请求次数超过3000次的C段地址(+微信关注networkworldweixin),根据经验来说,超过3000次的访问请求已经非常可疑了。然后去掉白名单里面的C段地址,再去掉出现在真实访问列表中的IP地址段,最后剩下来的就是高度可疑的C段地址了。对于这些地址查询IP地址数据库信息,再格式化成报告自动给我发送电子邮件。

最后需要人肉的简单识别,比方说某地址的来源信息显示为“Google公司总部”,那么我就知道这个地址需要添加到白名单里面。除去这些可以肉眼识别的地址,剩下来的就可以统统干掉了。

另外,对于这个简单的程序还需要进一步完善,比方说不是简单的根据realiplist进行比对和排除,而是给realiplist也建立一个ip段的统计信息,即使该段地址有真实访问量,仍然需要进一步甄别,用该地址的请求数量除以realiplist里面的访问数量,如果倍数大于一个阀值比方说1000,就可以断定仍然是网络爬虫。

四、使用浏览器内核驱动的网络爬虫

有人在文章后面的评论里面提到一种新的爬虫的爬取方式,就是不用程序去爬取,而是编程控制一个真正的浏览器内核去爬取网站,由于浏览器内核可以真正执行js,所以会被识别为真实用户访问,从而避开网站的检查机制。这种爬虫是最难以甄别的爬虫,如果精心编写,甚至可以欺骗Google的服务器。由于Safari的webkit浏览器内核和Firefox的Gecko浏览器内核都是开源的,因此一个水平比较高的程序员自己动手编写程序驱动一个真实的浏览器内核作为爬虫并不是非常困难的事情。

实际上这种爬虫我们也遇到过几次,但也并不难以甄别,只是需要一定的手工甄别机制,难以用程序全部自动化甄别。我们知道一个网站的真实用户访问量如果没有短期的市场推广活动,那么会保持一个比较稳定的水平,如果网站的访问量出现一个比较大的跳跃,或者网站频道之间的访问比例出现突变,就可以99%断定有此类爬虫出现了。

那么要甄别它也很简单,对真实访问IP进行统计和排序,挑选出来前200名C段IP地址中每天访问量超过3000次的IP段地址,然后去除白名单,最后再用IP地址数据库去比对。根据经验来说,一个C段地址每天超过3000次访问已经肯定是一个大公司在访问JavaEye了,可如果该来源C段并非出自像阿里巴巴,IBM中国公司,搜狐,腾讯这样的公司地址,就可以99%断定是网络爬虫,直接用iptables干掉该C段地址。

总之,通过这种方式目前已经可以有效甄别伪装的网络爬虫,以及通过n多国外代理服务器的分布式网络爬虫,不过网站和爬虫之间的战争永远不会结束,我们可以通过每天的日志报告来检测网站的运行状况,一旦发现数据报告异常,就知道有新的爬虫出现,那么就可以通过日志分析寻找封杀它的新办法。

相关文章