字符串分词,字符串词语切割

 

基本分词-BaseAnalysis

基本分词是什么

  • 基本就是保证了最基本的分词.词语颗粒度最非常小的..所涉及到的词大约是10万左右.
  • 基本分词速度非常快.在macAir上.能到每秒300w字每秒.同时准确率也很高.但是对于新词他的功能十分有限

基本分词具有什么功能

 

一个简单的使用方式

package demo;

import java.util.List;

import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.BaseAnalysis;
 
/**
 * @author liuchaojun
 * @date 2018-8-27 下午05:18:50
 */
public class Test {
	public static void main(String[] args) {
			List<Term> parse = BaseAnalysis.parse("大家新年好!");
			System.out.println(parse);
	}
}
 

运行结果

 

精准分词-ToAnalysis

精准分词具有什么功能

  1. 用户自定义词典
  2. 数字识别
  3. 人名识别

一个简单的使用方式

/**
 * 
 */
package demo;

import java.util.List;

import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.ToAnalysis;

/**
 * @author liuchaojun
 * @date 2018-9-26 下午01:47:23
 */
public class Test1 {
	public static void main(String[] args) {
		  List<Term> parse = ToAnalysis.parse("让战士们过一个欢乐祥和的新春佳节。");
		    System.out.println(parse);

	}
}

运行结果:

 

nlp分词-NlpAnalysis

nlp分词是什么

  1. nlp分词是总能给你惊喜的一种分词方式.
  2. 它可以识别出未登录词.但是它也有它的缺点.速度比较慢.稳定性差.ps:我这里说的慢仅仅是和自己的其他方式比较.应该是40w字每秒的速度吧.
  3. 个人觉得nlp的适用方式.1.语法实体名抽取.未登录词整理.只要是对文本进行发现分析等工作

精准分词具有什么功能

  1. 用户自定义词典
  2. 数字识别
  3. 人名识别
  4. 机构名识别
  5. 新词发现

一个简单的使用方式

package demo;

import java.util.List;

import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.NlpAnalysis;

/**
 * @author liuchaojun
 * @date 2018-9-26 下午02:12:19
 */
public class Test3 {
	public static void main(String[] args) {
		   List<Term> parse = NlpAnalysis.parse("洁面仪配合洁面深层清洁毛孔 清洁鼻孔面膜碎觉使劲挤才能出一点点皱纹 脸颊毛孔修复的看不见啦 草莓鼻历史遗留问题没辙 脸和脖子差不多颜色的皮肤才是健康的 长期使用安全健康的比同龄人显小五到十岁 28岁的妹子看看你们的鱼尾纹");
		   System.out.println(parse);
	}
}

运行结果:

面向索引的分词-IndexAnalysis

面向索引的分词是什么

面向索引的分词。故名思议就是适合在lucene等文本检索中用到的分词。 主要考虑以下两点

  • 召回率
    • 召回率是对分词结果尽可能的涵盖。比如对“上海虹桥机场南路” 召回结果是[上海/ns, 上海虹桥机场/nt, 虹桥/ns, 虹桥机场/nz, 机场/n, 南路/nr]
  • 准确率
    • 其实这和召回本身是具有一定矛盾性的Ansj的强大之处是很巧妙的避开了这两个的冲突 。比如我们常见的歧义句“旅游和服务”->对于一般保证召回 。大家会给出的结果是“旅游 和服 服务” 对于ansj不存在跨term的分词。意思就是。召回的词只是针对精准分词之后的结果的一个细分。比较好的解决了这个问题

基本分词具有什么功能

  1. 用户自定义词典
  2. 数字识别
  3. 人名识别

一个简单的使用方式

package demo;

import java.util.List;

import org.ansj.domain.Term;
import org.ansj.splitWord.analysis.IndexAnalysis;

/**
 * @author liuchaojun
 * @date 2018-9-26 下午02:15:57
 */
public class Test4 {
	public static void main(String[] args) {
		List<Term> parse = IndexAnalysis.parse("上海虹桥机场");
		System.out.println(parse);
	}
}

运行结果:

用户自定义词典

Ansj目前支持以下的公户自定义词典的操作方式.

  • 从文件中加载词典
    • 配置文件
    • 编码路径
  • 从内存操作词典
    • 增加
    • 删除
    • 修改

同时Ansj的用户自定义词典.支持多词典.多层次的分词.对于特定领域的分词.就是一神器.O(∩_∩)O~

 

动态添加

直接看例子.这个功能其实在tree-split中就已经存在的.

说明:

1..删除只能删除用户自定义词典的词.

2.对了分词默认把大写都转换为小写了.所以添加新词的时候要求必须是小写.

package demo;
import java.util.List;
import org.ansj.domain.Term;
import org.ansj.library.UserDefineLibrary;
import org.ansj.splitWord.analysis.ToAnalysis;
/**
 * @author liuchaojun
 * @date 2018-9-26 下午02:22:58 
 */
public class DynamicWordDemo {
	 public static void main(String[] args) {
	        // 增加新词,中间按照'\t'隔开
	        UserDefineLibrary.insertWord("ansj中文分词", "userDefine", 1000);
	        List<Term> terms = ToAnalysis.parse("我觉得Ansj中文分词是一个不错的系统!我是王婆!");
	        System.out.println("增加新词例子:" + terms);
	        // 删除词语,只能删除.用户自定义的词典.
	        UserDefineLibrary.removeWord("ansj中文分词");
	        terms = ToAnalysis.parse("我觉得ansj中文分词是一个不错的系统!我是王婆!");
	        System.out.println("删除用户自定义词典例子:" + terms);
	}
}

运行结果:

0

 

设置辞典路径

关于ansj分词用户自定义词典的路径设置

第一种.正规方式

创建library.properties 中增加

#path of userLibrary
userLibrary=library/userLibrary/userLibrary.dic
ambiguityLibrary=/library/ambiguity.dic

第二种 在用词典未加载前可以通过,代码方式方式来加载

MyStaticValue.userLibrary=[你的路径]

第三种,调用api加载.在程序运行的任何时间都可以.动态价值

loadLibrary.loadLibrary(String path)方式加载

路径可以是具体文件也可以是一个目录 如果是一个目录.那么会扫描目录下的dic文件自动加入词典

 

歧义纠正辞典

很多时候.分词发生歧异不是很好调整.用户需要更强的规则来约束所以.ansj中增加了歧异消除的一个强规则方式

在library/ambiguity.dic

中你会看到如下内容

三个和尚    三个    m    和尚    n
的确定不    的确    d    定    v    不    v
大和尚    大    a    和尚    n
张三和    张三    nr    和    c

这里例子告诉计算机

第一列是识别串.第二列是分词结果.奇数行是词.偶数行是词性.

ps:这个是优先分词运行的.所以添加时候要谨慎...

当然 ambiguity.dic 的路径你可以在分词调用前..

用 MyStaticValue.ambiguityLibrary = "歧异词典的路径" 来设定

歧义纠正是Ansj分词的最后最后的大招了。杀伤力巨大。谨慎使用。极可能造成其他的错误。

 

下面给一个例子。是动态添加的。

            //歧义纠正
            Value value = new Value("川府办", "川府办", "n");
            Library.insertWord(UserDefineLibrary.ambiguityForest, value);

            value = new Value("京财企业务", "京财企", "nt", "业务", "j");
            Library.insertWord(UserDefineLibrary.ambiguityForest, value);

            System.out.println(NlpAnalysis.parse("据说川府办发的发文很厉害"));;
            System.out.println(NlpAnalysis.parse("京财企业务繁忙"));;

 

自定义词性和停用词

很多时候.系统的内置词性无法满足您的需求.

你需要根据自己的规则对词语进行词性标注.

最简单的就是用户自定义词典中的词性在分词结果中,并不是优先出现的.

所以我们通过 FilterModifWord 来对分次结果进一步处理

1.增加停用词的例子

//增加两个停用词
FilterModifWord.insertStopWord("并且") ;
FilterModifWord.insertStopWord("但是") ;

2.增加停用词性的例子

//加入过滤词性词性
FilterModifWord.insertStopNatures("v") ;

3.以用户自定义的词性优先

/*
 * 停用词过滤并且修正词性
 */
List<Term> parse = ToAnalysis.parse(string) ;
new NatureRecognition(parse).recognition() ;
FilterModifWord.modifResult(parse) ;

4.使用自定义的词典树

/*
 * 停用词过滤并且修正词性,
 */
public static List<Term> modifResult(List<Term> all, Forest... forests) 

 

分词http服务

摘要

  • ansj_seg 内置了一个用来提供分词 API 的 HttpServer,类名为 org.ansj.web.AnsjServer。
  • 启动服务

在开发环境中,可以通过 mvn 运行分词服务:>

mvn exec:java -Dexec.mainClass="org.ansj.web.AnsjServer" -Dexec.args="<端口号>"

在 staging 或生产环境中,运行 org.ansj.webAnsjServer 类即可,如:

java -classpath [jar包位置] org.ansj.app.web.AnsjServer <端口号>


 

API 调用

假设端口号为 8888。

一个调用例子为:http://127.0.0.1:8888/segment?input=自然语言处理&method=to&nature=true

input

待分词的文本。

method

使用的分词方法,可以为 to, nlp 或 base。对应 ansj_seg 的 analysis 中的三种分词方法。

默认为 to。

nature

是否启用词性标注,true 代表启用,false 代表禁用。

默认为 true。


 

如果需要一个演示界面可以直接访问

http://127.0.0.1:[]port]/page/index.html

就可以进行可视化操作了


 

为了方便调用。为了不总解释我搭配好了一套系统大家可以从这里下载。

http://yun.baidu.com/s/1dDBrec5#dir/path=%2Fansj%E5%88%86%E8%AF%8D 下载ansj_web.jar

解压缩运行run.sh 然后访问

展示界面:http://127.0.0.1:8888/page/index.html

API:http://127.0.0.1:8888

 

新词发现小工具

  1. 其实本身是一个tire树。因为分词中集成了大量的。新词识别。 比如 人名识别,机构名识别,新词发现等,这些新词的出现对分词结果起着重要的影响,如何能将这些结果整合起来。 可以想到的有两种方式,
  2. 线性链模式:以新词发现的准确率为基准,进行一步一步的合并。 比如。现识别人名,(因为人名识别的准确率相对较高)再识别机构名,然后是地名等 这个方式的优点是速度快。程序逻辑清晰。在不同识别方式上不必要担心,词语权重不一致。 但是缺点也很明显,人名识别发生错误。造成后面的识别一错再错,比如“非洲八冠王曾夺世界季军”,如果现经历人名识别。会出现“王曾夺”错误的划分为人名。
  3. 集合模式:这个方式就是利用了learntool的特性。它将所有识别出来的认为是新词的词语。都完整的加入learntool中。之后再以新词为辞典。构建最优路径。


  package org.ansj.demo;

  import org.ansj.dic.LearnTool;
  import org.ansj.domain.Nature;
  import org.ansj.splitWord.analysis.NlpAnalysis;

  /**
   * 新词发现工具
   * @author ansj
   *
   */
  public class LearnToolDemo {
      public static void main(String[] args) {

          //构建一个新词学习的工具类。这个对象。保存了所有分词中出现的新词。出现次数越多。相对权重越大。
          LearnTool learnTool = new LearnTool() ;

          //进行词语分词。也就是nlp方式分词,这里可以分多篇文章
          NlpAnalysis.parse("说过,社交软件也是打着沟通的平台,让无数寂寞男女有了肉体与精神的寄托。", learnTool) ;
          NlpAnalysis.parse("其实可以打着这个需求点去运作的互联网公司不应只是社交类软件与可穿戴设备,还有携程网,去哪儿网等等,订房订酒店多好的寓意", learnTool) ;
          NlpAnalysis.parse("张艺谋的卡宴,马明哲的戏",learnTool) ;

          //取得学习到的topn新词,返回前10个。这里如果设置为0则返回全部
          System.out.println(learnTool.getTopTree(10));

          //只取得词性为Nature.NR的新词
          System.out.println(learnTool.getTopTree(10,Nature.NR));

      }
  }

关于learntool的结果保存。及重新训练

  • 有好几个朋友提出过这个问题.的确当初做这个的时候没有完整的考虑。那么让我们看看他是怎么可以迭代训练吧。我直接上代码了,因为其内部newWord结构比较复杂。所以在write的时候。我放弃了没有激活的词,很可能这些词。会在以后激活,而且放弃了这些词的词性。全部为nw,但是这个词性也可能在以后的训练中纠正。目前我觉得最简单的保存方式只有如此。完整无损保存这个功能,可能会在以后的版本实现,我最终的意思是。现这么凑合用吧。也还行问题不大 !^_^
  /**
   * 将训练结果序列写入到硬盘中
   */
  List<Entry<String, Double>> topTree = learnTool.getTopTree(0);
  StringBuilder sb = new StringBuilder();
  for (Entry<String, Double> entry : topTree) {
      sb.append(entry.getKey() + "\t" + entry.getValue()+"\n");
  }
  IOUtil.Writer("/home/ansj/temp/learnTool.snap", IOUtil.UTF8, sb.toString());
  sb = null;

  /**
   * reload训练结果
   */
  learnTool = new LearnTool() ;
  HashMap<String, Double> loadMap = IOUtil.loadMap("/home/ansj/temp/learnTool.snap", IOUtil.UTF8, String.class, Double.class);
  for (Entry<String, Double> entry : loadMap.entrySet()) {
      learnTool.addTerm(new NewWord(entry.getKey(), Nature.NW, entry.getValue())) ;
      learnTool.active(entry.getKey()) ;
  }
  System.out.println(learnTool.getTopTree(10));

 

关键词抽取

/**
 * 关键词提取的例子
 * @author ansj
 *
 */
public class KeyWordCompuerDemo {
public static void main(String[] args) {
    KeyWordComputer kwc = new KeyWordComputer(5);
    String title = "维基解密否认斯诺登接受委内瑞拉庇护";
    String content = "有俄罗斯国会议员,9号在社交网站推特表示,美国中情局前雇员斯诺登,已经接受委内瑞拉的庇护,不过推文在发布几分钟后随即删除。俄罗斯当局拒绝发表评论,而一直协助斯诺登的维基解密否认他将投靠委内瑞拉。  俄罗斯国会国际事务委员会主席普什科夫,在个人推特率先披露斯诺登已接受委内瑞拉的庇护建议,令外界以为斯诺登的动向终于有新进展。  不过推文在几分钟内旋即被删除,普什科夫澄清他是看到俄罗斯国营电视台的新闻才这样说,而电视台已经作出否认,称普什科夫是误解了新闻内容。  委内瑞拉驻莫斯科大使馆、俄罗斯总统府发言人、以及外交部都拒绝发表评论。而维基解密就否认斯诺登已正式接受委内瑞拉的庇护,说会在适当时间公布有关决定。  斯诺登相信目前还在莫斯科谢列梅捷沃机场,已滞留两个多星期。他早前向约20个国家提交庇护申请,委内瑞拉、尼加拉瓜和玻利维亚,先后表示答应,不过斯诺登还没作出决定。  而另一场外交风波,玻利维亚总统莫拉莱斯的专机上星期被欧洲多国以怀疑斯诺登在机上为由拒绝过境事件,涉事国家之一的西班牙突然转口风,外长马加略]号表示愿意就任何误解致歉,但强调当时当局没有关闭领空或不许专机降落。";
        Collection<Keyword> result = kwc.computeArticleTfidf(title, content);
            System.out.println(result);
    }
}

 

词性标注

  • Ansj词性标注是基于HMM的。

主要利用了ngram的方式,相对而言作的还是比较粗糙

  • 词性标注的规范

说句实话,这个自由度一直很高,因为既要支持用户自定义辞典。而用户的词性关我屁事。所以没有一个完整的统一。但是在实际使用中我们还是尽量以北大标注为准,在另一个文档中,有一份词性说明。我自己增加了nw词性,这个词性意思是是一个新词,但是具体是什么。我不知道。

  • 什么地方需要词性标注

除了nlpanalysis 自带词性标注。其他的方式都是需要词性标注的。词性标注的方式是以工具类的形式调用。下面是调用代码,可以看到我们是利用new NatureRecognition(terms).recognition();对分词结果进行的标注。

    package org.ansj.demo;

    import java.io.IOException;
    import java.util.List;

    import org.ansj.domain.Term;
    import org.ansj.recognition.NatureRecognition;
    import org.ansj.splitWord.analysis.ToAnalysis;

    /**
     * 词性标注
     * 
     * @author ansj
     * 
     */
    public class NatureDemo {
        public static void main(String[] args) throws IOException {
            List<Term> terms = ToAnalysis.parse("Ansj中文分词是一个真正的ict的实现.并且加入了自己的一些数据结构和算法的分词.实现了高效率和高准确率的完美结合!");
            new NatureRecognition(terms).recognition(); //词性标注
            System.out.println(terms);
        }
    }
  • 我只想用ansj的词性标注。我没有分词结果

    package org.ansj.demo;    
    import java.util.Arrays;
    import java.util.List;
    import org.ansj.domain.Term;
    import org.ansj.recognition.NatureRecognition;

    /**
     * 对非ansj的分词结果进行词性标注
     * @author ansj
     *
     */
    public class NatureTagDemo {
        public static void main(String[] args) {
            String[] strs = {"对", "非", "ansj", "的", "分词", "结果", "进行", "词性", "标注"} ;
            List<String> lists = Arrays.asList(strs) ;
            List<Term> recognition = NatureRecognition.recognition(lists, 0) ;
            System.out.println(recognition);
        }
    }

 

tree-split

  • tree-split是一个小巧好用的。tire树数据库。
  • 里面封装了我一些常用的工具类。比如IOUtil 。 StringUtil。
  • tire树就不解释了。也就是词典树,个人认为是最好的分词数据结构。没有之一。
  • tree-split 中的tire采用首字hash 。次字二分查找的方式。同时也支持参数可配置的形式。

下面是tree-split的一个使用说明


        /**
         * 词典的构造.一行一个词后面是参数.可以从文件读取.可以是read流.
         */
        String dic = "中国\t1\tzg\n人名\t2\n中国人民\t4\n人民\t3\n孙健\t5\nCSDN\t6\njava\t7\njava学习\t10\n";
        Forest forest = Library.makeForest(new BufferedReader(new StringReader(dic)));

        /**
         * 删除一个单词
         */
        Library.removeWord(forest, "中国");
        /**
         * 增加一个新词
         */
        Library.insertWord(forest, "中国人");
        String content = "中国人名识别是中国人民的一个骄傲.孙健人民在CSDN中学到了很多最早iteye是java学习笔记叫javaeye但是java123只是一部分";
        GetWord udg = forest.getWord(content);

        String temp = null;
        while ((temp = udg.getFrontWords()) != null)
            System.out.println(temp + "\t\t" + udg.getParam(1) + "\t\t" + udg.getParam(2));

jar包下载地址:

http://maven.ansj.org/org/ansj/tree_split/

maven

  • 第一步在你的pom.xml中加入.
<project>
    <repositories>
        <repository>
            <id>mvn-repo</id>
            <url>http://maven.ansj.org/</url>
        </repository>
    </repositories>
</project>
  1. 在dependencies标签中粘贴如下:(其实version 以最新的为标准.)
    <dependencies>
        <dependency>
            <groupId>org.ansj</groupId>
            <artifactId>tree_split</artifactId>
            <version>1.2</version>
        </dependency>
    </dependencies>

获得源码

https://github.com/ansjsun/tree_split

 

Ansj In Lucene

  • Ansj目前有了lucene 什么版本的插件:
    • lucene3.x
    • lucene4.x

对于3.x之前的版本,我表示不会写相关的jar了,lucene的分词插件不是很难写,如果非要说难写就是因为他没有一个很好的文档和说明,里面暗坑比较多。

  • 如何获得lucene插件的jar包:

  • 你可以从我的maven仓库中下载http://maven.ansj.org/org/ansj/ 打开这个

    找到 ansj_lucene3_plug/ , ansj_lucene4_plug/ 从里面下载jar包把。maven的话同理。不多阐述

          //实际使用中jar最好是最新版本的,需要这三个jar。。。
          http://maven.ansj.org/org/ansj/ansj_lucene4_plug/1.3/ansj_lucene4_plug-1.3.jar
    
          http://maven.ansj.org/org/ansj/ansj_seg/1.x/ansj_seg-1.3-min.jar
    
          http://maven.ansj.org/org/ansj/tree_split/1.x/tree_split-1.2.jar
    
  • 如何用maven集成

     <dependency>
              <groupId>org.ansj</groupId>
              <artifactId>ansj_seg</artifactId>
              <version>1.3</version>
           <classifier>min</classifier>
          </dependency>
          <dependency>
              <groupId>org.ansj</groupId>
              <artifactId>ansj_lucene4_plug</artifactId>
              <version>1.3</version>
          </dependency>
    
  • 如何获得Ansj lucene插件的源码:

        插件源码我已经集合到ansj_seg的项目中了。在plug目录下有这两个项目的源码。并且也是maven项目。你可以直接作为maven导入。

  • 使用例子:

 


import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Date;
import java.util.HashSet;
import java.util.ResourceBundle;
import love.cq.util.IOUtil;
import org.ansj.lucene.util.PorterStemmer;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Token;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;
public class AnsjAnalysisTest {
    @Test
    public void test() throws IOException {
        Token nt = new Token();
        Analyzer ca = new AnsjAnalysis();
        Reader sentence = new StringReader(
                "\n\n\n\n\n\n\n我从小就不由自主地认为自己长大以后一定得成为一个象我父亲一样的画家, 可能是父母潜移默化的影响。其实我根本不知道作为画家意味着什么,我是否喜欢,最重要的是否适合我,我是否有这个才华。其实人到中年的我还是不确定我最喜欢什么,最想做的是什么?我相信很多人和我一样有同样的烦恼。毕竟不是每个人都能成为作文里的宇航员,科学家和大教授。知道自己适合做什么,喜欢做什么,能做好什么其实是个非常困难的问题。"

 

                    + "幸运的是,我想我的孩子不会为这个太过烦恼。通过老大,我慢慢发现美国高中的一个重要功能就是帮助学生分析他们的专长和兴趣,从而帮助他们选择大学的专业和未来的职业。我觉得帮助一个未成形的孩子找到她未来成长的方向是个非常重要的过程。"
                    + "美国高中都有专门的职业顾问,通过接触不同的课程,和各种心理,个性,兴趣很多方面的问答来帮助每个学生找到最感兴趣的专业。这样的教育一般是要到高年级才开始, 可老大因为今年上计算机的课程就是研究一个职业走向的软件项目,所以她提前做了这些考试和面试。看来以后这样的教育会慢慢由电脑来测试了。老大带回家了一些试卷,我挑出一些给大家看看。这门课她花了2个多月才做完,这里只是很小的一部分。"
                    + "在测试里有这样的一些问题:"
                    + "你是个喜欢动手的人吗? 你喜欢修东西吗?你喜欢体育运动吗?你喜欢在室外工作吗?你是个喜欢思考的人吗?你喜欢数学和科学课吗?你喜欢一个人工作吗?你对自己的智力自信吗?你的创造能力很强吗?你喜欢艺术,音乐和戏剧吗?  你喜欢自由自在的工作环境吗?你喜欢尝试新的东西吗? 你喜欢帮助别人吗?你喜欢教别人吗?你喜欢和机器和工具打交道吗?你喜欢当领导吗?你喜欢组织活动吗?你什么和数字打交道吗?");
    TokenStream ts = ca.tokenStream("sentence", sentence);

    System.out.println("start: " + (new Date()));
    long before = System.currentTimeMillis();
    while (ts.incrementToken()) {
        System.out.println(ts.getAttribute(CharTermAttribute.class));
    }
    ts.close();
    long now = System.currentTimeMillis();
    System.out.println("time: " + (now - before) / 1000.0 + " s");
}

@Test
public void indexTest() throws CorruptIndexException, LockObtainFailedException, IOException, ParseException {
    HashSet<String> hs = new HashSet<String>();
    BufferedReader reader2 = IOUtil.getReader(ResourceBundle.getBundle("library").getString("stopLibrary"), "UTF-8");
    String word = null;
    while ((word = reader2.readLine()) != null) {
        hs.add(word);
    }
    Analyzer analyzer = new AnsjAnalysis(hs,false);
    Directory directory = null;
    IndexWriter iwriter = null;

    BufferedReader reader = IOUtil.getReader("/Users/ansj/Desktop/未命名文件夹/indextest.txt", "UTF-8");
    String temp = null;
    StringBuilder sb = new StringBuilder();
    while ((temp = reader.readLine()) != null) {
        sb.append(temp);
        sb.append("\n");
    }
    reader.close();
    String text = sb.toString();

    text = "开源项目管理你喜欢在室外工作吗?你是个喜欢思考的人吗?你喜欢数学和科学课吗?你喜欢一个人工作吗?你对自己的智力自信吗?你的创造能力很强吗?你喜欢艺术,音乐和戏剧吗?  你喜欢自由自在的工作环境吗?你喜欢尝试新的东西吗? 你喜欢帮助别人吗?你喜欢教别人吗?你喜欢和机器和工具打交道吗?你喜欢当领导吗?你喜欢组织活动吗?你什么和数字打交道吗?";

    IndexWriterConfig ic = new IndexWriterConfig(Version.LUCENE_32, analyzer);
    // 建立内存索引对象
    directory = new RAMDirectory();
    iwriter = new IndexWriter(directory, ic);
    // BufferedReader reader =
    // IOUtil.getReader("/Users/ansj/Documents/快盘/分词/语料/1998年人民日报分词语料_未区分.txt",
    // "GBK");
    // String temp = null;
    // while ((temp = reader.readLine()) != null) {
    // addContent(iwriter, temp);
    // }
    addContent(iwriter, text);
    addContent(iwriter, text);
    addContent(iwriter, text);
    addContent(iwriter, text);
    iwriter.commit();
    iwriter.close();

    System.out.println("索引建立完毕");

    search(analyzer, directory, "室外工作");
}

private Analyzer ansjHeightAnalyzer = new AnsjAnalysis();

private void search(Analyzer analyzer, Directory directory, String queryStr) throws CorruptIndexException, IOException, ParseException {
    IndexSearcher isearcher;
    // 查询索引
    isearcher = new IndexSearcher(directory);
    QueryParser tq = new QueryParser(Version.LUCENE_32, "text", ansjHeightAnalyzer);
    Query query = tq.parse(queryStr);
    System.out.println(query);
    TopDocs hits = isearcher.search(query, 5);
    System.out.println(queryStr + ":共找到" + hits.totalHits + "条记录!");
    for (int i = 0; i < hits.scoreDocs.length; i++) {
        int docId = hits.scoreDocs[i].doc;
        Document document = isearcher.doc(docId);
        System.out.println(toHighlighter(ansjHeightAnalyzer, query, document));
    }
}

/**
 * 高亮设置
 * 
 * @param query
 * @param doc
 * @param field
 * @return
 */
private String toHighlighter(Analyzer analyzer, Query query, Document doc) {
    String field = "text";
    try {
        SimpleHTMLFormatter simpleHtmlFormatter = new SimpleHTMLFormatter("<font color=\"red\">", "</font>");
        Highlighter highlighter = new Highlighter(simpleHtmlFormatter, new QueryScorer(query));
        TokenStream tokenStream1 = analyzer.tokenStream("text", new StringReader(doc.get(field)));
        String highlighterStr = highlighter.getBestFragment(tokenStream1, doc.get(field));
        return highlighterStr == null ? doc.get(field) : highlighterStr;
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (InvalidTokenOffsetsException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
}
private void addContent(IndexWriter iwriter, String text) throws CorruptIndexException, IOException {
    Document doc = new Document();
    doc.add(new Field("text", text, Field.Store.YES, Field.Index.ANALYZED));
    iwriter.addDocument(doc);
}
@Test
public void poreterTest() {
    PorterStemmer ps = new PorterStemmer();
    System.out.println(ps.stem("apache"));
}

Ansj In Solr

已经有热心的大牛,帮我完成了这个。我直接粘贴他的git地址了。有啥问题直接找他与我无关^_^

https://github.com/lgnlgn/ansj4solr

在这里感谢@梁山伯 帅哥。。。

 

Ansj In Elasticsearch

推荐es神器。也是我最喜欢用的一个搜索框架。

已经有热心的大牛,帮我完成了这个。我直接粘贴他的git地址了。有啥问题直接找他与我无关^_^

https://github.com/4onni/elasticsearch-analysis-ansj

在这里感谢@4onni 帅哥。。。

 

词性说明

汉语文本词性标注标记集

# 1. 名词  (1个一类,7个二类,5个三类)
名词分为以下子类:
n 名词
nr 人名
nr1 汉语姓氏
nr2 汉语名字
nrj 日语人名
nrf 音译人名
ns 地名
nsf 音译地名
nt 机构团体名
nz 其它专名
nl 名词性惯用语
ng 名词性语素
nw 新词
# 2. 时间词(1个一类,1个二类)
t 时间词
tg 时间词性语素
# 3. 处所词(1个一类)
s 处所词
# 4. 方位词(1个一类)
f 方位词
# 5. 动词(1个一类,9个二类)
v 动词
vd 副动词
vn 名动词
vshi 动词“是”
vyou 动词“有”
vf 趋向动词
vx 形式动词
vi 不及物动词(内动词)
vl 动词性惯用语
vg 动词性语素
# 6. 形容词(1个一类,4个二类)
a 形容词
ad 副形词
an 名形词
ag 形容词性语素
al 形容词性惯用语
# 7. 区别词(1个一类,2个二类)
b 区别词
bl 区别词性惯用语
# 8. 状态词(1个一类)
z 状态词
# 9. 代词(1个一类,4个二类,6个三类)
r 代词
rr 人称代词
rz 指示代词
rzt 时间指示代词
rzs 处所指示代词
rzv 谓词性指示代词
ry 疑问代词
ryt 时间疑问代词
rys 处所疑问代词
ryv 谓词性疑问代词
rg 代词性语素
# 10. 数词(1个一类,1个二类)
m 数词
mq 数量词
# 11. 量词(1个一类,2个二类)
q 量词
qv 动量词
qt 时量词
# 12. 副词(1个一类)
d 副词
# 13. 介词(1个一类,2个二类)
p 介词
pba 介词“把”
pbei 介词“被”
# 14. 连词(1个一类,1个二类)
c 连词
 cc 并列连词
# 15. 助词(1个一类,15个二类)
u 助词
uzhe 着
ule 了 喽
uguo 过
ude1 的 底
ude2 地
ude3 得
usuo 所
udeng 等 等等 云云
uyy 一样 一般 似的 般
udh 的话
uls 来讲 来说 而言 说来
uzhi 之
ulian 连 (“连小学生都会”)
# 16. 叹词(1个一类)
e 叹词
# 17. 语气词(1个一类)
y 语气词(delete yg)
# 18. 拟声词(1个一类)
o 拟声词
# 19. 前缀(1个一类)
h 前缀
# 20. 后缀(1个一类)
k 后缀
# 21. 字符串(1个一类,2个二类)
x 字符串
 xx 非语素字
 xu 网址URL
# 22. 标点符号(1个一类,16个二类)
w 标点符号
wkz 左括号,全角:( 〔  [  {  《 【  〖〈   半角:( [ { <
wky 右括号,全角:) 〕  ] } 》  】 〗 〉 半角: ) ] { >
wyz 左引号,全角:“ ‘ 『 
wyy 右引号,全角:” ’ 』
wj 句号,全角:。
ww 问号,全角:? 半角:?
wt 叹号,全角:! 半角:!
wd 逗号,全角:, 半角:,
wf 分号,全角:; 半角: ;
wn 顿号,全角:、
wm 冒号,全角:: 半角: :
ws 省略号,全角:……  …
wp 破折号,全角:——   --   ——-   半角:---  ----
wb 百分号千分号,全角:% ‰   半角:%
wh 单位符号,全角:¥ $ £  °  ℃  半角:$

项目的文档地址:http://nlpchina.github.io/ansj_seg/ 

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员阿军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值