飞道的博客

反爬虫策略手把手教你使用FastAPI来限制接口的访问速率

443人阅读  评论(0)

击上方“Python爬虫与数据挖掘”,进行关注

回复“书籍”即可获赠Python从入门到进阶共10本电子书

秋风吹不尽,总是玉关情。 

在网络爬虫的过程中,我们都会遇到各种各样的反爬虫,封禁IP和账号,设置验证码,前端加密,浏览器指纹,甚至输出假数据来等等都是可能出现的反爬手段,这些我们今天一个也不会谈及,而是谈谈一种叫访问速率限制的手段。


对于服务端而言,有时候会碰到这么一个场景:某个接口需要在某个时间段内设置最高的访问次数来降低服务器的压力,比如之前用的某度的一些接口,一分钟内访问次数过高就会返回失败,等上个2分钟就又可以返回了。目的就是为了防止开发人员或者爬虫,甚至是恶意请求对服务器无限制的访问,降低服务器开支,因为一般的用户的请求是不会这么频繁的

Ratelimiter

python 中使用 Ratelimiter 来限制某方法的调用次数,用法如下


   
  1. import time
  2. from ratelimiter  import RateLimiter
  3. def limited(until):
  4.     duration =  int(round(until - time.time()))
  5.      print( 'Rate limited, sleeping for {:d} seconds'.format(duration))
  6. # 3秒之内只能访问 2
  7. rate_limiter = RateLimiter(max_calls= 2, period= 3, callback=limited)
  8. for i in  range( 3):
  9.     with rate_limiter:
  10.          print( 'Iteration', i)

输出结果如下


   
  1. Iteration  0
  2. Iteration  1
  3. Rate limited, sleeping  for  3 seconds
  4. Iteration  2

看到程序如期打印, callback 指定了超出指定次数是回调方法 

达到了预期的要求

asyncio 异步中的使用


   
  1. import asyncio
  2. import time
  3. from ratelimiter  import RateLimiter
  4. async def limited(until):
  5.     duration =  int(round(until - time.time()))
  6.      print( 'Rate limited, sleeping for {:d} seconds'.format(duration))
  7. async def coro():
  8.     rate_limiter = RateLimiter(max_calls= 2, period= 3, callback=limited)
  9.      for i in  range( 3):
  10.         async with rate_limiter:
  11.              print( 'Iteration', i)
  12. loop = asyncio.get_event_loop()
  13. loop.run_until_complete(coro())

执行结果是一致的, 在一般的 python 方法里面用 Ratelimiter 是没有问题的

Slowapi

对于网络请求的访问速率限制,我建议使用 Slowapi 库,Slowapi相对灵活易用,不必考虑更多的因素。在 fastapi 和 flask 中使用也是得心应手,当然flask框架也有第三方扩展,这个自不必说,django也有自带的限制访问速率的库,而 fastapi 相对比较新,扩展库相对匮乏,在一个偶然的机会看到 Slowapi 的源码, 这是一个非常不错的选择,如果有机会,我会把它封装成 fastapi 框架的另一个插件,继成更多的功能,名字可以是 fastapi-slowapi 之类的

来看看具体的用法


   
  1. # -*- coding: utf -8 -*
  2. # @Time :  2020/ 11/ 11  11: 09
  3. from fastapi  import FastAPI
  4. from slowapi  import Limiter, _rate_limit_exceeded_handler
  5. from slowapi.errors  import RateLimitExceeded
  6. from slowapi.util  import get_remote_address
  7. # 初始化 slowapi,注册进 fastapi
  8. limiter = Limiter(key_func=get_remote_address)
  9. FastAPI().state.limiter = limiter
  10. FastAPI().add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)

具体调用方法


   
  1. # -*- coding: utf -8 -*
  2. # @Time :  2020/ 11/ 11  11: 09
  3. # 一小时内只能调用该接口  4 次
  4. @limiter.limit( "4/hour")
  5. async def startSpider(*, request: Request, d_obj: dict):
  6.      if request.method ==  "POST":
  7.         statusDict = get_spider_status(shopId=d_obj.get( "shopId"))
  8.          if not statusDict.get( "data"):
  9.              return resp_422(message= '程序正在抓取中,请勿重复调度')
  10.         try:
  11.             result = all_run(d_obj.get( "shopId"))
  12.              return result
  13.         except:
  14.              return resp_401()
  15.      return  "这是一个GET请求"

这是我写的一个用于限制爬虫调度的一个方法,如果这个爬虫接口一小时中调度超过 4 次就返回调度超过指定次数的结果,当然代码中的 hour 也可以是 minute 或者 second,使用相对简单,大家可以一试并自行扩展

具体作用就是为了限制某接口在单位时间内被调用的次数,对于后端开发者来说可以减少对服务器的访问压力,而对于爬虫工程师而言,这也是从某种程度上保护我方数据的一种策略。

需要具体代码的小伙伴可以后台回复关键字:限制爬虫,进行获取。

------------------- End -------------------

往期精彩文章推荐:

欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

想加入Python学习群请在后台回复【入群

万水千山总是情,点个【在看】行不行

/今日留言主题/

随便说一两句吧~~


转载:https://blog.csdn.net/pdcfighting/article/details/111713857
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场