摘要:
遍历key,在跟进value的类型遍历value是否包含指定字符串 search_strings ,这里使用redis-py
库,默认只能处理utf-8编码,如果存在其他编码会出现问题。
使用decode_responses=True可以顺利的遍历不同类型的value,不使用该参数可以顺利遍历不同编码的key。
正文:
源代码
import redis
import chardet
# 连接到Redis服务器
r = redis.Redis(host=' xx', port=6935, db=9, decode_responses=True)
# r = redis.Redis(host=' xx', port=6935, db=9)
# 假设我们有以下key和它们对应的数据类型
# key1: 字符串
# key2: 列表
# key3: 集合
# key4: 有序集合
# key5: 哈希表
# 函数:根据key的数据类型执行不同的操作
def handle_data_by_type(key, file, search_strings):
try:
# 获取key的类型
data_type = r.type(key)
# b'string'
if data_type == 'string':
# 对于字符串,直接获取并打印
value = r.get(key)
# print(f"String: {value}")
has_attr(value, key, file, search_strings)
elif data_type == 'list':
# 对于列表,遍历并打印每个元素
values = r.lrange(key, 0, -1) # 获取列表中的所有元素
for value in values:
has_attr(value, key, file, search_strings)
# print(f"List Element: {value}")
elif data_type == 'set':
# 对于集合,遍历并打印每个元素(注意集合是无序的)
members = r.smembers(key)
for member in members:
# has_attr(member, key, file, search_strings)
print(f"Set Member: {member}")
elif data_type == 'zset':
# 对于有序集合,遍历并打印每个元素及其分数
for member, score in r.zscan_iter(key):
print(f"Sorted Set Member: {member}, Score: {score}")
elif data_type == 'hash':
# 对于哈希表,遍历并打印每个字段及其值
for field in r.hkeys(key):
# result = chardet.detect(field)
# encoding = result['encoding']
value = r.hget(key, field)
has_attr(value, key, file, search_strings)
# print(f"Hash Field: {field}, Value: {value}")
else:
print(f"Unknown data type for key: {key}")
except Exception as e:
print(f"Error processing key: {key}, error: {e}")
# 示例:处理不同的key
# handle_data_by_type('key1') # 假设key1是字符串
# handle_data_by_type('key2') # 假设key2是列表
# handle_data_by_type('key3') # 假设key3是集合
# handle_data_by_type('key4') # 假设key4是有序集合
# handle_data_by_type('key5') # 假设key5是哈希表
# 注意:上面的'key1'到'key5'及其数据类型只是示例,你需要根据实际情况替换它们
def has_attr(value, key, file, search_strings):
if value: # 确保value不是None
# 检查value是否包含任何一个search_strings中的字符串
for search_string in search_strings:
if search_string in value:
# print(f"Key: {key}, Value: {value}, contains: {search_string}")
file.write(f"Key: {key}, Value: {value}, contains: {search_string}\n")
break # 如果已经找到一个匹配的字符串,可以跳出内层循环
if __name__ == '__main__':
# 连接到Redis服务器
# r = redis.Redis(host='10.14.177.66', port=6935, db=9, decode_responses=True)
# 要搜索的字符串列表
search_strings = ['xxx ']
# 使用SCAN命令迭代遍历Redis中的所有key
cursor = '0'
with open('20240813_1916.txt', 'a') as file:
while cursor != 0:
cursor, keys = r.scan(cursor=cursor, match='*', count=10)
# print(f"Cursor: {cursor}, Keys: {keys}, Length: {len(keys)}")
for key in keys:
try:
# 尝试将键解码为 UTF-8 字符串
decoded_key = key.decode('utf-8')
# print(f"Processing key: {key}")
handle_data_by_type(decoded_key, file, search_strings)
# 获取key对应的value
# value = r.get(key)
# if value: # 确保value不是None
# # 检查value是否包含任何一个search_strings中的字符串
# for search_string in search_strings:
# if search_string in value:
# print(f"Key: {key}, Value: {value}, contains: {search_string}")
# break # 如果已经找到一个匹配的字符串,可以跳出内层循环
except Exception as e:
print(f"Error scanning keys, error: {e}")
# 注意:上面的代码假设所有value都是字符串。如果value是其他类型(如列表、集合等),则需要相应地调整检查逻辑。
在Python的redis
库或类似的Redis客户端库中,decode_responses=True
是一个非常重要的参数,它决定了从Redis服务器接收到的响应数据是如何被处理的。
解释
默认情况下,当你从Redis数据库读取数据时(比如使用get
、hget
、lrange
等命令),返回的数据类型是bytes
(字节串)。这是因为Redis本身是以二进制安全的方式存储数据的,所以它返回的数据也是原始的二进制数据。
当你设置decode_responses=True
时,客户端库会自动将接收到的bytes
类型数据解码为字符串(str
)。这通常意味着,如果你的数据原本是以UTF-8或其他编码方式存储的文本,那么你就可以直接以字符串的形式处理这些数据,而无需手动进行解码。
使用场景
- 文本数据处理:如果你的Redis数据库主要用于存储和检索文本数据(如字符串、列表中的字符串元素等),那么设置
decode_responses=True
可以大大简化数据处理流程。 - 二进制数据处理:如果你需要处理的是二进制数据(如图片、视频文件等),那么你可能不希望自动解码响应。在这种情况下,你应该保持默认设置(即不设置
decode_responses
或显式设置为False
),以便以bytes
类型接收数据。
--end---