【Java Web】敏感词过滤

news2024/9/24 13:17:06

一、前缀树

假设有敏感词:b,abc,abd,bcd,abcd,efg,hii
那么前缀树可以构造为:
在这里插入图片描述

二、敏感词过滤器

package com.nowcoder.community.util;

import org.apache.commons.lang3.CharUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component

public class SensitiveFilter {

    private static final Logger logger = LoggerFactory.getLogger(SensitiveFilter.class);

    // 敏感词替换
    private static final String REPLACEMENT = "***";

    // 初始化根节点
    private TrieNode rootNode = new TrieNode();


    // 实例被创建后自动完成敏感词库的加载和前缀树的构建
    @PostConstruct
    public void init(){
        try (
                InputStream is = this.getClass().getClassLoader().getResourceAsStream("sensitive-words.txt");  // 通过类加载器获取敏感词库的字节流
                // 字节流转换为字符流
                // 然后在转换为具有缓冲区、读取性能高的BufferedReader
                BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        ){
            String keyword;
            while((keyword=reader.readLine())!=null){ // 每读一行获取一个keywords
                // 添加到前缀树
                this.addKeyword(keyword);
            }

        } catch (IOException e) {
            logger.error("加载敏感词汇表失败:"+e.getMessage());
            throw new RuntimeException(e);
        }
    }

    // 将一个敏感词加入前缀树
    private void addKeyword(String keyword){
        TrieNode tempNode = rootNode;
        for(int i=0; i<keyword.length(); i++){
            char c = keyword.charAt(i);
            TrieNode subNode = tempNode.getSubNode(c);

            if(subNode == null){
                // 初始化子节点
                subNode = new TrieNode();
                tempNode.addSubNode(c,subNode);
            }
            // 指向子节点,进入下一轮训练
            tempNode = subNode;
            // 设置结束标识
            if(i == keyword.length() - 1){
                tempNode.setKeywordEnd(true);
            }
        }
    }

    /**
     * 过滤敏感词
     * @param text 待过滤文本
     * @return 过滤后的文本
     */
    public String filter(String text){
        if(StringUtils.isBlank(text)){  // 文本为空
            return null;
        }
        // 指针1:
        TrieNode tempNode = rootNode;
        // 指针2:
        int begin = 0;
        // 指针3:
        int position = 0;
        // 变长字符串保存扫描结果
        StringBuilder sb = new StringBuilder();
        // 用指针2做循环
        while(begin < text.length()){
            if(position < text.length()){
                Character c = text.charAt(position);
                // 跳过符号
                if(isSymbol(c)){
                    if(tempNode == rootNode){
                        begin ++;
                        sb.append(c);
                    }
                    position++;
                    continue;
                }
                // 检查下级节点
                tempNode = tempNode.getSubNode(c);
                if(tempNode == null){ // 不是敏感词
                    sb.append(text.charAt(begin));
                    position = ++begin;
                    tempNode = rootNode;
                } else if (tempNode.isKeywordEnd() ) { // 是敏感词
                    sb.append(REPLACEMENT);
                    begin = ++position;
                } else {
                    position++;
                }
            } else { // position遍历出界
                sb.append(text.charAt(begin));
                position = ++begin;
                tempNode = rootNode;
            }
        }
        return sb.toString();
    }

    // 判断是否为符号
    private boolean isSymbol(Character c){
        // 0x2E80~0x9FF为东亚文字范围
        // CharUtils.isAsciiAlphanumeric()判断是否为普通字符
        return !CharUtils.isAsciiAlphanumeric(c)  && (c < 0x2E80 || c > 0x9FFF);
    }

    // 前缀树
    private class TrieNode{

        // 关键词结束标识
        private boolean isKeywordEnd = false;

        // 子节点(key是下级节点字符,value是下级节点)
        private Map<Character,TrieNode> subNodes = new HashMap<>();

        public boolean isKeywordEnd() {
            return isKeywordEnd;
        }

        public void setKeywordEnd(boolean keywordEnd) {
            isKeywordEnd = keywordEnd;
        }

        // 添加子节点
        public void addSubNode(Character c, TrieNode node){
            subNodes.put(c, node);
        }

        public TrieNode getSubNode(Character c){
            return subNodes.get(c);
        }

    }


}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/958374.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kvm 虚拟机添加网卡方法

找到kvm虚拟机的配置文件 虚拟机名称.xml kvm虚拟机配置文件默认路径&#xff1a;/etc/libvirt/qemu/ 先停kvm虚拟机 virsh shutdown 虚拟机名称 修改kvm虚拟机配置文件 virsh edit 虚拟机名称 在kvm虚拟机里面配置新增接口如下内容&#xff1a; <interface typebridg…

【MetaAI】2023年MetaAI发布的开源模型和工具

MetaAI开源模型和工具 MetaAILlamaSegment AnythingDINOv2ImageBindMMSLimaVoiceboxMusicGenLlama 2AudioCraftSeamlessM4T MetaAI Meta 首席执行官扎克伯格表示&#xff0c;与其他研究者分享 Meta 公司开发的模型可以帮助该公司促进创新、发现安全漏洞和降低成本。他今年 4 月…

Python中处理Excel文件的常见问题与技巧

在数据分析和办公自动化领域&#xff0c;Excel是一种广泛使用的工具。本文将介绍如何利用Python来处理Excel文件时可能遇到的常见问题&#xff0c;并分享一些实用技巧。 1. 安装必要库 - 使用pip或conda安装openpyxl、pandas等第三方库&#xff1b; – 确保所选版本兼容性以及…

基于Django 框架搭建的机器学习在线平台源代码+数据库,实现KNN、ID3、C4.5、SVM、朴素贝叶斯、BP神经网络等算法及流程管理

结果展示&#xff08;Kmeans&#xff09;&#xff1a; 完整代码下载地址&#xff1a;基于Django 框架搭建的机器学习在线平台源代码数据库 python机器学习之 K-邻近算法 简单的理解&#xff1a;[ 采用测量不同特征值之间的距离方法进行分类 ] 优点 &#xff1a;精度高、对异常…

ABAP FICO 凭证替代 凭证校验

凭证校验 1.T-CODE--->GGX2--->GBLR-->ZRGGBR000 2.将程序RGGBR000 复制为ZRGGBR000 3.GGB0--》财务会计--》凭证抬头或者行项目维护检验规则 4.OB28 维护特定的公司代码和调用点和确认&#xff0c;活动等级设置为1 5.GGB4-->激活校验 凭证替代 1.T-CODE--->GG…

解决vue项目首行报红( ESLint 配置)和新建的vue文件首行报红问题

目录 前情提要&#xff1a; 修改ESLint 配置 新建的vue文件首行还是报红 报红原因&#xff1a; 解决方法&#xff1a; 前情提要&#xff1a; 在网上查到的方法可能是在package.json文件或者.eslintrc.js文件中添加 requireConfigFile: false 如果此方法对你的错误不起作用…

Linux入门之进程信号|信号产生的方式

文章目录 一、信号入门 1.linux信号的基本概念 2.使用kill -l 命令可以查看系统定义的信号列表 3.信号处理常见方式 二、产生信号 1.通过终端按键产生信号 2.通过调用系统函数向进程发信号 3.由软条件产生信号 4.硬件异常产生信号 1. /0异常 2.模拟野指针 一、信号入门…

君子签「智能文档对比」解决合同文档内容比对问题,提高工作效率

人工校对合同&#xff0c;只能逐字逐句地查看合同条款&#xff1f;文档内容相似度过高&#xff0c;只能靠肉眼比对&#xff1f;文档细微修改难察觉&#xff0c;为后续合同履约埋下纠纷隐患&#xff1f; 「智能文档对比」是君子签基于AI人工智能技术&#xff0c;针对文档内容的…

2023年9月长沙/长春/深圳CDGA/CDGP数据治理认证考试报名

据DAMA中国官方网站消息&#xff0c;2023年度第三期DAMA中国CDGA和CDGP认证考试定于2023年9月23日举行。 报名通道现已开启&#xff0c;相关事宜通知如下&#xff1a; 考试科目: 数据治理工程师(CertifiedDataGovernanceAssociate,CDGA) 数据治理专家(CertifiedDataGovernanc…

离线环境安装jdk,使用用户环境变量配置JAVA_HOME

先说下背景&#xff0c;研发服务器&#xff0c;没有外网&#xff0c;账户权限受限&#xff0c;不能配置系统环境变量&#xff0c;只能使用用户环境变量进行配置。 具体说下步骤&#xff1a; 1、下载jdk在linux环境的安装包&#xff0c;上传到服务器&#xff0c;使用tar命令进…

Streamlit 讲解专栏(十二):数据可视化-图表绘制详解(下)

文章目录 1 前言2 使用st.vega_lite_chart绘制Vega-Lite图表2.1 示例1&#xff1a;绘制散点图2.2 示例2&#xff1a;自定义主题样式 3 使用st.plotly_chart函数创建Plotly图表3.1 st.plotly_chart函数的基本用法3.2 st.plotly_chart 函数的更多用法 4 Streamlit 与 Bokeh 结合进…

Talk | 清华大学博士生胡晨旭:ChatDB-用数据库作为符号性记忆模块来增强大语言模型

​ 本期为TechBeat人工智能社区第527期线上Talk&#xff01; 北京时间8月31日(周四)20:00&#xff0c; 清华大学博士生—胡晨旭的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “ChatDB-用数据库作为符号性记忆模块来增强大语言模型”&#xff0c;…

14家展商集中亮相!8月30-31日,智能汽车软件与座舱车联大会

过去几年&#xff0c;在特斯拉及新势力的带动下&#xff0c;车企的盈利模式正在寻求从“一次售卖”转变为“硬件预埋&#xff0b;软件付费解锁”&#xff0c;背后是驱动汽车软件架构的迭代&#xff0c;即从面向信号的软件架构&#xff0c;过渡至面向服务的SOA架构。 同时&#…

实录分享 | Alluxio在AI/ML场景下的应用

欢迎来到【微直播间】&#xff0c;2min纵览大咖观点 本次分享主要包括五个方面&#xff1a; 关于Alluxio&#xff1b;盘点企业在尝试AI时面临的挑战&#xff1b;Alluxio在技术栈中的位置&#xff1b;Alluxio在模型训练&模型上线场景的应用&#xff1b;效果对比&#xff1…

[羊城杯 2020] easyphp

打开题目&#xff0c;源代码 <?php$files scandir(./); foreach($files as $file) {if(is_file($file)){if ($file ! "index.php") {unlink($file);}}}if(!isset($_GET[content]) || !isset($_GET[filename])) {highlight_file(__FILE__);die();}$content $_GE…

Docker私有镜像仓库(Harbor)安装

Docker私有镜像仓库(Harbor)安装 1、什么是Harbor Harbor是类似与DockerHub 一样的镜像仓库。Harbor是由VMware公司开源的企业级的Docker Registry管理项目&#xff0c;它包括权限管理(RBAC)、LDAP、日志审核、管理界面、自我注册、镜像复制和中文支持等功能。Docker容器应用的…

【附安装包】Lingo 17安装教程

软件下载 软件&#xff1a;Lingo版本&#xff1a;17语言&#xff1a;英文大小&#xff1a;55.3M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a;https://pan.baidu.com/s/1-…

深入解析Kotlin类与对象:构造、伴生、单例全面剖析

前言 本篇文章将带您了解Kotlin编程中的重要概念&#xff1a;类及构造函数、访问修饰符、伴生对象和单例模式。就像搭积木一样&#xff0c;我们会逐步揭开这些概念的面纱&#xff0c;让您轻松理解它们的作用和用法。无论您是编程新手还是有经验的开发者&#xff0c;本文都将为…

Pycharm中无法使用pip安装的包问题解决方案

在终端通过pip装好包以后&#xff0c;在pycharm中导入包时&#xff0c;依然会报错。主要原因就是pip把包安装到了“解释器1”&#xff0c;但我们项目使用的是“解释器2”。具体使用的哪个解释器看项目中python解释器的配置。 解决方案一&#xff1a; Pycharm中直接安装第三方库…

pdf怎么编辑文字?了解一下这几种编辑方法

pdf怎么编辑文字&#xff1f;PDF文件的普及使得它成为了一个重要的文件格式。然而&#xff0c;由于PDF文件的特性&#xff0c;它们不可直接编辑&#xff0c;这就使得PDF文件的修改变得比较麻烦。但是&#xff0c;不用担心&#xff0c;接下来这篇文章就给大家介绍几种编辑pdf文字…