一.前言

近期项目有了一个过滤敏感词的功能需求,在网上找了一些方法及解说,发现DFA算法比较好用,容易实现,但很多文章解释得不太清楚,这里将其详细描述,并用python代码实现.

二.DFA算法详解

DFA,网上常译为确定有限自动机,俗话就是新数据在已有的数据基础上去有限次查找,比如:新数据为苹果公司年会,旧数据为苹果公司,这样就可以直接旧数据后面添加"年会"两个字.
DFA算法思想是将敏感词组通过建立嵌套字典的方式去构建敏感词链表(以一个特定字符’\x00’作为结束),然后遍历新词的每个字是否出现在敏感词链表中,如果出现,即为敏感词,提取出来,可以用"*"代替.
例如:敏感词词组有:新疆骚乱,爆炸,骚乱
则构建出来的敏感词链表分别为:
‘新’: {‘疆’: {‘骚’: {‘乱’: {’\x00’: 0}}}}
‘爆’: {‘炸’: {’\x00’: 0}}
‘骚’: {‘乱’: {’\x00’: 0}}
合为一个链表为:{‘新’: {‘疆’: {‘骚’: {‘乱’: {’\x00’: 0}}}}, ‘爆’: {‘炸’: {’\x00’: 0}}, ‘骚’: {‘乱’: {’\x00’: 0}}}
其中’\x00’是指以该字符作为链表结尾
这样,当新词作为输入遍历敏感词链表时,遇到特定字符\x00才算敏感词识别出来,否则都不算入敏感词

三.python实现

采用类管理,初始化一个空字典链表,特定结束符以及生成敏感词链表的函数

Proj_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
SensitiveWord_Path = os.path.join(Proj_path, "main/minganci.txt")
class DFAFilter(object):def __init__(self):self.keyword_chains = {}  # 关键词链表self.delimit = '\x00'  # 限定self.parse(SensitiveWord_Path)

接下来是parse()读取敏感词库表,通过add()将敏感词以嵌套字典的方式形成链表,即为level,访问level即可匹配敏感词

    def parse(self, path):with open(path, encoding='utf-8') as f:for keyword in f:self.add(str(keyword).strip())def add(self, keyword):keyword = keyword.lower()  # 关键词英文变为小写chars = keyword.strip()  # 关键字去除首尾空格和换行if not chars:  # 如果关键词为空直接返回returnlevel = self.keyword_chains# 遍历关键字的每个字for i in range(len(chars)):# 如果这个字已经存在字符链的key中就进入其子字典if chars[i] in level:level = level[chars[i]]else:if not isinstance(level, dict):breakfor j in range(i, len(chars)):level[chars[j]] = {}last_level, last_char = level, chars[j]level = level[chars[j]]last_level[last_char] = {self.delimit: 0}breakif i == len(chars) - 1:  # 最后一个字level[self.delimit] = 0print(level)

最后,将传入的词组进行敏感词过滤,遍历新词组,只有当前字在敏感词链表中才能加入敏感词

    def filter(self, message, repl="*"):message = message.lower()ret = []start = 0while start < len(message):level = self.keyword_chainsstep_ins = 0for char in message[start:]:# 新字在敏感词字典链表中if char in level:step_ins += 1# 特定字符不在当前字的value值里,嵌套遍历下一个if self.delimit not in level[char]:level = level[char]else:# 将敏感词以*代替,跳出for循环ret.append(repl * step_ins)start += step_ins - 1breakelse:# 新字不在敏感词字典链表中ret.append(message[start])breakelse:ret.append(message[start])start += 1return ''.join(ret)

四.全部代码

import os
Proj_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
SensitiveWord_Path = os.path.join(Proj_path, "main/minganci.txt")# DFA算法
class DFAFilter(object):def __init__(self):self.keyword_chains = {}  # 关键词链表self.delimit = '\x00'  # 限定self.parse(SensitiveWord_Path)def add(self, keyword):keyword = keyword.lower()  # 关键词英文变为小写chars = keyword.strip()  # 关键字去除首尾空格和换行if not chars:  # 如果关键词为空直接返回returnlevel = self.keyword_chains# 遍历关键字的每个字for i in range(len(chars)):# 如果这个字已经存在字符链的key中就进入其子字典if chars[i] in level:level = level[chars[i]]else:if not isinstance(level, dict):breakfor j in range(i, len(chars)):level[chars[j]] = {}last_level, last_char = level, chars[j]level = level[chars[j]]last_level[last_char] = {self.delimit: 0}breakif i == len(chars) - 1:  # 最后一个字level[self.delimit] = 0print(level)def parse(self, path):with open(path, encoding='utf-8') as f:for keyword in f:self.add(str(keyword).strip())def filter(self, message, repl="*"):message = message.lower()ret = []start = 0while start < len(message):level = self.keyword_chainsstep_ins = 0for char in message[start:]:# 新字在敏感词字典链表中if char in level:step_ins += 1# 特定字符不在当前字的value值里,嵌套遍历下一个if self.delimit not in level[char]:level = level[char]else:# 将敏感词以*代替,跳出for循环ret.append(repl * step_ins)start += step_ins - 1breakelse:# 新字不在敏感词字典链表中ret.append(message[start])breakelse:ret.append(message[start])start += 1return ''.join(ret)

敏感词或关键词过滤,DFA算法详解及python代码实现相关推荐

  1. kmeans算法详解和python代码实现

    kmeans算法详解和python代码实现 kmeans算法 无监督学习和监督学习 监督学习: 是通过已知类别的样本分类器的参数,来达到所要求性能的过程 简单来说,就是让计算机去学习我们已经创建好了的 ...

  2. 编辑距离算法详解和python代码

    编辑距离(Levenshtein Distance)算法详解和python代码 最近做NLP用到了编辑距离,网上学习了很多,看到很多博客写的有问题,这里做一个编辑距离的算法介绍,步骤和多种python ...

  3. K-means算法详解及python代码实现

    K-means算法 算法步骤 对数据的要求 算法的优缺点 算法需要注意的点 算法实现(python)(待更.......) 算法步骤 1.随机选取K个点作为初始聚类中心 2.计算各个数据到个聚类中心的 ...

  4. python机器学习算法.mobi_机器学习之ID3算法详解及python代码实现

    在生活中我们经常会用到决策树算法,最简单的就是二叉树了:相信大家也会又同样的困扰,手机经常收到各种短信,其中不乏很多垃圾短信.此时只要设置这类短信为垃圾短信手机就会自动进行屏蔽.减少被骚扰的次数,同时 ...

  5. python决策树 value_机器学习之ID3算法详解及python代码实现

    在生活中我们经常会用到决策树算法,最简单的就是二叉树了:相信大家也会又同样的困扰,手机经常收到各种短信,其中不乏很多垃圾短信.此时只要设置这类短信为垃圾短信手机就会自动进行屏蔽.减少被骚扰的次数,同时 ...

  6. k-means算法详解及python代码

    K-means算法原理 K-means聚类属于原型聚类(基于原型的聚类,prototype-based clustering).原型聚类算法假设聚类结构能够通过一组原型进行刻画,在现实聚类任务中极为常 ...

  7. 朴素贝叶斯算法详解及python代码实现

    朴素贝叶斯算法 算法原理 对数据的要求 算法的优缺点 算法需要注意的点 算法实现(python)(待更.......) 算法原理 P(Ck∣xi)=p(xi∣ck)∗p(ck)p(xi)=p(x1∣c ...

  8. Simhash算法详解及python实现

    Simhash算法详解及python实现 GoogleMoses Charikar发表的一篇论文"detecting near-duplicates for web crawling&quo ...

  9. AC自动机算法详解以及Java代码实现

    详细介绍了AC自动机算法详解以及Java代码实现. 文章目录 1 概念和原理 2 节点定义 3 构建Trie前缀树 3.1 案例演示 4 构建fail失配指针 4.1 案例演示 5 匹配文本 5.1 ...

最新文章

  1. 两个关于.NET读取EXCEL文件的问题,记下来,很有用!
  2. org.apache.jasper.JasperException: /jsp/menu.jsp (line: 8, column: 1) Page directive
  3. GraphSAGE节点分类
  4. for循环false 终止 python_python3.5.1给用户3次无效的尝试,然后终止pgm(Simple FOR循环)...
  5. 2021-2025年中国传感器融合行业市场供需与战略研究报告
  6. Linux 常用命令——不看白不看
  7. wireshark+rtmp协议分析
  8. UML统一建模语言快速入门
  9. 西门子1200plc与施耐德变频器modbus通讯程序
  10. cad详图怎么画_CAD结构图怎么画?手把手教你CAD结构图的绘制方法
  11. docker容器怎么设置开机启动
  12. 10 分钟了解 Flutter 跨平台方案
  13. ROS学习笔记4_订阅者Subscriber
  14. jQuery.closest() 函数详解
  15. CQ CSP-S2021游记
  16. Life Restart 人生模拟器 网址
  17. 不使用redis,在前后端分离项目的条件下将验证码进行储存
  18. Oracle 11g RAC 迁移至单机
  19. 国产手机启用鸿蒙系统,国产机会抛弃安卓系统?华为启用全新自研“鸿蒙”系统,你会买吗...
  20. 唤醒词检测引擎Snowboy

热门文章

  1. [2017年第八届真题] 分巧克力
  2. 【解决方案】EasyNVR+EasyNVS视频解决方案实现内外网视频流互通互联,实现智慧水利智慧化转变
  3. HTML5 完美解决javascript中iphone手机和android手机复制文本到剪切板问题
  4. Type-C转3.5mm音频转接器的由来
  5. 2021-08-18 【O2 优化是什么东西?氧气优化!?】
  6. 报错:SON parse error: Cannot deserialize value of type `java.lang.String` from Array value (token `Jso
  7. 【Leetcode】748. Shortest Completing Word
  8. 【Spring Boot】数据校验
  9. 每人100万!6位院士,获领域重要奖项!
  10. WEB前端学习路线2023完整版(附视频教程+学习资料)