有了这个,网页反爬限制请求频率易如反掌!

本文介绍了如何利用Python的walrus库和Redis快速实现带过期时间的LRU缓存、全文搜索(支持拼写纠错)以及频率限制功能。walrus库为Redis提供了简洁的接口,使得这些复杂功能的实现变得简单易懂,尤其适合初学者。
摘要由CSDN通过智能技术生成

这是「进击的Coder」的第 548 篇技术分享

作者:kingname

来源:未闻 Code

阅读本文大概需要 6 分钟。

在以前的文章里面,我给大家介绍了使用 Python 自带的 LRU 缓存实现带有过期时间的缓存:实现有过期时间的 LRU 缓存。也讲过倒排索引:使用倒排索引极速提高字符串搜索效率。但这些代码对初学者来说比较难,写起来可能会出错。

实际上,这些功能其实都可以使用 Redis 来实现,而且每个功能只需要 1 分钟就能做出来。全文搜索功能在搜索英文的时候,甚至可以智能识别拼写错误的问题。

要实现这些功能,只需要做两件事:

  1. 安装 Redis

  2. Python 安装第三方库:walrus

安装完成以后,我们来看看它有多简单:

带过期时间的缓存装饰器

我们想实现一个装饰器,它装饰一个函数。让我在 1 分钟内多次访问函数的时候,使用缓存的数据;超过 1 分钟以后才重新执行函数的内部代码:

import time
import datetime
from walrus import Database

db = Database()
cache = db.cache()

@cache.cached(timeout=60)
def test():
    print('函数真正运行起来')
    now = datetime.datetime.now()
    return now

now = test()
print('函数返回的数据是:', now)
time.sleep(10) # 等待10秒,此时会使用缓存
print('函数返回的数据是:', test())
time.sleep(5) # 等待5秒,此时依然使用缓存
print('函数返回的数据是:', test())

time.sleep(50)  # 让时间超过缓存的时间
print('函数返回的数据是:', test())

运行效果如下图所示:

30fb2dd6c94dbd16a175590ca40ab087.png

全文搜索

我们再来看看全文搜索功能,实现起来也很简单:

from walrus import Database

db = Database()
search = db.Index('xxx')  # 这个名字随便取
poem1 = 'Early in the day it was whispered that we should sail in a boat, only thou and I, and never a soul in the world would know of this our pilgrimage to no country and to no end.'
poem2 = 'Had I the heavens’ embroidered cloths,Enwrought with golden and silver light'
poem3 = 'to be or not to be, that is a question.'

search.add('docid1', poem1) # 第一个参数不能重复
search.add('docid2', poem2)
search.add('docid3', poem3)


for doc in search.search('end'):
    print(doc['content'])

运行效果如下图所示:

86fb4dc62cdef19cc32a05ebf1e139c6.png

如果你想让他兼容拼写错误,那么可以把search = db.Index('xxx')改成search = db.Index('xxx’, metaphone=True),运行效果如下图所示:

19e5a177107630da6708555fe6ec521f.png

不过遗憾的是,这个全文搜索功能只支持英文。

频率限制

我们有时候要限制调用某个函数的频率,或者网站的某个接口要限制 IP 的访问频率。这个时候,使用walrus也可以轻松实现:

import time
from walrus import Database

db = Database()
rate = db.rate_limit('xxx', limit=5, per=60) # 每分钟只能调用5次

for _ in range(35):
    if rate.limit('xxx'):
        print('访问频率太高!')
    else:
        print('还没有触发访问频率限制')
    time.sleep(2)

运行效果如下图所示:

269764a4c9064d549326c64adfb305b4.png

其中参数limit表示能出现多少次,per表示在多长时间内。

rate.limit只要传入相同的参数,那么就会开始检查这个参数在设定的时间内出现的频率。

你可能觉得这个例子并不能说明什么问题,那么我们跟 FastAPI 结合一下,用来限制 IP 访问接口的频率。编写如下代码:

from walrus import Database, RateLimitException
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

db = Database()
rate = db.rate_limit('xxx', limit=5, per=60) # 每分钟只能调用5次

app = FastAPI()


@app.exception_handler(RateLimitException)
def parse_rate_litmit_exception(request: Request, exc: RateLimitException):
    msg = {'success': False, 'msg': f'请喝杯茶,休息一下,你的ip: {request.client.host}访问太快了!'}
    return JSONResponse(status_code=429, content=msg)

@app.get('/')
def index():
    return {'success': True}


@app.get('/important_api')
@rate.rate_limited(lambda request: request.client.host)
def query_important_data(request: Request):
    data = '重要数据'
    return {'success': True, 'data': data}

上面代码定义了一个全局的异常拦截器:

@app.exception_handler(RateLimitException)
def parse_rate_litmit_exception(request: Request, exc: RateLimitException):
    msg = {'success': False, 'msg': f'请喝杯茶,休息一下,你的ip: {request.client.host}访问太快了!'}
    return JSONResponse(status_code=429, content=msg)

在整个代码的任何地方抛出了RateLimitException异常,就会进入这里的逻辑中。

使用装饰器@rate.rate_limited装饰一个路由函数,并且这个装饰器要更靠近函数。路由函数接收什么参数,它就接收什么参数。在上面的例子中,我们只接收了request参数,用于获取访问者的 IP。发现这个 IP 的访问频率超过了限制,就抛出一个RateLimitException。于是前面定义好的全局拦截器就会拦截RateLimitException异常,拦截到以后返回我们定义好的报错信息。

在频率范围内访问页面,返回正常的 JSON 数据:

424faeb2621c53f620f8a2bf8e81afc5.png

频率超过设定的值以后,访问页面就会报错,如下图所示:

a146423930a307d80ae672d18c4e39cb.png

总结

walrusredis-py进行了很好的二次封装,用起来非常顺手。除了上面我提到的三个功能外,它还可以实现几行代码生成布隆过滤器,实现自动补全功能,实现简易图数据库等等。大家可以访问它的官方文档了解详细使用说明[1]。

参考文献

[1] 官方文档了解详细使用说明: https://walrus.readthedocs.io/en/latest/getting-started.html

8eb1597398a2bc88f48bb3381a8b7183.png

End

崔庆才的新书《Python3网络爬虫开发实战(第二版)》已经正式上市了!书中详细介绍了零基础用 Python 开发爬虫的各方面知识,同时相比第一版新增了 JavaScript 逆向、Android 逆向、异步爬虫、深度学习、Kubernetes 相关内容,‍同时本书已经获得 Python 之父 Guido 的推荐,目前本书正在七折促销中!

内容介绍:《Python3网络爬虫开发实战(第二版)》内容介绍

6fe0c931bce3db7552f07fc4d6d370f7.png

扫码购买

ad2390fa56293f2046c9a1896495b5af.png

好文和朋友一起看~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值