makedown过滤标签解决黑产内容通过<>规避词库检测的问题

makedown过滤标签解决黑产内容通过<>规避词库检测的问题

【需求背景】

用户发布的内容中包含富文本内容,包括a标签,img标签等,为了提升词库检测的准确性,目前在做词库检测之前,通过hutool的HtmlUtil.cleanHtmlTag将待检测文本进行过滤。

但cleanHtmlTag未校验标签的合法性,会存在误操作,比如:会将所有"<“和”>"包裹的内容全部过滤,导致被黑产利用发布违规内容。

例如:<英超比赛在哪押注{C><网-Ag886.cn-网>#<英超比赛在哪押注{d英超比赛在哪押注><英超比赛在哪押注{H英超比赛在哪押注>

【需求详情】

在做词库检测之前,仅过滤合法的html标签,规避被黑产利用的问题

【实现方式】

通过调研发现有多款库可以实现html过滤。比如java清理html以封装好的库有三种分别是HtmlUtil.cleanHtmlTag (hutool),HtmlUtils.htmlEscape (spring),Jsoup.parse("").text() (jsoup)
前两都是对尖括号来进行清理html标签的,而jsoup可以更加html标签来清理html标签,但是也会有误杀比如<123><123>就可以但是<中文><中文>就不行!

所以并不满足当前开发的需求,所以我就自己实现了一个满足需求的html清理库,主要思路是先过滤无法用正则表达式清除的HTML标签,

第一步替换掉html标签里面的像Style,class,src.href等等这样的内容

makedown过滤标签解决黑产内容通过<>规避词库检测的问题

第二步去除空格

makedown过滤标签解决黑产内容通过<>规避词库检测的问题

第三步移除掉向,

,标签

makedown过滤标签解决黑产内容通过<>规避词库检测的问题

第四步 匹配html标签,例如"xxx

"这种格式

makedown过滤标签解决黑产内容通过<>规避词库检测的问题

第五步 针对多个标签嵌套的情况进行处理

* 比如 <p><a href='https://itunes.apple.com/'>违规内容</a></p>
* 预处理并且正则匹配完之后结果是 <a>违规内容
* 需要手工移除掉前面的起始标签

makedown过滤标签解决黑产内容通过<>规避词库检测的问题

最后只需要调用getResultsFromHtml就可以清理掉了

makedown过滤标签解决黑产内容通过<>规避词库检测的问题

makedown过滤标签解决黑产内容通过<>规避词库检测的问题

过滤代码

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HtmlFilterUtil {
    /**
     * 替换掉html标签里面的像Style,class,src.href等等这样的内容
     *
     * @param content
     * @return
     */
    public static String replaceTagContent(String content) {
        List<String> regExArray = new ArrayList<>();
        String[] regExTextArray ={"style","src","href","class","data-origin","data-type"};
        for(String regExText:regExTextArray){
            regExArray.add(regExText+"=\'(.*?)\'");
            regExArray.add(regExText+"=\"(.*?)\"");
        }

        if (content == null || content.length() == 0) {
            return content;
        }
        for(String regEx : regExArray){
            Pattern p = Pattern.compile(regEx);
            Matcher m = p.matcher(content);
            if (m.find()) {
                content = m.replaceAll("");
            }
        }
        return content;
    }
    /**
     * 移除掉向<img/>,<h1>,<h2>,<h3>,标签
     *
     * @param src
     * @return
     */
    public static String removeAllTagList(String src) {
        List<String> regExArray = new ArrayList<>();
        String[] regExHtextArray ={"h1","h2","h3","h4","h5"};
        for(String regExHtext:regExHtextArray){
            regExArray.add("<"+regExHtext+">");
            regExArray.add("</"+regExHtext+">");
        }
        String[] regExTextArray ={"img","a","div","span"};
        for(String regExText:regExTextArray){
            regExArray.add("<"+regExText+"/>");

        }
        for(String regEx:regExArray){
            if (src != null && !src.isEmpty()) {
                src = src.replaceAll(regEx, "");
            }
        }
        return src;
    }
    /**
     * 针对多个标签嵌套的情况进行处理
     * 比如 <p><a href='https://itunes.apple.com/'>违规内容</a></p>
     * 预处理并且正则匹配完之后结果是 <a>违规内容
     * 需要手工移除掉前面的起始标签
     * @param content
     * @return
     */
    public static String replaceStartTag(String content) {
        if (content == null || content.length() == 0) {
            return content;
        }
        String regEx = "<[a-zA-Z]*?>([\\s\\S]*?)";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(content);
        if (m.find()) {
            content = m.replaceAll("");
        }
        return content;
    }
    /**
     * 匹配html标签,例如"xxx</p>"这种格式
     */
    private static Pattern HTML_TAG_PATTERN_rigth = Pattern.compile("([\\s\\S]*?)</[a-zA-Z]*?>");

    /**
     * 获取html中的数据
     * @param htmlString
     * @return
     */
    public static String getResultsFromHtml(String htmlString) {
        htmlString = "<p>"+htmlString+"</p>";
        String results = "";
        // 数据预处理
        htmlString = replaceTagContent(htmlString).replace(" ", "");//同时去除空格
        htmlString = removeAllTagList(htmlString);
        if (htmlString != null && htmlString.length() > 0) {
            Matcher imageTagMatcher = HTML_TAG_PATTERN_rigth.matcher(htmlString);
            // 针对多个并列的标签的情况
            while (imageTagMatcher.find()) {
                String result = "";
                // group(1)对应正则表达式中的圆括号括起来的数据
                result = imageTagMatcher.group(1).trim();
                // 针对多个标签嵌套的情况进行处理
                if (result != null && result.length() > 0) {
                    result = replaceStartTag(result);
                }

                results+=result;
            }
        }
        return results;
    }
}

上一篇:go的形参


下一篇:3.服务器负载均衡的实现