'''
DFA算法过滤敏感词
'''

'''
DFA敏感词存放结构(公用前缀)
{
    's': {
        'e': {
            'x': {
                'y': {
                    '\x00': 0
                }
            }
        }
    },
    'h': {
        'e': {
            'l': {
                'l': {
                    'o': {
                        '\x00': 0
                    }
                },
                'p': {
                    '\x00': 0,
                    'l': {
                        'i': {
                            'n': {
                                'e': {
                                    '\x00': 0
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
'''
import pickle
class DFAFilter():

    def __init__(self):
        # 存放敏感词的字典
        self.keyword_chains = {}
        # 设置分隔符为 '\x00',用于在特定场合下作为字符串的分隔标志
        self.delimit = '\x00'

    def add(self, keyword):
        """
        将给定的敏感词添加到敏感词链中。
        :param keyword: 需要添加的关键词,将被转换为小写并去除首尾空白。
        :return: 无返回值。
        """
        # keyword = keyword.lower()  # 将敏感词转换为小写
        chars = keyword.strip()  # 去除敏感词的首尾空白字符
        if not chars:  # 如果处理后的敏感词为空,则直接返回
            return
        level = self.keyword_chains  # 初始化根级别

        # 遍历敏感词中的每个字符,逐级向下创建或更新字典结构
        for i in range(len(chars)):
            # 如果字符在当前级别存在,说明可以公用,进入下一级
            if chars[i] in level:
                level = level[chars[i]]
            # 如果不存在,从当前位置创建所有缺失级别到敏感词末尾
            else:
                for j in range(i, len(chars)):
                    level[chars[j]] = {}
                    last_level, last_char = level, chars[j]
                    level = level[chars[j]]
                # 在最后一个创建的级别中,添加一个以self.delimit为键,值为0的项
                last_level[last_char] = {self.delimit: 0}
                break

        # 如果遍历到了关键词的末尾,则在当前级别添加一个以self.delimit为键,值为0的项
        if i == len(chars) - 1:
            level[self.delimit] = 0

    def parse(self, path):
        if path.endswith('pkl'):
            with open(path, "rb") as f:
                data = pickle.load(f)
                for keyword in data:
                    self.add(keyword.strip())
        else:
            with open(path, "r", encoding='utf-8') as f:
                for keyword in f:
                    self.add(keyword.strip())

    def filter(self, path, repl="*"):
        """
        过滤给定消息中的敏感关键词,用指定字符替换。
        参数:
        - message: 待过滤的字符串消息。
        - repl: 用于替换敏感词的字符,默认为"*"。
        返回值:
        - 过滤后的字符串。
        """
        with open(path, mode='r', encoding='utf-8') as f:
            message = f.read()
            # message = message.lower()
            ret = []  # 存储过滤后的字符
            start = 0  # 指向当前处理的字符位置
            while start < len(message):
                level = self.keyword_chains  # 初始化敏感词层级
                step_ins = 0  # 记录当前嵌套层级
                for char in message[start:]:
                    if char in level:
                        step_ins += 1
                        if self.delimit not in level[char]:
                            level = level[char]
                        else:
                            # 当遇到分隔符时,添加替换字符到结果中,并调整起始位置
                            ret.append(repl * step_ins)
                            start += step_ins - 1
                            break
                    else:
                        # 当字符不在关键词列表中,添加原字符到结果中,并结束当前循环
                        ret.append(message[start])
                        break
                start += 1  # 更新起始位置
            f.close()
            return ''.join(ret)  # 将结果列表转换为字符串并返回

    '''
    将过滤敏感词之后的message重新sink
    '''
    def outputNoSensitiveness(self, outputPath, inputMessage):
        filterSensitiveness = open(outputPath, 'w')
        filterSensitiveness.write(inputMessage)
        filterSensitiveness.close()



if __name__ == '__main__':
    dfa = DFAFilter()
    dfa.parse('data.pkl')
    # dfa.parse('C:\job\AI数据集平台工具\数据\sensitive_words.txt')
    print(f"敏感词字典为:{dfa.keyword_chains}")
    later_filter = dfa.filter('C:\job\AI数据集平台工具\数据\DFA.txt')
    print(f"敏感词过滤后的结果为:{later_filter}")
    output = dfa.outputNoSensitiveness('C:\job\AI数据集平台工具\数据\\fliter_sensitiveness.txt', later_filter)

附:敏感词关键字.pkl方式创建代码,以下:

import pickle

if __name__ == '__main__':

    # 创建一个字典对象
    data = ['flink', 'spark', 'hive', 'FLINK', 'SPARK', 'HIVE', '实时', '离线']

    # 打开一个文件用于写入
    with open('data.pkl', 'wb') as f:
        # 使用pickle.dump()将字典对象序列化并保存到文件中
        pickle.dump(data, f)

附:过滤消息样本数据,以下:

flink是一个实时计算引擎,flink处理时间为毫秒级别。
flink采用流的模式读取数据
flink使用事件时间而不是spark的处理时间
flink通过窗口进行聚合计算,checkpoint是flink的核心容错机制,其通过快照的方式定期将各个operator的状态存储下来,checkpoint设置的越大,小文件越少
flink通过watermark水位线处理延迟和乱序数据,是flink为了处理eventtime提出的新的机制,侧输出流sideoutput是针对超过了最大允许的延迟时间的最后兜底机制...
SPARK是离线计算引擎
SPARK使用处理时间作为时间语义
SPARK是批处理,也有近似实时的微批处理,spark处理时间为秒级别的
hive是离线数仓
hive用于处理离线数据,时间为T-1

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐