基于布隆过滤器实现敏感词识别和过滤

简介: 在当前的网络环境下,敏感词过滤已经是各大网站的“标准配置”,如果不想被大量的垃圾信息充斥,除了使用机器人识别、验证码等验证工具,还需要阻止含有敏感词内容的发布,否则可能面临关站等风险,可谓是国内互联网的红线。

在当前的网络环境下,敏感词过滤已经是各大网站的“标准配置”,如果不想被大量的垃圾信息充斥,除了使用机器人识别、验证码等验证工具,还需要阻止含有敏感词内容的发布,否则可能面临关站等风险,可谓是国内互联网的红线。

布隆过滤器

布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。

敏感词的过滤,在编程中最常见的方法是敏感词库数组遍历匹配,如果敏感词在文本中出现,则视为违规。本文将介绍基于分词技术和布隆过滤器实现的敏感词检测。相比于其它的数据结构,布隆过滤器在空间和时间方面都有巨大的优势。布隆过滤器存储空间和插入/查询时间都是常数(O(k))。另外,散列函数相互之间没有关系,方便由硬件并行实现。布隆过滤器不需要存储元素本身,在某些对保密要求非常严格的场合有优势。除了敏感词过滤,布隆过滤器还有以下应用场景:

  1. 字处理软件中,需要检查一个英语单词是否拼写正确
  2. 在 FBI,一个嫌疑人的名字是否已经在嫌疑名单上
  3. 在网络爬虫里,一个网址是否被访问过
  4. yahoo, gmail等邮箱垃圾邮件过滤功能

布隆过滤器的原理

布隆过滤器(Bloom Filter)的核心实现是一个超大的位数组和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k
20190326214904
以上图为例,具体的操作流程:假设集合里面有3个元素{x, y, z},哈希函数的个数为3。首先将位数组进行初始化,将里面每个位都设置位0。对于集合里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,这个值对应位数组上面的一个点,然后将位数组对应的位置标记为1。查询W元素是否存在集合中的时候,同样的方法将W通过哈希映射到位数组上的3个点。如果3个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。反之,如果3个点都为1,则该元素可能存在集合中。注意:此处不能判断该元素是否一定存在集合中,可能存在一定的误判率。可以从图中可以看到:假设某个元素通过映射对应下标为4,5,6这3个点。虽然这3个点都为1,但是很明显这3个点是不同元素经过哈希得到的位置,因此这种情况说明元素虽然不在集合中,也可能对应的都是1,这是误判率存在的原因。

基于Java的编程实现

Google提供的guava核心库中,提供了布隆过滤器的实现。其中的敏感词库文件,可以参考:https://github.com/tenstone/textfilter

@Service
public class BloomFilterService {

    private BloomFilter<String> configuredFilter;

    private final BloomFilter<String> filter = BloomFilter.create(new Funnel<String>() {
        private static final long serialVersionUID = 1L;
        @Override
        public void funnel(String arg0, PrimitiveSink arg1) {

            arg1.putString(arg0, Charsets.UTF_8);
        }
    }, 1024*1024*32);

    /**
     * 读取带敏感词的布隆过滤器
     *
     * @return
     * @throws IOException
     */
    public BloomFilter<String> getSensitiveWordsFilter() throws IOException {
        InputStreamReader read = null;
        BufferedReader bufferedReader = null;
        read = new InputStreamReader(this.getClass().getClassLoader().getResourceAsStream("SensitiveWords.txt"), StandardCharsets.UTF_8);
        bufferedReader = new BufferedReader(read);
        for (String txt = null; (txt = bufferedReader.readLine()) != null; ) {
            filter.put(txt);
        }
        this.configuredFilter = filter;
        return filter;
    }

    /**
     * 判断一段文字中,是否包含敏感词
     *
     * @param segments
     * @return
     */
    public Boolean segmentSensitiveFilterPassed(String[] segments) {
        if(configuredFilter == null){
            try {
                getSensitiveWordsFilter();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        Segment shortestSegment = new DijkstraSegment().enableCustomDictionary(false).enablePlaceRecognize(true).enableOrganizationRecognize(true);
        for(String segment :segments){
            List<Term> termList =  shortestSegment.seg(segment);
            for (Term term :termList){
                // 如果布隆过滤器中找到了对应的词,则认为敏感检测不通过
                if(configuredFilter.mightContain(term.word)){
                    log.info("检测到敏感词:"+term.word);
                    throw new RuntimeException("检测到敏感词");
                }
            }
        }
        return true;
    }
目录
相关文章
|
2月前
|
JavaScript 前端开发 Swift
查找和过滤4
查找和过滤4
35 2
|
5月前
|
数据采集 Web App开发 缓存
深入了解布隆过滤器:数据筛选的利器
深入了解布隆过滤器:数据筛选的利器
|
6月前
|
自然语言处理 Java
BoolQueryBuilder 如何进行模糊查询 并且模糊过滤去除name为Ab的 【4月更文挑战第2天】
如果你想使用 BoolQueryBuilder 进行模糊查询,并且要排除那些 name 字段为特定值(如 "Ab")的文档,你可以使用 must_not 子句与 FuzzyQueryBuilder 和 TermQueryBuilder 组合。以下是如何在 Elasticsearch 中实现这一需求的示例: Java代码实现 假设你想对字段 description 进行模糊查询,并确保排除 name 字段为 "Ab" 的文档: java Copy code import org.elasticsearch.index.query.BoolQueryBuilder; import org.e
929 3
|
6月前
|
缓存 索引
7.过滤查询
7.过滤查询
|
6月前
|
存储 缓存 NoSQL
🍻带你一起来理解布隆过滤器,带图分析~
🍻带你一起来理解布隆过滤器,带图分析~
110 0
|
数据采集 数据可视化 数据挖掘
如何筛选和过滤ARWU网站上的大学排名数据
ARWU网站(ShanghaiRanking's Academic Ranking of World Universities)是一个公认的全球大学排名的先驱和最值得信赖的大学排名之一。它每年发布世界前1000所研究型大学的排名,基于透明的方法论和客观的第三方数据。ARWU网站上的大学排名数据可以为高考考生、专业选择、就业指导、行业发展等提供有价值的参考信息。
如何筛选和过滤ARWU网站上的大学排名数据
|
数据挖掘
基于R筛选过滤低丰度物种的几种方式
基于R筛选过滤低丰度物种的几种方式
447 0
关于 WhereElementIsNotElementType() 过滤的理解
关于 WhereElementIsNotElementType() 过滤的理解
关于 WhereElementIsNotElementType() 过滤的理解
|
自然语言处理 搜索推荐 算法
推荐系统:基于内容的过滤
此图像包含用户喜欢的电影的描述。根据用户喜欢的电影向用户推荐电影,需要使用这些描述得到一个数学形式,即文本应该是可测量的,然后通过与其他电影进行比较来找到相似的描述。 我们有各种电影和关于这些电影的数据。为了能够比较这些电影数据,需要对数据进行矢量化。在向量化这些描述时,必须创建所有电影描述(假设 n)和所有电影(假设 m)中的唯一词矩阵。列中有所有唯一的单词,行中有所有电影,每个单词在交叉点的电影中使用了多少。这样,文本就可以被矢量化。
290 0
|
Java
FilenameFilter 实现文件过滤
实现 FilenameFilter 接口的类的实例用于过滤文件名。这些实例被用来过滤类 File 的 list 方法中的目录列表。FilenameFilter 接口很简单,只有一个 accpet 方法
113 0