HanLP关键词提取。⼊门篇
前段时间,领导要求出⼀个关键字提取的微服务,要求轻量级。
对于没写过微服务的⼀个⼩⽩来讲。硬着头⽪上也不能说不会啊。
⾸先了解下公司⽬前的架构体系,发现并不是分布式开发,只能算是分模块部署。然后我需要写个Boot的服务,对外提供⼀个接⼝就⾏。
在上⽹浏览了下分词概念后,然后我选择了Gradle & HanLP & SpringBoot & JDK1.8 & tomcat8 & IDEA⼯具来实现。
然后准备就绪后,在idea⾥配置⼀下Gradle路径
HanLP分为词典 和模型,其中词典(dictionary)是词法分析必备,模型(model)是句法分析必需。解压好准备data的上级⽬录 的绝对路径  下⾯会提到⽤途。
这⾥为G:/kaipu/data-for-1.7.3
tomcat8 去官⽹⾃⾏下载,选择⾃⼰操作系统对应的。 jdk1.8 下载安装,环境变量配置不再描述。
⼀切准备就绪,开始创建项⽬
输⼊项⽬ID:keyWord,NEXT
选择本地的gradle
Next ,Finish
此刻项⽬就创建好了。
打开根⽬录下的
dependencies {
weight是什么词性compile 'org.springframework.boot:spring-boot:2.0.5.RELEASE'
compile 'org.springframework.boot:spring-boot-starter-web:2.0.5.RELEASE'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat:2.0.5.RELEASE'
testCompile group: 'junit', name: 'junit', version: '4.11'
compile 'com.hankcs:hanlp:portable-1.7.3'
}
 前三个jar 是集成springboot外部tomcat⽤的,第四个是junit单元测试依赖,第五个就是我们要⽤的hanlp依赖。
PS:这⾥我着重说下打包的事情,因为我没⽤过Gradle打包,项⽬时间紧,我就延⽤了war包格式,这⾥先记录下过程,这个项⽬后,再回头来研究Gradle打JAR包。
group 'keyword'
version '1.0-SNAPSHOT'
apply plugin: 'java'
apply plugin: 'war'
war {
archiveName 'key-word.war'
}
等待idea⾃动导包完成后,我们来加载hanlp
在resources下,出现⼀个hanlp.properties,打开编辑这个⽂件,更改root路径。这个路径就是上⾯我们提到的 data上级⽬录的绝对路径。
创建第⼀个测试类
  @Test
public void test0(){
String text = "中国是世界上的经济⼤国,社会主义强国!";
     List<Term> keyWords = HanLP.segment(text);
      System.out.String());
  }
说明词库引⼊成功。
接下来可以正常开发,按照需求,需要提取正⽂⾥的关键词,摘要。
分析如下:
关键词抽取⼯具:
思路:输⼊标题,正⽂⽂本,综合考虑词频、位置、词性、组合性短语长度等因素,计算权重得分;返回topN个关键词。在此基础上进⾏抽取式摘要,按句⼦包含的关键词数量和权重进⾏处理。
原理:分词后,将命名实体单独拿到,再合适的名词短语。依托HanLP的核⼼词典,根据TF*IDF算法计算每个命名实体和名词性短语的得分score,按score倒排返回前⾯若⼲关键词。
⾸先定义⼀个关键词类。可以是个单词,也可以是⼏个单词组成的短语。
public class Phrase implements Comparable<Phrase>{
private String word;          //候选关键词
private boolean inDictionary;  //是否在HanLP词典中
private String suffixWord;    //中⼼词。对单词,中⼼词就是word。如果是短语,则是短语中最后⼀词
private String suffixWordPos;  //中⼼词的词性
private String prefixWordPos;  //⾸词的词性
private int freqOfDict = 1;    //在词典中该词的词频
private boolean single;        //true表⽰单词,false表⽰短语
private Location location;    //该候选关键词出现的位置
private int offset;            //该候选词在正⽂中位置
private boolean isCandidate;  //是否候选关键词
*
*
*
/**
  *这会在⽐较score时⽤到
  */
@Override
public int compareTo(Phrase o) {
Word()Word());
}
}
  以下是核⼼算法的⼀部分,寻候选关键词
/**全局逻辑
先出关键词,再计算分数
⼀、
* 从分词Term中解析候选的关键词,
* 因为要计算每个句⼦的分数值需要句⼦⾥的所有词累加计算score,所以这⾥都需要打标分数。
* @param terms              分词列表
* @param title              ⽂章标题
* @param firstParagraphEnd  对于正⽂处理,表⽰正⽂第⼀段结尾位置
* @param lastParagraphBegin 对于正⽂处理,表⽰正⽂最后⼀段开始位置
*/
int index= 0;
while (index < terms.size()) {
//当前词
Term current = (index);
//⾸先判断是否是命名实体⼈名开头包含地名动名词其他专名,或者团体名开头
if (current.nature.startsWith("nr")
|| current.nature.equals(Nature.ns)
|| current.nature.)
|| current.nature.equals(Nature.vn)
|| current.nature.startsWith("nt")) {
Phrase phrase = new Phrase(current.word,
current.word,
String(),
String(),
<(current.word) == null ? 100 : (current.word).totalFrequency,
true,
phrases.add(phrase);
index++;
}
⼆、
//计算候选关键词的权重
TreeMap<Phrase, Double> scoreMap = new TreeMap<>();
  for (Phrase phrase : phrases) {
  double score = ainsKey(phrase) ? (phrase) : 0.0;
  int wordLength = Word().toString().length();
  //排除单字符的关键字
  if (score == 0.0 && wordLength != 1) {
    //weight⽅法:根据词性、词频、位置、词语长度等因素计算权重
  //这⾥依赖HanLp核⼼词典实现TF*IDF算法