Go+PHP实现敏感词检测

栏目: 服务器 · 发布时间: 6年前

内容简介:广告,敏感词检测一直以来都是让人头疼的话题,仅仅通过添加敏感词列表是解决不了问题的。今天封禁了这个词,明天又会有新的违禁词冒出来,比起愚公无穷尽的子孙更甚。敏感词匹配这种治标不治本的方法,在一定的语义下蛮有效的,但是这个场景对高并发,访问QPS高的服务来说,不是很合适。前段时间看到垃圾邮件检测用到的贝叶斯分类算法,这种“半学习”形式的方法的准确度依赖于先验概率的准确性,而公司长期以来整理到的违禁词列表就是一个很好的源,随着贝叶斯分类的数据越来越多,分类的准确性也会越来越高,后期仅仅需要对违禁词文件进行添加

概述

广告,敏感词检测一直以来都是让人头疼的话题,仅仅通过添加敏感词列表是解决不了问题的。今天封禁了这个词,明天又会有新的违禁词冒出来,比起愚公无穷尽的子孙更甚。

敏感词匹配这种治标不治本的方法,在一定的语义下蛮有效的,但是这个场景对高并发,访问QPS高的服务来说,不是很合适。前段时间看到垃圾邮件检测用到的贝叶斯分类算法,这种“半学习”形式的方法的准确度依赖于先验概率的准确性,而公司长期以来整理到的违禁词列表就是一个很好的源,随着贝叶斯分类的数据越来越多,分类的准确性也会越来越高,后期仅仅需要对违禁词文件进行添加即可,方便又准确。

PHP做贝叶斯分类不能很好的利用内存,针对每一个请求都会创建一个进程,各个请求相互独立,所以每个请求都会重新来一遍贝叶斯分类数据集构建,这效率可想而知,因此不打算用 PHP 去实现。

go语言一直以来以快著称,就用它吧。那么问题又来了,怎么让 go 作为PHP的后端实现这个检测服务呢。进程间的数据通常来讲有这么几种方式:

实现

Go+PHP实现敏感词检测

代码目录

golang 后端

package main

import (
    "src/github.com/ajph/nbclassifier-go"
    "log"
            "os"
    "bufio"
    "io"
    "net"
    "syscall"
        "fmt"
        "src/github.com/yanyiwu/gojieba"
    "strings"
)

const SPAM_CHECK_SOCKET_FILE = "/tmp/spamcheck.sock"

// 使用go 实现简单的贝叶斯分类
func getWords(filepath string)[]string {
    file, err := os.Open(filepath)
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    reader := bufio.NewReader(file)
    ret := []string{}
    for {
        line, err := reader.ReadString('\n')
        if err != nil || io.EOF == err {
            if line == "" {
                break
            }
        }
        line = strings.Trim(line, "\n")
        fmt.Println("处理单词:" + line)
        ret = append(ret, line)
    }
    return ret
}

func learn(){
    m := nbclassifier.New()

    m.NewClass("normal")
    normalwords := getWords("normalwords.txt")
    //fmt.Println(normalwords)
    m.Learn("normal", normalwords...)
    //m.Learn("normal", "a", "need")

    m.NewClass("forbidden")
    forbiddenwords := getWords("forbiddenwords.txt")
    //fmt.Println(forbiddenwords)
    m.Learn("forbidden", forbiddenwords...)
    //m.Learn("forbidden", " design ", "banner", " picture", " logo ", "clip art", " ad ", "clipart", "hairstyles", " drawing", " rendering", " diagram ", " poster", "изображение")


    m.NewClass("terror")
    terrorwords := getWords("terrorwords.txt")
    //fmt.Println(terrorwords)
    m.Learn("terror", terrorwords...)
    //m.Learn("terror", "...", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "…", "image", "pinterest", ".c", "ltd.", "vector", "quote", "video", "search", "?", "click", "psd", "ai", "print", "file", "related", "download", "submit", "view", "buy", "how", "maker", "online", " on", "by")


    m.SaveToFile("materiel.json")

}

func reloadModel() *nbclassifier.Model{
    model, _ := nbclassifier.LoadFromFile("materiel.json")
    //fmt.Println(model.Classes[0].Items[0])
    //fmt.Println(model.Classes[1])
    //fmt.Println(model.Classes[2])
    return model
}

func match(model *nbclassifier.Model, content string) string {
    // 分词
    jieba := gojieba.NewJieba()
    defer jieba.Free()
    words := jieba.Cut(content, true)
    cls, unsure,_ := model.Classify(words...)
    fmt.Println("检测到分类为:" + cls.Id)

    result := "normal"
    if unsure == false {
        result = cls.Id
        fmt.Println(cls, unsure)
    }
    return result
}

func run() {
    socket, _ := net.Listen("unix", SPAM_CHECK_SOCKET_FILE)
    defer syscall.Unlink(SPAM_CHECK_SOCKET_FILE)
    learn()
    // 训练物料
    model := reloadModel()

    for {
        client, _ := socket.Accept()

        buf := make([]byte, 1024)
        datalength, _ := client.Read(buf)
        data := buf[:datalength]
        fmt.Println("client msg:" + string(data))

        checkret := match(model, string(data))
        fmt.Println("check result: " + checkret)
        response := []byte("")
        if len(checkret) > 0 {
            response  = []byte(checkret)
        }
        _,_ = client.Write(response)
    }
}

func main() {
    // 开启sock,检测服务
    run()
    //fmt.Println(reloadModel())
}

php 前端

<?php

$msg = "你说谎, 你放屁,你这个傻子";
$SOCKET_FILE = "/tmp/spamcheck.sock";
$socket = socket_create(AF_UNIX, SOCK_STREAM, 0);
socket_connect($socket, $SOCKET_FILE);
socket_send($socket, $msg, strlen($msg), 0);
$response = socket_read($socket, 1024);
socket_close($socket);

var_dump($response);

测试

Go+PHP实现敏感词检测

开启服务

Go+PHP实现敏感词检测

确认服务已开启

Go+PHP实现敏感词检测

服务调用

总结整理

目前看起来,sock的形式还有蛮多局限性的。目前只是单机,后续可以考虑继续进行优化。先这么着吧,后面应该还要继续跟进...


以上所述就是小编给大家介绍的《Go+PHP实现敏感词检测》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Haskell函数式编程基础

Haskell函数式编程基础

Simon Thompson / 科学出版社 / 2013-7-1 / 129.00

《Haskell函数式编程基础(第3版)》是一本非常优秀的Haskell函数式程序设计的入门书,各章依次介绍函数式程序设计的基本概念、编译器和解释器、函数的各种定义方式、简单程序的构造、多态和高阶函数、诸如数组和列表的结构化数据、列表上的原始递归和推理、输入输出的控制处理、类型分类与检测方法、代数数据类型、抽象数据类型、惰性计算等内容。书中包含大量的实例和习题,注重程序测试、程序证明和问题求解,易......一起来看看 《Haskell函数式编程基础》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具