创新实训(9)——博客文章的数据清洗(续)

我想让团队成员帮我抽取了几千条的博客文章数据,存在临时的数据库中,然后我尝试着进行处理。等待处理成功后在集成到正式的环境中。

博客标签的提取

提取博客的标签一直是一个很头疼的事情,因为自建博客,标签不一,有的博客有标签,有的博客没有标签,有的博客内容是统一方面的内容,但是标签却不太相同。

刚开始想的是,自己定义一套系统默认的博客标签,然后将抽取到的博客文章与标签对应,但是测试完之后发现,标签的种类是在太多了,自己想的几十个标签,根本无法涵盖庞杂的内容,有超过半数的博客都被分到未知标签的类别中。

后来经过在github的寻找,找到了一个计算机领域的词典库,发现里面包含了掘金博客平台的所有标签信息,我可以将这些标签,导入数据库,作为我们博客平台的标签信息。

计算机词典库为:https://github.com/blogstorm/cs-dict
在这里插入图片描述
在这里插入图片描述

我将这个词典的内容导入到了我的数据库中,作为博客系统定义好的标签星信息。
在这里插入图片描述
看了看词典的内容,发现有的标签可以衍生出很多的同义词,有很多词都能代表他,由于我的抽取方法是:
在这里插入图片描述
所以我随缘的在一些标签的描述中,随缘的加上了一些关键词,用“#”分割,只要句子中出现了相关的标签,或者有关标签的关键词,则就可以将这篇文章打上标签了。

  • 提取标签
/**
     * 获取博客的标签 ——有的博客本身有标签 但是需要统一成系统有的标签   有的博客没有标签,就需要构造标签
     * @param tagList   系统定义好的标签
     * @param articleBean  文章的信息
     * @return
     */
    public static List<String> getTag(List<Tag> tagList,ArticleBean articleBean)
{
    String tags = articleBean.getTags();//如果文章本身有标签 存在这里
    String clean_content = articleBean.getClean_content();//清洗后的文章内容
    String title = articleBean.getTitle();//文章的标题
    Map<String,Integer> map = new HashMap<>();
    List<String> resultTag = new ArrayList<>();//存储提取标签的结果

    if(!clean_content.equals("")) //当内容不为空时才能提取tag

    {
        //当这篇博客本身就有tag时
            if(!tags.equals(""))
            {
                String temp_tag [] = tags.split(",");
                //对比已有标签和系统定义标签的相似度标签的相似度
                /**
                 * 对比编辑距离  对比前需要将汉字全部转化为拼音 方便比对编辑距离
                 *
                 */
                for(int i = 0 ; i < temp_tag.length ; i++)
                {
                        for(Tag tag :tagList)
                        {

                                String default_tag = Word2PinYin(tag.getName());
                                String desc [] = tag.getDescription().split("#");
                                String now_tag = Word2PinYin(temp_tag[i]);

                                if(StringHasChinese(tag.getName()) || StringHasChinese(temp_tag[i]))
                                {
                                    if(editDistance(default_tag,now_tag) <3)
                                    {
                                        if(!map.containsKey(tag.getName())) map.put(tag.getName(),0);
                                        map.put(tag.getName(),map.get(tag.getName()) +1);
                                        resultTag.add(tag.getName());
                                        continue;
                                    }
                                }
                                else
                                {
                                    if(editDistance(default_tag,now_tag) ==0)
                                    {

                                        if(!map.containsKey(tag.getName())) map.put(tag.getName(),0);
                                        map.put(tag.getName(),map.get(tag.getName()) +1);
                                        resultTag.add(tag.getName());
                                        continue;
                                    }
                                }


                                for(int k = 0 ; k<desc.length ; k++)
                                {
                                    if((StringHasChinese(now_tag) || StringHasChinese(desc[k]) )&& !desc[k].equals(""))
                                    {
                                        if(editDistance(Word2PinYin(desc[k]),now_tag) <3)
                                        {
                                            if(!map.containsKey(tag.getName())) map.put(tag.getName(),0);
                                            map.put(tag.getName(),map.get(tag.getName()) +1);
                                            resultTag.add(tag.getName());
                                            continue;
                                        }
                                    }
                                    else {

                                        if(editDistance(Word2PinYin(desc[k]),now_tag) ==0)
                                        {
                                            if(!map.containsKey(tag.getName())) map.put(tag.getName(),0);
                                            map.put(tag.getName(),map.get(tag.getName()) +1);
                                            resultTag.add(tag.getName());
                                            continue;
                                        }
                                    }

                                }
               }}
            }
            /**
                 * 如果没有自带标签 或者自带标签与系统中的标签无法匹配上时,需要我们根据博客的标题和文字内容进行 字串对比 看能不能匹配到对应的标签
                 */

                for(Tag tag :tagList)
                {

                    String default_tag = Word2PinYin(tag.getName());
                    String desc [] = tag.getDescription().split("#");
                    if(clean_content.toLowerCase().contains(default_tag.toLowerCase()))
                    {
                        if(!map.containsKey(tag.getName())) map.put(tag.getName(),0);
                        map.put(tag.getName(),map.get(tag.getName()) +1);
                        resultTag.add(tag.getName());
                        continue;
                    }
                    else if(title.toLowerCase().contains(default_tag.toLowerCase()))
                    {
                        if(!map.containsKey(tag.getName())) map.put(tag.getName(),0);
                        map.put(tag.getName(),map.get(tag.getName()) +1);
                        resultTag.add(tag.getName());
                        continue;
                    }else
                    {
                        for(int k = 0 ; k<desc.length ; k++)
                        {
                            if(clean_content.toLowerCase().contains(desc[k].toLowerCase()) && !desc[k].equals(""))
                            {
                                if(!map.containsKey(tag.getName())) map.put(tag.getName(),0);
                                map.put(tag.getName(),map.get(tag.getName()) +1);
                                resultTag.add(tag.getName());
                                continue;
                            }
                        }
                    }
                }
    }
    List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
    Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {
        public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
            if(o2.getValue() > o1.getValue())
                return 1;
            else  if(o2.getValue() < o1.getValue())
                return -1;
            else return 0;
        }
    });
    int index = 0;
    List<String> result = new ArrayList<>();
    for(Map.Entry<String, Integer> t:list){
        result.add(t.getKey());
        if(++index >2) break;
    }
    return result;
}

  • 计算编辑距离
 /**
     * 利用动态规划求编辑距离
     * @param str1
     * @param str2
     * @return
     */
    public static int editDistance(String str1, String str2) {
        Preconditions.checkNotNull(str1);
        Preconditions.checkNotNull(str2);

        int len1 = str1.length();
        int len2 = str2.length();
        int[][] dp = new int[len1 + 1][len2 + 1];

        for (int i = 0; i <= len1; i++) {
            dp[i][0] = i;
        }

        for (int j = 0; j <= len2; j++) {
            dp[0][j] = j;
        }

        for (int i = 0; i < len1; i++) {
            char c1 = str1.charAt(i);
            for (int j = 0; j < len2; j++) {
                char c2 = str2.charAt(j);
                //if last two chars equal
                if (c1 == c2) {
                    //update dp value for +1 length
                    dp[i + 1][j + 1] = dp[i][j];
                } else {
                    dp[i + 1][j + 1] = 1 + min(dp[i+1][j], min(dp[i][j+1], dp[i][j]));
                }
            }
        }

        return  dp[len1][len2];
    }
  • 判断字符串时候含有中文,以及将中文转换成拼音
/**
     * 将有中文的字符串转成拼音
     * @param str
     * @return
     */
    public static String Word2PinYin(String str)
    {
        StringBuffer sb = new StringBuffer();
        for(int i = 0 ; i<str.length() ; i++)
        {
            char temp = str.charAt(i);
            //如果是小写字母
            if(temp >=97 && temp <= 122)
            {
                sb.append(temp);
            }
            else if(temp >=65 && temp<=90)  //如果是大写字母  转化成小写字母
            {
                sb.append(Character.toLowerCase(temp));
            }
            else if(isChinese(temp))  //如果是中文
            {
                sb.append(PinYinUtil.getStringPinYin(String.valueOf(temp)));
            }
            else //
            {
                sb.append(temp);
            }

        }
        return sb.toString();
    }

    /**
     * 判断一个字符串中是否含有中文
     * @param str
     * @return
     */
    public static boolean StringHasChinese(String str)
    {
        for(int i = 0 ; i< str.length() ; i++)
        {
            if(isChinese(str.charAt(i)))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断一个字符是否是中文
     * @param c
     * @return
     */
    public static boolean isChinese(char c) {
        Character.UnicodeScript sc = Character.UnicodeScript.of(c);
        if (sc == Character.UnicodeScript.HAN) {
            return true;
        }

        return false;
    }
 // 转换一个字符串
    public static String getStringPinYin(String str) {
        StringBuilder sb = new StringBuilder();
        String tempPinyin = null;
        for (int i = 0; i < str.length(); ++i) {
            tempPinyin = getCharacterPinYin(str.charAt(i));
            if (tempPinyin == null) {
                // 如果str.charAt(i)非汉字,则保持原样
                sb.append(str.charAt(i));
            } else {
                sb.append(tempPinyin);
            }
        }
        return sb.toString();
    }

思路:
(1)如果这篇文章本身就有标签,则将中文标签转化为拼音,与系统自定义的标签与有关标签的关键词(也转化为拼音)依次比较编辑距离,如果相等,则说明是同一个标签,则用系统定义的标签标记它。
(2)如果这篇文章没有标签,或者自带标签与系统中的标签无法匹配上时,需要我们根据博客的标题和文字内容进行 字串对比 看能不能匹配到对应的标签。
(3)最终输出出现次数最多的三个标签(我们用hashmap来统计每个标签的出现次数)

最终将文章打上了标签,但是还有不到百分之二十的博客,可能内容比较偏,还是被标记为未分类,只能之后在进行处理了

对标签进行分类

系统定义了五百多个标签,我们想要更好的展示到前端界面上,则需要对这些标签进行分类,才可以做到界面上进行分类展示。

= =在这里没有想到什么好办法,我人工定义了二十五个分类,然后用了几个小时,人工将这些标签进行了分类,
真——人工智能
在这里插入图片描述
将标签写入分类的描述中,用“#”分割
然后通过给文章打的标签,进行文章的分类就好了

    /**
     * 有了标签之后 根据博客的标签 匹配对应的博客分类
     * @param classify_list
     * @param tag_list
     * @return
     */
    public static List<String> getClassify(List<Classify> classify_list ,List<String> tag_list)
{
    List<String> classify_result = new ArrayList<>();
    for(String tag :tag_list)
    {
        String deal_tag = Word2PinYin(filtration(tag));
        for(Classify classify :classify_list)
        {
            String classify_desc [] = classify.getDescription().split("#");
            for(int i = 0 ; i< classify_desc.length ; i++)
            {
                    String deal_decs = Word2PinYin(filtration(classify_desc[i]));
                    if(editDistance(deal_decs,deal_tag) == 0)
                    {
                        classify_result.add(classify.getName());
                    }
            }
        }
    }
   return new ArrayList<String>(new HashSet<String>(classify_result));
}

至此,除了博客的摘要没有更好的替代方法,其他所有的数据都清洗完成了,可以进行下一步的工作了。

猜你喜欢

转载自blog.csdn.net/baidu_41871794/article/details/106690225