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

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

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

Ratelimiter

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

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

输出结果如下

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

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

达到了预期的要求

asyncio 异步中的使用

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

执行结果是一致的, 在一般的 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 3from fastapi import FastAPI 4from slowapi import Limiter, _rate_limit_exceeded_handler 5from slowapi.errors import RateLimitExceeded 6from slowapi.util import get_remote_address 7 8# 初始化 slowapi,注册进 fastapi 9limiter = Limiter(key_func=get_remote_address) 10FastAPI().state.limiter = limiter 11FastAPI().add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler) 12

具体调用方法

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

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

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

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

-------------------********************************** End **********-------------**-----********-**********************************

往期精彩文章推荐:

欢迎各位大佬点击链接加入群聊【helloworld开发者社区】:https://jq.qq.com/?_wv=1027&k=mBlk6nzX进群交流IT技术热点。

本文转自 https://mp.weixin.qq.com/s/ORWMtdutROYIigOQhXPKOg,如有侵权,请联系删除。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

sql注入

反引号是个比较特别的字符,下面记录下怎么利用0x00SQL注入反引号可利用在分隔符及注释作用,不过使用范围只于表名、数据库名、字段名、起别名这些场景,下面具体说下1)表名payload:select\from\users\whereuser\_id1limit0,1;!(https://o

python使用aiohttp通过设置代理爬取基金数据

说到python爬虫,我们就会想到它那强大的库,很多新手小白在选择框架的时候都会想到使用Scrapy,但是仅仅停留在会使用的阶段。在实际爬虫过程中遇到反爬机制是再常见不过的,今天为了增加对爬虫机制的理解,我们就通过手动实现多线程的爬虫过程,同时引入IP代理

Nginx反爬虫: 禁止某些User Agent抓取网站

一、概述网站反爬虫的原因不遵守规范的爬虫会影响网站的正常使用网站上的数据是公司的重要资产爬虫对网站的爬取会造成网站统计数据的污染常见反爬虫手段1\.根据IP访问频率封禁IP2\.设置账号登陆时长,账号访问过多封禁设置账号的登录限制,只有登录才能展现内容

Django中Admin中的一些参数配置

设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable