根据请求的url、请求方法、请求参数、请求体进行唯一标识,进行比对,由于这四个数据加到一起,内容较长,因此使用求指纹的方式来进行去重判断。
指纹计算方法,最常用的就是md5、sha1等hash加密算法,来求指纹,找个地方保存指纹即可
def _to_bytes(string):
"""为了兼容py2和py3,利用_to_bytes方法,把所有的字符串转化为字节类型"""
if six.PY2:
if isinstance(string, str):
return string
else: # 如果是python2的unicode类型,转化为字节类型
return string.encode('utf-8')
elif six.PY3:
if isinstance(string, str): # 如果是python3的str类型,转化为字节类型
return string.encode("utf-8")
else:
return string
def gen_fp(url, method, data={}):
# 1. url排序:借助w3lib.url模块中的canonicalize_url方法
url = w3lib.url.canonicalize_url(url)
# 2. method不需要排序,只要保持大小写一致就可以 upper()方法全部转换为大写
method = method.upper()
# 3. data排序:如果有提供则是一个字典,如果没有则是空字典
data = data if data is not None else {}
data = sorted(data.items(), key=lambda x: x[0]) # 用sorted()方法 按data字典的key进行排序
# items()返回元祖 key参数表示按什么进行排序 x表示data.items() x[0]表示元祖第一个值,也就是data的键
# 4. 利用sha1计算获取指纹
s1 = sha1()
s1.update(_to_bytes(url)) # sha1计算的对象必须是字节类型
s1.update(_to_bytes(method))
s1.update(_to_bytes(str(data)))
fp = s1.hexdigest()
return fp
调用gen_fp(),传入相应的参数,返回的是加密过后的指纹,直接用来存储,建议使用redis 速度比较快,要做好持久化
简单的redis实现的代码,仅供参考
import redis
def add_hash_value(r, value):
# 如果不存在,把这个值给存进去
r.sadd("myset", value)
def existence(r, value):
# 校验是否存在这个值
result = r.sismember("myset", value)
if not result:
# 不存在调用这个函数
add_hash_value(r, value)
# 返回查询结果,供查询者使用
return result
if __name__ == '__main__':
r = redis.Redis(host='127.0.0.1', port=6379)
value = "b"
print(existence(r, value))