`
qindongliang1922
  • 浏览: 2188442 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
7265517b-f87e-3137-b62c-5c6e30e26109
证道Lucene4
浏览量:117659
097be4a0-491e-39c0-89ff-3456fadf8262
证道Hadoop
浏览量:126068
41c37529-f6d8-32e4-8563-3b42b2712a50
证道shell编程
浏览量:60013
43832365-bc15-3f5d-b3cd-c9161722a70c
ELK修真
浏览量:71397
社区版块
存档分类
最新评论

Lucene4.3进阶开发之神游北冥(十八)

阅读更多
原创不易,转载请务必注明,原创地址,谢谢配合!
http://qindongliang1922.iteye.com/blog/2030639

散仙又有一段时间,没更新Lucene的文章了,Lucene版本的更新还是飞快的,现在已经到4.7的版本了,今天,散仙来给大家分享几个Lucene比较有用的小技术。Lucene作为一款优秀的全文检索工具包,自然附带了一些其他比较有用的功能,例如在文本挖掘领域,常常需要统计一些词或短语的TF信息,或者IDF的信息,用来加权某个词条,从而找出某篇新闻,或文献中比较重要的一些关键词或短语,或者我们想得到这些词库的位置信息等等。


下面进入正题,今天散仙就围绕如上所说的,来看下如何利用Lucene来获取TF,IDF,以及term词条的位置信息。


首先,第一个我们来看下如何获取分词后的短语的位置信息,这个功能,主要跟我们的分词器有关系,在分词过程中记录的位置信息,增量信息,载荷等等,我们重点来看下,如何获取位置信息,代码如下:

测试数据
中新网3月12日电 据中国政府网消息,3月12日上午10时15分,李克强总理参加完政协闭幕会后来到国务院应急指挥中心,与前方中国搜救船长通话,了解马航MH370失联客机搜救最新进展情况。李克强要求各有关部门调集一切可能力量,加大搜救密度和力度,不放弃任何一线希望。

	/**
	 * 搜索技术交流群: 324714439
	 * 
	 * 获取分词后term的位置信息
	 * @param word 分词的文本
	 * */
	public void postion(String word)throws Exception{
		
		Analyzer analyzer=new IKAnalyzer();//IK分词
		TokenStream token=analyzer.tokenStream("a", new StringReader(word));
		token.reset();
		CharTermAttribute term=token.addAttribute(CharTermAttribute.class);//term信息
		OffsetAttribute offset=token.addAttribute(OffsetAttribute.class);//位置数据
		while(token.incrementToken()){
		  System.out.println(term+"   "+offset.startOffset()+"   "+offset.endOffset());
		}
		token.end();
		token.close();
	}


输出结果:
中新网   0   3
中新   0   2
新网   1   3
3   3   4
月   4   5
12   5   7
日   7   8
电   8   9
据   10   11
中国政府   11   15
中国   11   13
国政   12   14
政府网   13   16
政府   13   15
网   15   16
消息   16   18
3   19   20
月   20   21
12   21   23
日   23   24
上午   24   26
10   26   28
时   28   29
15   29   31
分   31   32
李克强   33   36
克强   34   36
总理   36   38
参加   38   40
加完   39   41
政协   41   43
闭幕会   43   46
闭幕   43   45
会后   45   47
后来   46   48
来到   47   49
国务院   49   52
国务   49   51
院   51   52
应急   52   54
指挥中心   54   58
指挥   54   56
中心   56   58
与   59   60
前方   60   62
方中   61   63
中国   62   64
搜救   64   66
船长   66   68
通话   68   70
了解   71   73
马   73   74
航   74   75
mh370   75   80
mh   75   77
370   77   80
失   80   81
联   81   82
客机   82   84
搜救   84   86
最新进展   86   90
最新   86   88
新进展   87   90
新进   87   89
进展   88   90
情况   90   92
李克强   93   96
克强   94   96
强要   95   97
要求   96   98
各有   98   100
有关部门   99   103
有关   99   101
有   99   100
关   100   101
部门   101   103
调集   103   105
一切   105   107
切   106   107
可能   107   109
能力   108   110
力量   109   111
加大   112   114
搜救   114   116
密度   116   118
力度   119   121
不放   122   124
放弃   123   125
任何   125   127
一线希望   127   131
一线   127   129
线   128   129
希望   129   131

由上显示,我们可以获取所有短语的位置信息,这个功能在Lucene高亮的时候是非常有用的,如果数据位置发生错位,那么大部分原因都有可能跟这个地方有关系。

第二,我们来看下,如何使用Lucene来获取一片文章中所有短语的词频,这个首先我们的数据是需要索引起来的,并且要开启向量存储的功能,然后我们在去索引里面获取词频,然后,稍作加工,按词频降序输出,由此来直观显示,这篇文章可能重点体现的意思,在这之前,需要对一些常见的禁用词做下处理,以防影响数据结果。

数据和一里面的一样,代码如下:

存储核心代码;

FieldType ft=new FieldType();
		ft.setIndexed(true);//存储
		ft.setStored(true);//索引
		ft.setStoreTermVectors(true);
		ft.setTokenized(true);
		ft.setStoreTermVectorPositions(true);//存储位置
		ft.setStoreTermVectorOffsets(true);//存储偏移量
		Document doc=new Document();
		doc.add(new Field("name", word, ft));
		writer.addDocument(doc);

  获取TF的代码

/**
	 * 读取索引,显示词频
	 * 
	 * **/
    public void getTF(){
	List<Word> list=new ArrayList<Word>();	
	
		try{
			Directory directroy=FSDirectory.open(new File("D:\\lucene测试索引\\2014311测试"));
			IndexReader	  reader= DirectoryReader.open(directroy);
			 for (int i = 0; i < reader.numDocs(); i++) {
		            int docId = i;
		             System.out.println("第"+(i+1)+"篇文档:");
		            Terms terms = reader.getTermVector(docId, "name");
		            if (terms == null)
		                continue;		   
		            TermsEnum termsEnum = terms.iterator(null);
		            BytesRef thisTerm = null;
		            while ((thisTerm = termsEnum.next()) != null) {
		            	String termText = thisTerm.utf8ToString();
		                DocsEnum docsEnum = termsEnum.docs(null, null);
		                while ((docsEnum.nextDoc()) != DocIdSetIterator.NO_MORE_DOCS) {                  
		                	 System.out.println("termText:"+termText+" TF:  "+docsEnum.freq()); 
		                }
 
		                }
		            }
			 
			reader.close();
			directroy.close();
			
			Collections.sort(list);
			
			for(Word w:list){
				System.out.println(w);
			}
			
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
		
	}

输出结果如下:
索引成功了..........
第1篇文档:
关键词: 搜救  词频: 3
关键词: 12  词频: 2
关键词: 3  词频: 2
关键词: 中国  词频: 2
关键词: 克强  词频: 2
关键词: 日  词频: 2
关键词: 月  词频: 2
关键词: 李克强  词频: 2
关键词: 10  词频: 1
关键词: 15  词频: 1
关键词: 370  词频: 1
关键词: mh  词频: 1
关键词: mh370  词频: 1
关键词: 一切  词频: 1
关键词: 一线  词频: 1
关键词: 一线希望  词频: 1
关键词: 上午  词频: 1
关键词: 不放  词频: 1
关键词: 与  词频: 1
关键词: 中国政府  词频: 1
关键词: 中心  词频: 1
关键词: 中新  词频: 1
关键词: 中新网  词频: 1
关键词: 了解  词频: 1
关键词: 任何  词频: 1
关键词: 会后  词频: 1
关键词: 关  词频: 1
关键词: 分  词频: 1
关键词: 切  词频: 1
关键词: 前方  词频: 1
关键词: 力度  词频: 1
关键词: 力量  词频: 1
关键词: 加大  词频: 1
关键词: 加完  词频: 1
关键词: 参加  词频: 1
关键词: 可能  词频: 1
关键词: 各有  词频: 1
关键词: 后来  词频: 1
关键词: 国务  词频: 1
关键词: 国务院  词频: 1
关键词: 国政  词频: 1
关键词: 失  词频: 1
关键词: 客机  词频: 1
关键词: 密度  词频: 1
关键词: 希望  词频: 1
关键词: 应急  词频: 1
关键词: 强要  词频: 1
关键词: 总理  词频: 1
关键词: 情况  词频: 1
关键词: 指挥  词频: 1
关键词: 指挥中心  词频: 1
关键词: 据  词频: 1
关键词: 放弃  词频: 1
关键词: 政协  词频: 1
关键词: 政府  词频: 1
关键词: 政府网  词频: 1
关键词: 新网  词频: 1
关键词: 新进  词频: 1
关键词: 新进展  词频: 1
关键词: 方中  词频: 1
关键词: 时  词频: 1
关键词: 最新  词频: 1
关键词: 最新进展  词频: 1
关键词: 有  词频: 1
关键词: 有关  词频: 1
关键词: 有关部门  词频: 1
关键词: 来到  词频: 1
关键词: 消息  词频: 1
关键词: 电  词频: 1
关键词: 线  词频: 1
关键词: 网  词频: 1
关键词: 联  词频: 1
关键词: 能力  词频: 1
关键词: 航  词频: 1
关键词: 船长  词频: 1
关键词: 要求  词频: 1
关键词: 调集  词频: 1
关键词: 进展  词频: 1
关键词: 通话  词频: 1
关键词: 部门  词频: 1
关键词: 闭幕  词频: 1
关键词: 闭幕会  词频: 1
关键词: 院  词频: 1
关键词: 马  词频: 1


最后,我们来看下,如何获取IDF,
核心代码如下:

/**
 * 计算IDF
 * 
 * **/
	public void printIDF(){
		
		try{
			Directory directroy=FSDirectory.open(new File("D:\\lucene测试索引\\2014311测试"));
			IndexReader	  reader= DirectoryReader.open(directroy);
			List<AtomicReaderContext>  list=reader.leaves();
			for(AtomicReaderContext ar:list){
				String field="name";
				AtomicReader areader=ar.reader();
				Terms term=areader.terms("name");
				TermsEnum tn=term.iterator(null);
				  
			    BytesRef text;
			    while((text = tn.next()) != null) {
			   
			      System.out.println("field=" + field + "; text=" + text.utf8ToString()+"   IDF : "+tn.docFreq()
			    	 // +" 全局词频 :  "+tn.totalTermFreq()
			    		  );
			      
			       
			      
			  }
			}
			reader.close();
			directroy.close();
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
		
	}


输出结果如下:
索引成功了..........
field=name; text=10   IDF : 1
field=name; text=12   IDF : 1
field=name; text=15   IDF : 1
field=name; text=3   IDF : 1
field=name; text=370   IDF : 1
field=name; text=mh   IDF : 1
field=name; text=mh370   IDF : 1
field=name; text=一切   IDF : 1
field=name; text=一线   IDF : 1
field=name; text=一线希望   IDF : 1
field=name; text=上午   IDF : 1
field=name; text=不放   IDF : 1
field=name; text=与   IDF : 1
field=name; text=中国   IDF : 1
field=name; text=中国政府   IDF : 1
field=name; text=中心   IDF : 1
field=name; text=中新   IDF : 1
field=name; text=中新网   IDF : 1
field=name; text=了解   IDF : 1
field=name; text=任何   IDF : 1
field=name; text=会后   IDF : 1
field=name; text=克强   IDF : 1
field=name; text=关   IDF : 1
field=name; text=分   IDF : 1
field=name; text=切   IDF : 1
field=name; text=前方   IDF : 1
field=name; text=力度   IDF : 1
field=name; text=力量   IDF : 1
field=name; text=加大   IDF : 1
field=name; text=加完   IDF : 1
field=name; text=参加   IDF : 1
field=name; text=可能   IDF : 1
field=name; text=各有   IDF : 1
field=name; text=后来   IDF : 1
field=name; text=国务   IDF : 1
field=name; text=国务院   IDF : 1
field=name; text=国政   IDF : 1
field=name; text=失   IDF : 1
field=name; text=客机   IDF : 1
field=name; text=密度   IDF : 1
field=name; text=希望   IDF : 1
field=name; text=应急   IDF : 1
field=name; text=强要   IDF : 1
field=name; text=总理   IDF : 1
field=name; text=情况   IDF : 1
field=name; text=指挥   IDF : 1
field=name; text=指挥中心   IDF : 1
field=name; text=据   IDF : 1
field=name; text=搜救   IDF : 1
field=name; text=放弃   IDF : 1
field=name; text=政协   IDF : 1
field=name; text=政府   IDF : 1
field=name; text=政府网   IDF : 1
field=name; text=新网   IDF : 1
field=name; text=新进   IDF : 1
field=name; text=新进展   IDF : 1
field=name; text=方中   IDF : 1
field=name; text=日   IDF : 1
field=name; text=时   IDF : 1
field=name; text=最新   IDF : 1
field=name; text=最新进展   IDF : 1
field=name; text=月   IDF : 1
field=name; text=有   IDF : 1
field=name; text=有关   IDF : 1
field=name; text=有关部门   IDF : 1
field=name; text=李克强   IDF : 1
field=name; text=来到   IDF : 1
field=name; text=消息   IDF : 1
field=name; text=电   IDF : 1
field=name; text=线   IDF : 1
field=name; text=网   IDF : 1
field=name; text=联   IDF : 1
field=name; text=能力   IDF : 1
field=name; text=航   IDF : 1
field=name; text=船长   IDF : 1
field=name; text=要求   IDF : 1
field=name; text=调集   IDF : 1
field=name; text=进展   IDF : 1
field=name; text=通话   IDF : 1
field=name; text=部门   IDF : 1
field=name; text=闭幕   IDF : 1
field=name; text=闭幕会   IDF : 1
field=name; text=院   IDF : 1
field=name; text=马   IDF : 1

转载请务必注明,原创地址,谢谢配合!
http://qindongliang1922.iteye.com/blog/2030639
分享到:
评论
5 楼 yuhe 2014-08-15  
标题很蛋疼,没指明文章的主讲内容。

使用  Lucene来获取TF,IDF,以及term词条的位置信息  作为标题,是不是会更好?
4 楼 qindongliang1922 2014-06-10  
YANGSONGone 写道
就只有一片文档吧

你还想要啥
3 楼 YANGSONGone 2014-06-10  
就只有一片文档吧
2 楼 qindongliang1922 2014-03-18  
qq911110 写道
请问为什么IDF的值都是一样的为1

就一篇测试文章,当然是1了
1 楼 qq911110 2014-03-18  
请问为什么IDF的值都是一样的为1

相关推荐

Global site tag (gtag.js) - Google Analytics