Python实现敏感词过滤的4种方法

在我们生活中的一些场合经常会有一些不该出现的敏感词,我们通常会使用*去屏蔽它,例如:尼玛 -> **,一些骂人的敏感词和一些政治敏感词都不应该出现在一些公共场合中,这个时候我们就需要一定的手段去屏蔽这些敏感词。下面我来介绍一些简单版本的敏感词屏蔽的方法。

(我已经尽量把脏话做成图片的形式了,要不然文章发不出去)

方法一:replace过滤

replace就是最简单的字符串替换,当一串字符串中有可能会出现的敏感词时,我们直接使用相应的replace方法用*替换出敏感词即可。

缺点:

文本和敏感词少的时候还可以,多的时候效率就比较差了

import datetime
now = datetime.datetime.now()
print(filter_sentence, " | ", now)

如果是多个敏感词可以用列表进行逐一替换

for i in dirty:
 speak = speak.replace(i, '*')
print(speak, " | ", now)

方法二:正则表达式过滤

正则表达式算是一个不错的匹配方法了,日常的查询中,机会都会用到正则表达式,包括我们的爬虫,也都是经常会使用到正则表达式的,在这里我们主要是使用“|”来进行匹配,“|”的意思是从多个目标字符串中选择一个进行匹配。写个简单的例子:

import re

def sentence_filter(keywords, text):
 return re.sub("|".join(keywords), "***", text)

print(sentence_filter(dirty, speak))

方法三:DFA过滤算法

DFA的算法,即Deterministic Finite Automaton算法,翻译成中文就是确定有穷自动机算法。它的基本思想是基于状态转移来检索敏感词,只需要扫描一次待检测文本,就能对所有敏感词进行检测。(实现见代码注释)

#!/usr/bin/env python
# -*- coding:utf-8 -*-
# @Time:2020/4/15 11:40
# @Software:PyCharm
# article_add: https://www.cnblogs.com/JentZhang/p/12718092.html
__author__ = "JentZhang"
import json

MinMatchType = 1 # 最小匹配规则
MaxMatchType = 2 # 最大匹配规则

class DFAUtils(object):
 """
 DFA算法
 """

 def __init__(self, word_warehouse):
  """
  算法初始化
  :param word_warehouse:词库
  """
  # 词库
  self.root = dict()
  # 无意义词库,在检测中需要跳过的(这种无意义的词最后有个专门的地方维护,保存到数据库或者其他存储介质中)
  self.skip_root = [' ', '&', '!', '!', '@', '#', '$', '¥', '*', '^', '%', '?', '?', '<', '>', "《", '》']
  # 初始化词库
  for word in word_warehouse:
   self.add_word(word)

 def add_word(self, word):
  """
  添加词库
  :param word:
  :return:
  """
  now_node = self.root
  word_count = len(word)
  for i in range(word_count):
   char_str = word[i]
   if char_str in now_node.keys():
    # 如果存在该key,直接赋值,用于下一个循环获取
    now_node = now_node.get(word[i])
    now_node['is_end'] = False
   else:
    # 不存在则构建一个dict
    new_node = dict()

    if i == word_count - 1: # 最后一个
     new_node['is_end'] = True
    else: # 不是最后一个
     new_node['is_end'] = False

    now_node[char_str] = new_node
    now_node = new_node

 def check_match_word(self, txt, begin_index, match_type=MinMatchType):
  """
  检查文字中是否包含匹配的字符
  :param txt:待检测的文本
  :param begin_index: 调用getSensitiveWord时输入的参数,获取词语的上边界index
  :param match_type:匹配规则 1:最小匹配规则,2:最大匹配规则
  :return:如果存在,则返回匹配字符的长度,不存在返回0
  """
  flag = False
  match_flag_length = 0 # 匹配字符的长度
  now_map = self.root
  tmp_flag = 0 # 包括特殊字符的敏感词的长度

  for i in range(begin_index, len(txt)):
   word = txt[i]

   # 检测是否是特殊字符"
   if word in self.skip_root and len(now_map) < 100:
    # len(nowMap)<100 保证已经找到这个词的开头之后出现的特殊字符
    tmp_flag += 1
    continue

   # 获取指定key
   now_map = now_map.get(word)
   if now_map: # 存在,则判断是否为最后一个
    # 找到相应key,匹配标识+1
    match_flag_length += 1
    tmp_flag += 1
    # 如果为最后一个匹配规则,结束循环,返回匹配标识数
    if now_map.get("is_end"):
     # 结束标志位为true
     flag = True
     # 最小规则,直接返回,最大规则还需继续查找
     if match_type == MinMatchType:
      break
   else: # 不存在,直接返回
    break

  if tmp_flag < 2 or not flag: # 长度必须大于等于1,为词
   tmp_flag = 0
  return tmp_flag

 def get_match_word(self, txt, match_type=MinMatchType):
  """
  获取匹配到的词语
  :param txt:待检测的文本
  :param match_type:匹配规则 1:最小匹配规则,2:最大匹配规则
  :return:文字中的相匹配词
  """
  matched_word_list = list()
  for i in range(len(txt)): # 0---11
   length = self.check_match_word(txt, i, match_type)
   if length > 0:
    word = txt[i:i + length]
    matched_word_list.append(word)
    # i = i + length - 1
  return matched_word_list

 def is_contain(self, txt, match_type=MinMatchType):
  """
  判断文字是否包含敏感字符
  :param txt:待检测的文本
  :param match_type:匹配规则 1:最小匹配规则,2:最大匹配规则
  :return:若包含返回true,否则返回false
  """
  flag = False
  for i in range(len(txt)):
   match_flag = self.check_match_word(txt, i, match_type)
   if match_flag > 0:
    flag = True
  return flag

 def replace_match_word(self, txt, replace_char='*', match_type=MinMatchType):
  """
  替换匹配字符
  :param txt:待检测的文本
  :param replace_char:用于替换的字符,匹配的敏感词以字符逐个替换,如"你是大王八",敏感词"王八",替换字符*,替换结果"你是大**"
  :param match_type:匹配规则 1:最小匹配规则,2:最大匹配规则
  :return:替换敏感字字符后的文本
  """
  tuple_set = self.get_match_word(txt, match_type)
  word_set = [i for i in tuple_set]
  result_txt = ""
  if len(word_set) > 0: # 如果检测出了敏感词,则返回替换后的文本
   for word in word_set:
    replace_string = len(word) * replace_char
    txt = txt.replace(word, replace_string)
    result_txt = txt
  else: # 没有检测出敏感词,则返回原文本
   result_txt = txt
  return result_txt

if __name__ == '__main__':
 dfa = DFAUtils(word_warehouse=word_warehouse)
 print('词库结构:', json.dumps(dfa.root, ensure_ascii=False))
 # 待检测的文本
 msg = msg
 print('是否包含:', dfa.is_contain(msg))
 print('相匹配的词:', dfa.get_match_word(msg))
 print('替换包含的词:', dfa.replace_match_word(msg))

方法四:AC自动机

AC自动机需要有前置知识:Trie树(简单介绍:又称前缀树,字典树,是用于快速处理字符串的问题,能做到快速查找到一些字符串上的信息。)

详细参考:

https://www.luogu.com.cn/blog/juruohyfhaha/trie-xue-xi-zong-jie

ac自动机,就是在tire树的基础上,增加一个fail指针,如果当前点匹配失败,则将指针转移到fail指针指向的地方,这样就不用回溯,而可以路匹配下去了。

详细匹配机制我在这里不过多赘述,关于AC自动机可以参考一下这篇文章:

https://www.jb51.net/article/128711.htm

python可以利用ahocorasick模块快速实现:

# python3 -m pip install pyahocorasick
import ahocorasick

def build_actree(wordlist):
 actree = ahocorasick.Automaton()
 for index, word in enumerate(wordlist):
  actree.add_word(word, (index, word))
 actree.make_automaton()
 return actree

if __name__ == '__main__':
 actree = build_actree(wordlist=wordlist)
 sent_cp = sent
 for i in actree.iter(sent):
  sent_cp = sent_cp.replace(i[1][1], "**")
  print("屏蔽词:",i[1][1])
 print("屏蔽结果:",sent_cp)

当然,我们也可以手写一份AC自动机,具体参考:

class TrieNode(object):
 __slots__ = ['value', 'next', 'fail', 'emit']

 def __init__(self, value):
  self.value = value
  self.next = dict()
  self.fail = None
  self.emit = None

class AhoCorasic(object):
 __slots__ = ['_root']

 def __init__(self, words):
  self._root = AhoCorasic._build_trie(words)

 @staticmethod
 def _build_trie(words):
  assert isinstance(words, list) and words
  root = TrieNode('root')
  for word in words:
   node = root
   for c in word:
    if c not in node.next:
     node.next[c] = TrieNode(c)
    node = node.next[c]
   if not node.emit:
    node.emit = {word}
   else:
    node.emit.add(word)
  queue = []
  queue.insert(0, (root, None))
  while len(queue) > 0:
   node_parent = queue.pop()
   curr, parent = node_parent[0], node_parent[1]
   for sub in curr.next.itervalues():
    queue.insert(0, (sub, curr))
   if parent is None:
    continue
   elif parent is root:
    curr.fail = root
   else:
    fail = parent.fail
    while fail and curr.value not in fail.next:
     fail = fail.fail
    if fail:
     curr.fail = fail.next[curr.value]
    else:
     curr.fail = root
  return root

 def search(self, s):
  seq_list = []
  node = self._root
  for i, c in enumerate(s):
   matched = True
   while c not in node.next:
    if not node.fail:
     matched = False
     node = self._root
     break
    node = node.fail
   if not matched:
    continue
   node = node.next[c]
   if node.emit:
    for _ in node.emit:
     from_index = i + 1 - len(_)
     match_info = (from_index, _)
     seq_list.append(match_info)
    node = self._root
  return seq_list

if __name__ == '__main__':
 aho = AhoCorasic(['foo', 'bar'])
 print aho.search('barfoothefoobarman')

以上便是使用Python实现敏感词过滤的四种方法,前面两种方法比较简单,后面两种偏向算法,需要先了解算法具体实现的原理,之后代码就好懂了。(DFA作为比较常用的过滤手段,建议大家掌握一下~)

最后附上敏感词词库:

https://github.com/qloog/sensitive_words

以上就是Python实现敏感词过滤的4种方法的详细内容,更多关于python 敏感词过滤的资料请关注我们其它相关文章!

(0)

相关推荐

  • python用类实现文章敏感词的过滤方法示例

    过滤一遍并将敏感词替换之后剩余字符串中新组成了敏感词语,这种情况就要用递归来解决,直到过滤替换之后的结果和过滤之前一样时才算结束 第一步:建立一个敏感词库(.txt文本) 第二步:编写代码在文章中过滤敏感词(递归实现) # -*- coding: utf-8 -*- # author 代序春秋 import os import chardet # 获取文件目录和绝对路径 curr_dir = os.path.dirname(os.path.abspath(__file__)) # os.path

  • 利用Python正则表达式过滤敏感词的方法

    问题描述:很多网站会对用户发帖内容进行一定的检查,并自动把敏感词修改为特定的字符. 技术要点: 1)Python正则表达式模块re的sub()函数: 2)在正则表达式语法中,竖线"|"表示二选一或多选一. 参考代码: 以上这篇利用Python正则表达式过滤敏感词的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们.

  • 浅谈Python 敏感词过滤的实现

    一个简单的实现 class NaiveFilter(): '''Filter Messages from keywords very simple filter implementation >>> f = NaiveFilter() >>> f.add("sexy") >>> f.filter("hello sexy baby") hello **** baby ''' def __init__(self):

  • python 实现敏感词过滤的方法

    如下所示: #!/usr/bin/python2.6 # -*- coding: utf-8 -*- import time class Node(object): def __init__(self): self.children = None # The encode of word is UTF-8 def add_word(root,word): node = root for i in range(len(word)): if node.children == None: node.c

  • Python 实现王者荣耀中的敏感词过滤示例

    王者荣耀的火爆就不用说了,但是一局中总会有那么几个挂机的,总能看到有些人在骂人,我们发现,当你输入一些常见的辱骂性词汇时,系统会自动将该词变成"*",作为python初学者,就想用python来实现这一功能. 步骤很简单所以就用交互式演示 首先我们要知道王者荣耀有哪些敏感词汇,然后放到一个元组, 第二步用户接收输入的消息 第三步处理敏感词汇 最后输出处理后的消息. >>> words=('金币', '挂', '傻逼', '猪', '你妈') #创建一个敏感词汇库 &g

  • Python实现敏感词过滤的4种方法

    在我们生活中的一些场合经常会有一些不该出现的敏感词,我们通常会使用*去屏蔽它,例如:尼玛 -> **,一些骂人的敏感词和一些政治敏感词都不应该出现在一些公共场合中,这个时候我们就需要一定的手段去屏蔽这些敏感词.下面我来介绍一些简单版本的敏感词屏蔽的方法. (我已经尽量把脏话做成图片的形式了,要不然文章发不出去) 方法一:replace过滤 replace就是最简单的字符串替换,当一串字符串中有可能会出现的敏感词时,我们直接使用相应的replace方法用*替换出敏感词即可. 缺点: 文本和敏感词少

  • Python 敏感词过滤的实现示例

    目录 一个简单的实现 使用BSF(宽度优先搜索)进行实现 使用DFA(Deterministic Finite Automaton)进行实现 一个简单的实现 主要是通过循环和replace的方式进行敏感词的替换 class NaiveFilter(): '''Filter Messages from keywords very simple filter implementation >>> f = NaiveFilter() >>> f.parse("fil

  • Python基于DFA算法实现内容敏感词过滤

    DFA 算法是通过提前构造出一个 树状查找结构,之后根据输入在该树状结构中就可以进行非常高效的查找. 设我们有一个敏感词库,词酷中的词汇为: 我爱你 我爱他 我爱她 我爱你呀 我爱他呀 我爱她呀 我爱她啊 那么就可以构造出这样的树状结构: 设玩家输入的字符串为:白菊我爱你呀哈哈哈 我们遍历玩家输入的字符串 str,并设指针 i 指向树状结构的根节点,即最左边的空白节点: str[0] = ‘白’ 时,此时 tree[i] 没有指向值为 ‘白’ 的节点,所以不满足匹配条件,继续往下遍历 str[1

  • java利用DFA算法实现敏感词过滤功能

    前言 敏感词过滤应该是不用给大家过多的解释吧?讲白了就是你在项目中输入某些字(比如输入xxoo相关的文字时)时要能检 测出来,很多项目中都会有一个敏感词管理模块,在敏感词管理模块中你可以加入敏感词,然后根据加入的敏感词去过滤输 入内容中的敏感词并进行相应的处理,要么提示,要么高亮显示,要么直接替换成其它的文字或者符号代替. 敏感词过滤的做法有很多,我简单描述我现在理解的几种: ①查询数据库当中的敏感词,循环每一个敏感词,然后去输入的文本中从头到尾搜索一遍,看是否存在此敏感词,有则做相 应的处理,

  • Jsp敏感词过滤的示例代码

    大部分论坛.网站等,为了方便管理,都进行了关于敏感词的设定. 在多数网站,敏感词一般是指带有敏感政治倾向(或反执政党倾向).暴力倾向.不健康色彩的词或不文明语,也有一些网站根据自身实际情况,设定一些只适用于本网站的特殊敏感词. 比如,当你发贴的时候带有某些事先设定的词时,这个贴是不能发出的.或者这个词被自动替换为星号(*)或叉号(X)等,或者说是被和谐掉了. 在我看来敏感词过滤最重要的是在写过滤词汇的算法,如何过滤出大批量的敏感词,我感觉DFA的思想不错 DFA简介 在实现文字过滤的算法中,DF

  • Java实现敏感词过滤实例

    敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来一看,整个过程如下:读取敏感词库.如果HashSet集合中,获取页面上传文字,然后进行匹配.我就想这个过程肯定是非常慢的.对于他这个没有接触的人来说我想也只能想到这个,更高级点就是正则表达式.但是非常遗憾,这两种方法都是不可行的.当然,在我意识里没有我也没有认知到那个算法可以解决问题,但是Googl

  • js实现敏感词过滤算法及实现逻辑

    最近弄了一个用户发表评论的功能,用户上传了评论,再文章下可以看到自己的评论,但作为社会主义接班人,践行社会主义核心价值观,所以给评论敏感词过滤的功能不可少,在网上找了资料,发现已经有非常成熟的解决方案. 常用的方案用这么两种 1.全文搜索,逐个匹配.这种听起来就不够高大上,在数据量大的情况下,会有效率问题,文末有比较 2.DFA算法-确定有限状态自动机 附上百科链接确定有限状态自动机 DFA算法介绍 DFA是一种计算模型,数据源是一个有限个集合,通过当前状态和事件来确定下一个状态,即 状态+事件

随机推荐