软件工程应用与实践——词云的获取

Posted 叶卡捷琳堡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了软件工程应用与实践——词云的获取相关的知识,希望对你有一定的参考价值。

2021SC@SDUSC

文章目录

一、简介

经过小组分工和讨论后,决定由我负责分析词云的获取和整理的部分。在老年健康知识图谱系统中,词云图表示了知识图谱中出现的专业名词及其出现频率。

二、word文档分词

2.1 java引入jieba分词

引入依赖

本项目使用jieba分词对word文档中的文本实现分词,jieba-analysis库用于实现在java语言中进行jieba分词

<dependency>
  <groupId>com.huaban</groupId>
  <artifactId>jieba-analysis</artifactId>
  <version>1.0.2</version>
</dependency>

在引入jieba分词后,利用hutool工具中的TokenizerEngine完成中文分词,以下是一个小例子

//分词测试
@Test
public void testJieba()
    TokenizerEngine engine = TokenizerUtil.createEngine();
    String text = "这是一句话";
    Result result = engine.parse(text);
    String resultStr = CollUtil.join((Iterator<Word>)result, " ");
    //这是 一句 话
    System.out.println(resultStr);

TokenizerEngine会根据用户引入的依赖自动判断使用哪个分词引擎,查阅hutool官网可知,目前hutool支持的分词有以下几种

2.2 读取word文档完成分词

上面的小例子是对一个简单的字符串进行中文分词,在本项目中需要对word文档进行分词,因此需要首先读取word文档,再对word文档进行分词

FileReader fileReader = new FileReader("filePath");
List<String> list = fileReader.readLines();
List<String> finalResult = new ArrayList<>();
list.forEach(l->
	TokenizerEngine engine = TokenizerUtil.createEngine();
	String text = l;
	Result result = engine.parse(text);
    String resultStr = CollUtil.join((Iterator<Word>)result, " ");
    finalResult.add(resultStr)
)

三、词云的获取

在对word文档进行分词分词之后,由于word文档中有很多与医学无关的停用词,这一部分词不能显示到首页上,需要进行筛选,删除停用词后展示到首页。在本项目中,首先从文件中获取停用词,再对获取到的词语进行筛选。

3.1 获取所有词

本项目通过dao层访问数据库,服务层调用dao层接口,controller层调用服务层。mybatis完成dao层接口与sql语句的映射

保存词云的实体类

  • 使用lombok的@Data注解,当编译时自动为实体类添加get,set,equals,hashcode,toString方法
  • 使用lombok的@AllArgsConstructor注解,为类自动添加带参的构造方法
  • 使用lombok的@NoArgsConstructor注解,为类自动添加无参的构造方法
  • 使用lombok的@Accessors注解,可以实现链式调用
package com.sdu.nurse.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class WordCloudData

    //词云名称
    private String name;
    //词云数据
    private Integer value;

延伸说明:链式调用的进一步解释

当我们平时使用实体类,为实体类赋值时,需要反复调用set方法。假设我们有一个User类,里面有name,age,id三个属性,我们需要分别调用三次set方法

User user = new User();
user.setName("name");
user.setAge(20);
user.setId("id");

由于普通set方法的返回值是void,因此无法实现链式调用。在lombok中,使用@Accessors(chain = true)注解可以使set方法返回本对象,因此使用链式调用可以简化操作,不需要重复写多个set语句,仅需在一个语句中重复调用set方法即可

User user = new User();
user.setName("name").setAge(20).setId("id");

dao层接口

dao接口中的getWordCloudData()方法完成词云图的获取

package com.sdu.nurse.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.sdu.nurse.entity.WordCloudData;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface WordCloudDataDao extends BaseMapper<WordCloudData>

    List<WordCloudData> getWordCloudData();

mysql中的正则匹配

在使用sql语句从数据库中获取词云的过程中,需要排除非中文字符,本项目中使用mysql中的

REGEXP '[\\u4e00-\\u9fa5]'

函数用于匹配中文字符

3.2 去除停用词

在本项目中,在service层去除停用词,停用词保存在一个文件中,通过hutool的FileReader类按行获取停用词(readLines方法),并保存在List中。之后再对获取的所有词进行筛选,去除停用词即可。本项目利用了list集合中的contains方法判断集合中是否已经存在字符串

service层对应的代码

public List<WordCloudData> getWordCloudData() 
    //获取停用词列表到List中
    FileReader fileReader = new FileReader("../../src/main/resources/static/info/停用词.txt");
    List<String> list = fileReader.readLines();
    //去除List集合中的无用词
    List<WordCloudData> words = wordCloudDataDao.getWordCloudData();
    List<WordCloudData> results = new ArrayList<>();
    int length = words.size();
    for(int i = 0;i < length;i++)
        if(!list.contains(words.get(i).getName()))
            results.add(words.get(i));
        
    
    return results;

关于hutool工具中封装的FileReader源码分析

hutool工具对java中一些繁琐的操作(比如日期转换,类型转换,文件读取等)进行了一些封装。由于本课程源码分析,因此我希望在阅读基本的项目代码的基础上,还能进一步了解java工具当中的部分源码。在上面的例子中,我使用了FileReader类,通过传入路径获取FileReader类对象,我们来看一下FileReader底层是怎么实现的

首先找到对应的构造方法,发现这个方法调用了另一个该类中的构造方法

public FileReader(String filePath) 
    this(filePath, DEFAULT_CHARSET);

这里的DEFAULT_CHARSET在源码中也有体现。首先FileReader继承FileWrapper,而在FileWrapper类中的static代码块中,声明了DEFAULT_CHARSET为UTF-8

static 
    DEFAULT_CHARSET = StandardCharsets.UTF_8;

发现调用该构造方法后,这个构造方法又调用了一个新的构造方法

public FileReader(String filePath, Charset charset) 
    this(FileUtil.file(filePath), charset);

下面这个构造方法被调用

public FileReader(File file, Charset charset) 
    super(file, charset);
    this.checkFile();

而FileUtil.file(filePath)方法在底层实际上调用了java中的File类,并且使用三元运算符判断用户传入的路径是否为空

public static File file(String path) 
    return null == path ? null : new File(getAbsolutePath(path));

checkFile方法用于判断文件是否存在,如果不存在则会抛出异常

private void checkFile() throws IORuntimeException 
    if (!this.file.exists()) 
        throw new IORuntimeException("File not exist: " + this.file);
     else if (!this.file.isFile()) 
        throw new IORuntimeException("Not a file:" + this.file);
    

通过以上分析,可以知道,FileReader对象实际上是一个java中File对象的增强版。

四、总结

本博客重点介绍了如何对word文档进行分词,并去除停用词的过程,顺便拓展了lombok注解和hutool文件工具类的底层源码。总的来说,通过这一部分的分析,我和队友进一步了解了项目的构建过程,为下一步的代码阅读打下了基础。

以上是关于软件工程应用与实践——词云的获取的主要内容,如果未能解决你的问题,请参考以下文章

生成中文词云图的制作:带有不同的背板

3种好用的词云工具,快来试一下吧~

R在文本挖掘与分析的妙用:分词画词云

7.19 wordcloud库的基本介绍

word2vec实战:词云应用

☞实践词云可视化——中文分词与词云制作