美文网首页收集癖寒哥管理的技术专题代码改变世界
JS结合Memcache实现爬虫程序的识别与阻挡 演示Demo

JS结合Memcache实现爬虫程序的识别与阻挡 演示Demo

作者: 南瓜不胡闹 | 来源:发表于2015-04-16 13:25 被阅读6807次
   最近公司网站的一个查询接口一直遭受爬虫的访问,由于对方通过数量巨大的分布式IP访问(大约是正常访问IP数量的几百倍),同时单个IP的访问频率又比较低,所以以往部署的一些根据访问频率特征识别阻挡的策略基本无法起到有效的防范作用。

   频率特征识别行不通,于是我们又通过识别爬虫工具的HTTP请求头中的一些特征:是否包含特定的HTTP头或没有包含某些正常浏览器请求应该携带的HTTP头(如cookie和referrer),这样的封锁比较有针对性,但是HTTP头的修改成本很低,对方后来也确实多次调整HTTP头信息来规避我们的检查。同时这个方法也有可能误伤一些正常的访问。

   为了更有效地识别爬虫程序,我们继续寻找其它的方法,也在网上查了一些资料。其中一个比较普遍应用的原理,是基于爬虫一般都是构造查询请求直接Post到查询接口这一特征,通过在页面嵌入JS代码判断访问来源是一个真实浏览器还是一个直接请求接口的程序。
   在更完整的方案里,还有同时结合memcache或redis对请求的IP进行计数统计:在查询接口时,对来源IP请求计数+1,同时在响应页面的JS里实现对来源IP请求-1,这样一来,正常的用户浏览器查询访问,两次操作计数抵消,计数应该始终保持在一个比较低的值(理想情况应该始终在0或1,但考虑到响应页面可能出现加载不完全等情况,不一定每次都能减值),而爬虫程序由于并不触发JS,累计查询始终增长。这样就能有效识别出哪些来源是爬虫请求,接下来要怎么处理就简单了。

   说起来总是没有看起来那么清晰明了,于是和团队的小伙伴们商量做个demo来演示一下,说干就干,用简单强大又好用的Python(我不会告诉你其实是因为我只会Python的)搭个网站,起个memcache,半个下午基本齐活了。

代码如下:
<pre><code>

!/bin/python

import memcache
import web
render = web.template.render('templates/')

mc = memcache.Client(['x.x.x.x:11211'], debug=0)

index页面有个最基本的搜索框,post到search页面,在search直接显示post的内容。

在search页面嵌入的JS代码会向memcache页面发起请求

urls = (
'/','index',
'/search','search',
'/memcache','mem'

)

class index:
def GET(self):
return render.index()

在search页面,操作memcache,对访问源IP的计数+1

同时做个判断,如果发现memcache里这个IP的访问计数>1,就返回一个报错页面

class search:
def POST(self):
data = web.input().get('searchstr')
#data = web.ctx['ip']
srcip = str(web.ctx['ip'])
if mc.get(srcip):
mc.incr(srcip)
else:
mc.set(srcip,1)
if mc.get(srcip) > 1:
return render.bug()
else:
return render.search(data)

memcache页面的处理方法,操作对访问源IP计数-1

class mem:
def GET(self):
srcip = str(web.ctx['ip'])
if mc.get(srcip):
mc.decr(srcip)

if name == "main":
app = web.application(urls,globals())
app.run()
</code></pre>

   第一次贴完代码发现果然还是没有养成写注释的好习惯,好在比较简单,赶紧补充一下。
   代码运行起来,首页就长这样:
Paste_Image.png
   随便输入一个查询,比如"123",查询出的结果页,长这样:
Paste_Image.png

这时候,去看一下memcache里的记录,我们这个IP的记录有了,计数是0

Paste_Image.png

接下来我们通过工具构造POST请求模拟爬虫的行为。构造工具很多很多,我们为了方(tou)便(lan),就用linux自带的wget,道理是一样一样的

$ wget --post-data="searchstr=123&submit=Submit" http://x.x.x.x:8080/search

嗯,第一次查询,我们看到获取的结果和用浏览器访问得到的是一样的:


Paste_Image.png

但是看看我们的memcache,由于工具并不会触发结果页面上的JS,所以计数累计到了1


Paste_Image.png

于是再用工具来查询一次看看,由于memcache中累计到了2,程序处理直接跳到报错页面了。真实应用中,这里也可以是验证码之类的东西。


Paste_Image.png
   这个demo并没有用到特别深的原理和技术,不过能通过自己的双手把别人提供的解决方案演示出来,感觉还是棒棒哒,不断理论结合实践并做好总结才是提高技术水平的好方法。
   纸上得来终觉浅,绝知此事要躬行,以此作为简书第一篇。

相关文章

网友评论

  • 南瓜不胡闹:@cloverstd 完全阻止做不到,真的有心分析,总是道高一尺魔高一丈哈~但是提高对方的成本总比什么都不做要好:P
  • 南瓜不胡闹:@coolsui 思路是网上借鉴的~只是实践了一下
  • b8b2a56ade4c:思路很赞👍
  • Ey3sRc:@南瓜不胡闹 囧,当我发现我被屏蔽了,我就首先去对比 HTTP header,然后再去看是不是需要Cookies,如果都不是,我就去看是不是页面上也 JS,比如什么值得买,就在没有 Cookies,会首先出来一个通过 JS 跳转并且设置 Cookies的页面,然后再通过 window.location.href 跳转
  • 南瓜不胡闹:@cloverstd 是的,但要做到这一点是要做爬虫的人再去分析我是通过什么来阻挡他的,他也未必知道这个js发起请求就是用来做这个的。
  • Ey3sRc:你在前端用 JS 触发 mem 减一也是一次 HTTP 请求呀,爬虫也可以同时在 search 的时候发一个 mem 的请求,这样 IP 请求数也是维持在1啊
  • 未知用户sal: @南瓜不胡闹 原来如此,感谢回复~
  • 南瓜不胡闹:@Maxint64 在我们这里主要是因为这个爬行会产生费用,对我们的成本有压力,一般爬行如果不造成太大压力影响业务我觉得是可以接受的。而如果爬虫对站点造成比较大的压力,那要么扩充服务资源要么想办法把它干掉,都是需要投入的,可以对比评估。我是这么看的。
  • 未知用户sal:策略挺棒的,但是需要前台支持,如果受到爬虫抓取的接口或页面比较多的话,改造代价会不会太大?

本文标题:JS结合Memcache实现爬虫程序的识别与阻挡 演示Demo

本文链接:https://www.haomeiwen.com/subject/kebsfttx.html