`
wangdei
  • 浏览: 374372 次
社区版块
存档分类
最新评论

不用词典利用Lucene取标题中的关键字

阅读更多

一.问题提出:像这样的"[TVB2008][溏心风暴之家好月圆][国语][DVD-RMVB][第01集]|BT285.cn|BT下载|BT电影|BT软件"的标题,我们怎样提取出关键字"家好月圆",当然是在电影或是电视剧的范围内.
        二.不用词典,你用什么方式分词.

解决方法:
      1.针对此网站大部分都是BT下载,一般都是电影,电视剧,动漫.先对整个网站的标题进行Lucene索引.
      2.去掉一些常用符号如:数字,字母,标志符.如"[TVB2008][溏心风暴之家好月圆][国语][DVD-RMVB][第01集]|BT285.cn|BT下载|BT电影|BT软件" 变成"溏心风暴之家好月圆 国语 第 集"
      3.采用二元分法.如"溏心风暴之家好月圆 国语 第 集" 分拆成"溏心 心风 风暴 暴之 之家 家好 好月 圆 国语 第 集"
      4.采用统计方法,对一些高频词去掉,如"国语 第 集" 因为"国语" 出现次数3000次(注:数据库的数据有25万条),"第"与"集"也如此.
      5.对"溏心 心风 风暴 暴之 之家 家好 好月 圆 国语 第 集"进行分析并统计次数.
      6.按最长连接词拼凑.按一定的比例组合划分.
      7.得出"家好月圆"为其关键字

 上代码:

package com.wwy.lucene;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Searcher;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.funinhand.orm.database.base.Page;
import com.funinhand.shld.dao.Bt285DAO;
import com.funinhand.shld.dao.WNewsDAO;
import com.funinhand.shld.pojo.Bt285;
import com.funinhand.shld.pojo.WNews;
import com.wwy.thread.Configure;

/**
 * 本代码在下面的网站中测试过并取的60%左右的有效数.
 * 
 * http://www.bt285.cn BT下载 
 * http://www.yaonba.com.cn NBA中文网
 * http://www.5a520.cn 小说520网 
 * http://www.vagaaga.cn vagaa
 *author by wangdei
 *2008-6-12 上午11:16:41
 *
 */

public class KeyWordLucene {
	
		private static Logger logger = Logger.getLogger(KeyWordLucene.class);
		
		public static String[] StopStrs = {"BT285","BT软件","BT电影","BT下载"};
		
		
		public static String path = null ;
		
		private List<DataModel> sentenceList = new ArrayList<DataModel>();
		
		public KeyWordLucene(){
			logger.debug("KeyWordLucene init");
		}
		public int queryMatchSize(String queryStr,String lucennePath){		
			Searcher searcher = null;
			try {
			    searcher = new IndexSearcher(lucennePath);// "index"指定索引文件位置
				Document doc = new Document();
				StandardAnalyzer analyzer = new StandardAnalyzer(StopStrs);
				// 一段简单的检索代码
				QueryParser queryParser = new QueryParser("title", analyzer);
				Query query = queryParser.parse(queryStr);
				// 检索	
				Hits hits = searcher.search(query);
				int size = hits.length();
				searcher.close();
				return size;
			} catch (Exception e) {
				return 0;
			}finally{
				 if(searcher!=null){   
				     try {   
				    	 searcher.close();   
				     }   
				     catch (Exception e) {}   
				     searcher = null;   
				   }   

			}
			
		}
		
		
		public boolean stopWord(String word){
			char charAsi = word.toCharArray()[0];
			int intAsi = (int)charAsi;
			if(intAsi<127)
				return true;
			/*
			 * 65293 -,12289 、,9670 ◆,9733 ★,12300 「,8545 Ⅱ,65281 !,65288 ( ,65306 :,
			 */
			int[] asiExpert = {65293,12289,9670,9733,12300,8545,65281,65288,65306};
			for(int i=0;i<asiExpert.length;i++){
				if(asiExpert[i] == intAsi)
					return true;
			}
			String[] str = {"【","】","[","]","."," ","/","\\","》","《","?","的"};
			for(int i=0;i<str.length;i++){
				if(word.equals(str[i]))
					return true;
			}
			return false;
		}
		
		/**
		 * 返回整个句子的集合
		 *  cat news Id=211562,【There.Will.Be.Blood.血色黑金.2007.Blu-ray.a1080.x264.DD51 D9】
			 血色=165,j=21,time=23
			 色黑=19,j=22,time=23
			 黑金=86,j=23,time=23
		 * @param news
		 * @return
		 */
		private void charMatch(WNews news){
			sentenceList.clear();
			String title = news.getTitle();
			int matchSize = 0;
			int length = title.length();
			for(int j=0;j<length-2;j++){
				if(stopWord(title.substring(j,j+1)) || stopWord(title.substring(j+1,j+2)))
						continue;
				DataModel dataModel = new DataModel();
				long begin = System.currentTimeMillis();
				matchSize =queryMatchSize(title.substring(j,j+2), path);
				long needsTime = (System.currentTimeMillis()-begin);
				dataModel.setName(title.substring(j,j+2));
				dataModel.setSize(matchSize);
				dataModel.setLocation(j);
				dataModel.setNeedTime(needsTime);
				//logger.debug(dataModel.toString());
				sentenceList.add(dataModel);
			}
		}
		
		/**
		 * 提取字符串的.
		 * [古天乐刘若英最新钜献][我们这一家][粤语中字][那些发垃圾信息的不是我]
		 * [天乐=122,j=2,time=16,
		 *  刘若=84,j=4,time=16, 
		 *  若英=84,j=5,time=0,
		 *  最新=10298,j=7,time=31, 
		 * 钜献=11,j=9,time=16, 
		 * 我们=441,j=13,time=15, 
		 * 一家=518,j=16,time=16, 
		 * 语中=31128,j=21,time=63,
		 * 中字=36065,j=22,time=78,
		 * 那些=17,j=26,time=16, 
		 * 垃圾=24,j=29,time=94,
		 * 信息=12,j=31,time=0, 
		 * 不是=167,j=34,time=15]
		 */
		private void pickChar(){
			List<DataModel> tempList = new ArrayList<DataModel>();
			int size = sentenceList.size();
			//取二元比较字符串
			int i = 0;
			while(i<size){									
				DataModel dataModel1 = sentenceList.get(i);
				if(i == size-1){
					tempList.add(dataModel1);
					sentenceList.clear();
					setSentenceList(tempList);
					return;
				}
				DataModel dataModel2 = sentenceList.get(i+1);
				int location1 = dataModel1.getLocation();
				int location2 = dataModel2.getLocation();
				//如果是相邻的
				if(location1 +1  == location2){
					if(dataModel1.getSize()>=dataModel2.getSize())
						tempList.add(dataModel1);
					else
						tempList.add(dataModel2);
					i+=2;
					if(i == size){
						//加最后一个字
						sentenceList.clear();
						setSentenceList(tempList);
						return;
					}
				}else{
					tempList.add(dataModel1);
					//tempList.add(dataModel2);
					i++;
				}
			}
			return;
		}
		
		/**
		 * 去掉出现机率大的字符:如美国,大片,影视,==
		 *
		 */
		private void delRateBigChar(){
			List<DataModel> tempList = new ArrayList<DataModel>();
			int size = sentenceList.size();
			int i = 0;
			while(i<size){									
				DataModel dataModel = sentenceList.get(i);
				if(dataModel.getSize()>1000){
					i++;
					continue;
				}
				tempList.add(dataModel);
				i++;
			}
			sentenceList.clear();
			setSentenceList(tempList);
		}
		
		/**
		 * 组合字符
		 *
		 */
		private String compisteChar(){
			List<DataModel> tempList = new ArrayList<DataModel>();
			int size = sentenceList.size();
			int i = 0;		
			while(i<size){
				int j = i;
				DataModel dataModel = new DataModel("",0,0);
				StringBuffer sb = new StringBuffer(); 
				boolean isFetch = false;
				while(j<size){				
					DataModel dataModelJ1 = sentenceList.get(j);
					int location1 = dataModelJ1.getLocation();			
					if(j == size-1){
						dataModel.setName(dataModel.getName() + dataModelJ1.getName());
						dataModel.setLocation(dataModel.getLocation() + dataModelJ1.getLocation());
						dataModel.setAfterLocation(dataModelJ1.getAfterLocation());
						tempList.add(dataModel);
						break;
					}
					DataModel dataModelJ2 = sentenceList.get(j+1);
					int location2 = dataModelJ2.getLocation();
					if(dataModel.getAfterLocation() +2 <location1 && isFetch){
						tempList.add(dataModel);
						break;
					}						
					if(location1 +1==location2){
						isFetch = true;
						sb.append(dataModelJ1.getName() +dataModelJ2.getName().substring(1));
						dataModel.setName(dataModel.getName() + sb.toString());
						dataModel.setAfterLocation(dataModelJ2.getAfterLocation());
						dataModel.setLocation(dataModel.getLocation() + dataModelJ1.getLocation()+ dataModelJ2.getLocation());
					}
					else if(location1 +2==location2){
						isFetch = true;
						sb.append(dataModelJ1.getName() +dataModelJ2.getName());
						dataModel.setName(dataModel.getName() + sb.toString());
						dataModel.setAfterLocation(dataModelJ2.getAfterLocation());
						dataModel.setLocation(dataModel.getLocation() + dataModelJ2.getLocation());
					}
					else{
						dataModel.setName(dataModel.getName() + sb.toString());
						dataModel.setAfterLocation(dataModelJ2.getAfterLocation());
						dataModel.setLocation(dataModel.getLocation() + dataModelJ1.getLocation()+ dataModelJ2.getLocation());
						tempList.add(dataModel);
						break;
					}
					j+=2;
					if(j == size){
						tempList.add(dataModel);
						break;
					}
				}
				i++;
			}
			//取最长的字符串
			int tempSize = tempList.size();
			//如果字符串都超过给定的最大值时,或是其他情况
			if(tempSize == 0)
				return null;
			DataModel dataModelInit = tempList.get(0);		
			for(int k=1;k<tempSize;k++){
				String nameInit = dataModelInit.getName();
				DataModel dataModel = tempList.get(k);
				String name = dataModel.getName();
				if(name.length()>nameInit.length())
					dataModelInit.setName(name);
			}
			logger.info("getName()=" +dataModelInit.getName());
			return dataModelInit.getName();
		}
		public String seqAction(WNews news){
			if(logger.isDebugEnabled())
				logger.debug("KeyWordLucene seqAction is begin");
			charMatch(news);
			pickChar();
			delRateBigChar();
			return compisteChar();
		}
		public static void main(String[] args) throws Exception {
			System.out.println("server begin!");
			Configure.propertiesConfigure();
			 path = Configure.getCreateBtLucenePath();
			ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
			"./mysqlContext.xml");
			WNewsDAO newsDAO = (WNewsDAO) appContext.getBean("wNewDaoProxy");
			Bt285DAO bt285DAO = (Bt285DAO)appContext.getBean("bt285DAO");
			KeyWordLucene action = new KeyWordLucene();
			for(int i=1;i<3;i++){
				try {
					Thread.sleep(1000L);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				Page page = new Page();
				logger.info("i=" + i);
				page.setPageIndex(i);
				page.setPageSize(1000);
				List<WNews> list = bt285DAO.findPageByQuery(
						"select t from wnews t ",null, page);
				for(WNews news:list){
					//if(news.getId() != 212142)
						//continue;
					logger.debug("cat news Id=" + news.getId() +"," + news.getTitle());
					action.seqAction(news);
				}
			}
			
			//action.batchCreate();		
			
			System.out.println(URLEncoder.encode("天兆","UTF-8"));//%E5%A4%A9%E5%85%86
			System.out.println("server finish!");
		}


		public List<DataModel> getSentenceList() {
			return sentenceList;
		}


		public void setSentenceList(List<DataModel> sentenceList) {
			this.sentenceList = sentenceList;
		}
}

 

测试用例:
日本H动漫下载)鬼作第五夜-杉本翔子 
[TVB2008][当狗爱上猫][国语][DVD-RMVB][04-05集]
夜来香社区官方网站
结论:60%有效.

不足之处:
 1.没有采用词典,而用二元分,速度慢,词有较大的二意性.
 2.有些词用统计方法不准确.
 3.干扰系数较大.

 续,准备采用词典

4
0
分享到:
评论

相关推荐

    利用lucene实现文档关键字检索

    在这个使用案例中,我们将深入探讨如何利用Lucene实现对Word文档中的关键字检索并高亮显示结果。 首先,我们需要理解Lucene的基本工作原理。Lucene通过建立倒排索引(Inverted Index)来加速查询。倒排索引是一种...

    Lucene建索引及查询关键字

    在Eclipse环境中运用java,Lucene建索引及查询关键字

    lucene3.6.1文件关键字搜索代码(附加核心包)

    在标题中提到的"lucene3.6.1文件关键字搜索代码(附加核心包)"是一个基于Lucene 3.6.1版本的示例项目,主要目的是帮助初学者理解和掌握如何使用Lucene进行文件中的关键字搜索。 Lucene的主要功能包括: 1. **文本...

    Lucene5学习之Suggest关键字提示

    《深入探索Lucene5:Suggest关键字提示技术》 在信息检索领域,用户输入查询时,提供快速、准确的关键字提示能显著提升用户体验。Lucene,作为Java领域最流行的全文检索库,其5.x版本引入了Suggest组件,用于实现...

    Lucene5学习之Highlighte关键字高亮

    在信息技术领域,搜索引擎的使用已经变得无处不在,而其中的关键技术之一就是如何有效地突出显示搜索结果中的关键字,这就是我们今天要探讨的主题——Lucene5中的Highlighter模块。Lucene是一个开源全文检索库,它...

    android+lucene实现全文检索并高亮关键字索引库

    下面我们将深入探讨如何在Android环境中利用Lucene来创建一个高效、功能丰富的全文检索系统,并了解如何高亮显示搜索结果中的关键字。 首先,我们要理解全文检索的基本原理。全文检索是指通过建立倒排索引来快速...

    Lucene3.0增删改查和关键字高亮实例

    在这个“Lucene3.0增删改查和关键字高亮实例”项目中,我们将深入理解如何利用Lucene 3.0版本进行索引构建、文档的增删改查操作,并学习关键字高亮显示的实现方法。 首先,我们要了解**创建索引**的基本流程。在...

    android+lucene实现全文检索并高亮关键字

    在Android平台上实现全文检索并高亮关键字是一项技术挑战,但通过集成Apache Lucene库,可以有效地解决这个问题。Apache Lucene是一个高性能、可扩展的信息检索库,它为开发人员提供了强大的文本搜索功能。以下是对...

    支持lucene的词典机械中文分词

    本文将深入探讨一种基于Lucene的词典机械中文分词方法,该方法采用了反向机械分词算法,尤其关注对数字、英文以及中英文数字混合词的特殊处理,旨在提高分词速度和准确性。 首先,反向机械分词算法是一种常用的中文...

    lucene.NET 中文分词

    - **使用内存词典**:在处理大量数据时,可以考虑将词典加载到内存中,减少磁盘I/O操作,提高分词速度。 - **批量处理**:对于大批量的文档,应尽量批量添加到索引,以利用内部优化减少开销。 - **缓存策略**:合理...

    Lucene建立索引及查询包含“java”关键字 示例代码

    **Lucene创建索引与搜索"java"关键字的示例代码** Apache Lucene是一个高性能、全功能的文本搜索引擎库,广泛应用于各种系统中用于实现高效、精准的全文检索功能。这个示例代码将向我们展示如何使用Lucene来创建一...

    luceneDemo(创建索引+关键字查询)

    创建索引 一、创建词法分析器 二、创建索引存储目录 三、创建索引写入器 四、将内容存储到索引 关键字查询 一、创建索引存储目录读取器 二、创建索引搜索器 三、解析查询 四、获取结果

    Lucene与数据库结合示例(加双关键字高亮)

    “Lucene与数据库结合示例(加双关键字高亮)”这个标题表明,我们将讨论如何将开源全文搜索引擎Lucene与关系型数据库MySQL整合在一起,并且在搜索结果中实现关键词高亮显示,以提升用户体验。这通常涉及到数据的...

    基于词典的最大匹配的Lucene中文分词程序

    在Lucene中,我们可以使用IK Analyzer、Smart Chinese Analyzer或HanLP等第三方分词器,它们都实现了基于词典的最大匹配分词策略。这些分词器通常包括以下步骤: - 读取词典:加载词典文件,构建Trie树或其他高效的...

    利用lucene进行搜索

    利用lucene进行搜索,IndexSearcher是整个Lucene搜索查询相关信息的驱动引擎,在使IndexSearcher之前,需要构建IndexSearcher对象,Lucene提供了两种构建IndexSearcher对象的方式: 1、基于Directory对象构建; 2...

    利用Lucene 实现高级搜索

    例如,若文档由多个字段组成,如标题(Title)和内容(Content),则可以通过“Title:Lucene AND Content:Java”这样的查询,精确查找标题中包含“Lucene”,同时内容中包含“Java”的文档。 #### 代码示例 以下是...

    lucene 3.0 API 中文帮助文档 chm

    lucene 3.0 API中文帮助,学习的人懂得的

    lucene4.10

    当用户输入查询字符串时,IKAnalyzer会对其进行分词处理,生成对应的查询关键字,然后Lucene会使用这些关键字在倒排索引中进行查找,返回匹配的文档。通过这种方式,即使面对复杂的中文查询,也能快速找到相关结果。...

    关于Lucene的词典FST深入剖析-申艳超1

    《关于Lucene的词典FST深入剖析》这篇文章是由申艳超撰写的,主要探讨了Apache Lucene这个全文搜索引擎库中的一个关键数据结构——有限状态转换器(Finite State Transducer,简称FST)。FST在Lucene中被用于构建和...

    lucene 3.0 API 中文帮助文档

    1. **Analyzer**: 分析器是Lucene中的核心组件之一,负责将输入的文本分解成可搜索的词项(tokens)。在3.0版本中,Lucene提供了多种预定义的Analyzer,如StandardAnalyzer,它们可以处理不同语言的文本。 2. **...

Global site tag (gtag.js) - Google Analytics