Python实现敏感词过滤

2023-11-17

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

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

方法一: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://blog.csdn.net/bestsort/article/details/82947639

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



以上,便是今天的内容,希望大家喜欢,欢迎「转发」或者点击「在看」支持,谢谢各位。




“扫一扫,关注我吧”
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python实现敏感词过滤 的相关文章

  • Pandas 面板Panel

    一 Panel介绍 Pandas 面板 Panel 是3维数据的存储结构 相当于一个存储 DataFrame 的字典 有3个轴 axis 分别给出描述涉及面板数据的操作的一些语义 具体如下 items axis 0 每个项目对应于内部包含的
  • 推荐系统:GBDT+LR简介

    1 GBDT LR简介 前面介绍的协同过滤和矩阵分解存在的劣势就是仅利用了用户与物品相互行为信息进行推荐 忽视了用户自身特征 物品自身特征以及上下文信息等 导致生成的结果往往会比较片面 而这次介绍的这个模型是2014年由Facebook提出
  • ubuntu通过apt安装软件的安装路径

    jdk usr lib jvm 具体jdk版本 tomcat usr share tomcat具体版本
  • 把ffmpeg放到后台自动运行

    最近一个项目 需要用ffmpeg把rtsp流转成ts流 由于rtsp服务器有可能关闭 需要自动的重启ffmpeg去连接rtsp服务器 1 编写一个用ffmpeg转TS流的脚本rtsp2ts sh ffmpeg i rtsp xx xx xx
  • pyd文件介绍

    pyd一般是python外的其他语言如C C 编写的python扩展模块 即python的一个动态链接库 与dll文件相当 在linux系统中一般为 so文件 也有的时候 为了对python文件进行加密 会把python模块编译成 pyd文
  • Unity基础学习之C#学习(二)

    C 程序三大结构 0 前言 1 分支结构 1 1 if语句 1 2 switch语句 2 循环结构 2 1 while循环 2 2 do while循环 2 3 for循环 最常用 2 4 foreach循环 主要用于迭代遍历 3 brea
  • oracle查询结果添加序列,SQL查询结果增加序列号

    SQL查询记录中增加序列号 根据学生成绩在查询结果中增加排名字段 1 SELECT ROW NUMBER OVER ORDER BY SCORE ASC AS RANK NAME SCORE FROM GRADE ORDER BY SCOR
  • vue-element-admin使用Tinymce富文本插件的踩坑填坑

    vue element admin项目的作者已经封装好了Tinymce富文本组件 我直接在Git上下载demo运用到自己项目里 这是Git地址 https github com PanJiaChen vue element admin 一
  • [0x7FFBFB69D3E0] ANOMALY: meaningless REX prefix used问题的修复

    0x7FFBFB69D3E0 ANOMALY meaningless REX prefix used 困扰了我几个礼拜 导致idea git 用不了 差点重装系统了 今天还好 解决了 用360 各种修复 各种操作 cmd 没有那串东西咯 各
  • 宏观经济浅学20210724

    https www bilibili com video BV1Ng4y1B7ig p 14 8大类 251个基本分类 700个品种 120万个商品
  • 写一篇有关机器学习的论文

    写一篇有关机器学习的论文 需要从以下几个方面进行阐述 机器学习的定义 首先要明确机器学习的定义 并简要介绍其历史发展 机器学习的分类 接着介绍机器学习的分类方法 例如监督学习 非监督学习 半监督学习 强化学习等 机器学习的应用 最后详细阐述
  • 智能城市dqn算法交通信号灯调度_新基建激发AI新动力,助推人工智能产业化落地进程...

    8月7日 9日 由中国计算机学会主办 香港中文大学 深圳 雷锋网联合承办的全球人工智能和机器人峰会在深圳开幕 峰会期间揭晓了 2020AI 最佳成长榜 千方科技旗下博观智能凭借在智慧城市多个细分领域的商用落地实力 斩获 AI 智慧城市 领域
  • python判断语句

    判断语句 if if 语句的判断语法 if 要判断的条件 条件成立时 要做的事情 else语法格式如下 if 要判断的条件 条件成立时 要做的事情 else 条件不成立 要做的事情 逻辑运算 只有多个条件都满足 才能执行后续代码 这个时候需
  • 两张动图-彻底明白TCP的三次握手与四次挥手

    背景描述 通过上一篇中网络模型中的IP层的介绍 我们知道网络层 可以实现两个主机之间的通信 但是这并不具体 因为 真正进行通信的实体是在主机中的进程 是一个主机中的一个进程与另外一个主机中的一个进程在交换数据 IP协议虽然能把数据报文送到目
  • C++课程设计之高校学生简单信息管理系统

    给大家分享一个用C 语言编写的高校学生信息管理系统 程序比较简单 也比较好理解 适合刚入门C 的程序小白 大学生做C 相关的课程设计也可以给你提供一些思路 或者在此基础上修改一下 添加一些自己的类和成员函数 让系统的功能更加的强大 系统功能
  • iOS APP 启动页和icon图标尺寸

    前言 记录一下竖屏iPhone启动页和icon图标尺寸 好记性不如烂笔头 1 启动页尺寸 320x480 640x960 640x1136 750x1334 1125x2436 1242x2208 1242x2688 828x1792 2
  • chatgpt小程序安装指引

    chatgpt小程序安装指引 JAVA 创建数据库 名字随意 数据库编码为utf8mb4 导入sql文件 在renren api db目录下面 第一次导入数据的先执行chatgpt sql文件 在根据日期先后顺序执行 已导入过的同志 根据更
  • html chm 打不开,Win7系统中出现CHM打不开的具体解决方法

    一部分用户在使用Win7系统的时候 出现CHM打不开的情况 该怎么处理呢 下文就为你们带来了Win7系统中出现CHM打不开的具体解决方法 方法一 1 可以对注册表进行操作 按快捷键 Win R 启动 运行 程序 2 在 运行 程序的输入框中
  • 舒尔补-边际概率-条件概率

    margin求边际概率的时候喜欢通过舒尔补的形式去操作信息矩阵 如p b c 求积分p a b c da 从上图可知 边缘概率直接看协方差矩阵比较方便 边际概率的方差就是取对应联合分布中相应的协方差块 信息矩阵是由舒尔补的形式计算 此形式也
  • GBDT调参指南

    GBDT分类器和回归器的大部分参数都是相同的 除了损失函数的选项有些不同 因此下面我们统一说明各个参数的意义以及在什么情境下做什么调整方法 一 GBDT的boosting框架参数 1 n estimators 代表弱学习器的最大个数 即最多

随机推荐

  • Python+OpenCV人脸识别签到考勤系统

    前言 本项目为IOT实验室人员签到考勤设计 系统实现功能 1 人员人脸识别并完成签到 签退 2 考勤时间计算 3 保存考勤数据为CSV格式 Excel表格 PS 本系统2D人脸识别 节约了繁琐的人脸识别训练部分 简洁快捷 该项目为测试版 正
  • mac电脑的C语言安装包,Mac上运行C/C++程序

    由于工作需要 要在Mac环境里面运行C程序 遇到的问题及解决方法如下 1 确认环境里是否安装了command line developer tools 打开Terminal终端 输入g 提示 xcrun error invalid acti
  • (新)Chrome浏览器自定义背景插件

    一 效果预览 二 项目回顾 1 原理 主要是利用js脚本在页面打开前插入一个背景图片容器 在通过相应的事件控制来实现该功能 2 功能 将网络图片设置为浏览器背景 3 使用 下载插件 gt 修改js文件 加入图片链接 添加浏览器扩展 gt 刷
  • C++学习记录6--srand(time(NULL)产生随机数

    time 函数 返回从1970 1 1 00 00 00到调用time 函数时所经过的时间 以秒为单位 所以是个整数 time NULL 或time 0 表示在内存中不存储返回的数值 头文件 include
  • 如何保证测试用例覆盖全面

    测试用例覆盖度一般是从以下几方面衡量的 1 测试需求的覆盖 保证所有需求都已经设计用例 2 测试特性的覆盖 保证所有不同类型已覆盖 如 功能测试 性能测试等 3 平台与层次的覆盖 保证所有平台有用例覆盖 不同层次都有设计用例 如业务层 接口
  • JavaScript随机生成颜色功能

    思路 实现一个函数 随机生成颜色 格式为 000000 颜色由a f A F 0 9 3种字母任意组成 且 后面是3位或者6位 只要随机生成一个数字是奇数或者偶数来随机出是3位或者6位 然后在随机其下标循环上面步骤确认的次数 functio
  • 设计模式之简单工厂模式(Simply Factory)摘录

    从设计模式的类型上来说 简单工厂模式是属于创建型模式 又叫静态工厂方法 Static Factory Method 模式 但不属于23种GOF设计模式之一 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例 简单工厂模式是工厂模式家族
  • 数据库索引

    3 1 概括 索引 Index 是数据库中的一种存储结构 用于快速查找数据 索引通常是在数据库表上创建的 可以用于加速查询 排序和数据的唯一性验证 索引可以理解为图书中的目录 通过目录我们可以很快找到页码对应的内容 当表中有大量数据需要查询
  • 计算机竞赛 基于计算机视觉的身份证识别系统

    0 前言 优质竞赛项目系列 今天要分享的是 基于机器视觉的身份证识别系统 该项目较为新颖 适合作为竞赛课题方向 学长非常推荐 更多资料 项目分享 https gitee com dancheng senior postgraduate 1
  • 封裝:WPF基于Vlc.DotNet.Wpf封装的视频播放器

    一 目的 应用自带的MediaElement播放器播放文件类型有限 有些格式还需要安装插件 由此应用第三方工具包Vlc DotNet Wpf封装支持多格式的视频播放器 二 环境 VS2019 Win10 Vlc DotNet Wpf HeB
  • 校友全剧透CMU :ME + 转CS + 其他主要项

    在CMU待了一个半学期了 对于留学 对于CMU 对于ME 对于转CS 对于CMU其它各种项目都了解的更多了一些 也有不同的体会 我想这篇文章应该会对任何一个申请了CMU 或者想申请CMU 甚至每一个想要出国留学的人都会有一点帮助 写下面这些
  • Easy-Es核心功能深度介绍

    背景 近期随着项目开源后热度的不断上涨 越来越多小伙伴开始对框架核心功能感兴趣 今天就让我带大家深入源码和架构 一起探索Easy Es 简称EE 的核心功能是如何被设计和实现的 和众多ORM框架一样 EE最为核心的功能就是CRUD 增删改查
  • selenium3之selenium-server-standalone-3.8.1.jar启动

    查看安装的selenium版本 下载对应版本的selenium server 下载地址 http selenium release storage googleapis com index html 需要先安装JDK 自行百度安装 启动se
  • Linux的NFS共享目录操作步骤

    首先准备两台Linux 一台服务器 一台客户机 IP地址可自行设置 两台防火墙都要关闭 配置服务器IP地址 172 20 10 11 配置客户机IP地址 172 20 10 12 先关闭防火墙 systemctl stop filewall
  • 【JavaScript】页面加载 解决Uncaught TypeError: Cannot set property of undefined at

    在初学js的时候 有同学会遇到 Uncaught TypeError Cannot set property onmouseover of undefined at html 的问题 这个问题牵扯到页面加载顺序的问题 我们知道 页面的加载顺
  • 使用Prometheus+Grafana+Spring Boot Actuator监控应用

    在企业级的应用中 监控往往至关重要 监控可以帮助我们预防故障 预测变化趋势 在达到阈值的时候报警 为排查生产问题提供更多的信息 如果我们不知道我们程序的运行情况 当线上系统出现了事故再去排查就需要花费更多的时间 如果能提前监控 就能早做准备
  • VScode的PHP远程调试模式Xdebug

    目录 第一步 安装VScode中相应插件 remote ssh的原理 ssh插件 PHP相关插件 第二步 安装对应PHP版本的xdebug 查看PHP具体配置信息的phpinfo页面 1 首先 打开php编辑器 新建一个php文件 例如 i
  • CentOS7下rsync实现服务器之间实时同步

    rsync简介 rsync是类unix系统下的数据镜像备份工具 使用快速增量备份工具Remote Sync可以远程同步 支持本地复制 或者与其他SSH rsync主机同步 文章主讲实际操作 不再进行详细叙述 想要了解更多可以查看百度百科 一
  • QT 编译报错“QWidget: Must construct a QApplication before a QWidget”

    一 错误原因 1 在构造QApplication之前创建了部件 某个类或者其子类中采用了静态的qWidget或者其子类 由于静态或者全局对象在 main 之前就产生了 所以 早于main 里的QApplication对象 2 混用 debu
  • Python实现敏感词过滤

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