Lucene学习——IKAnalyzer中文分词(二)

来源:互联网 发布:斗鱼不承认淘宝鱼丸 编辑:程序博客网 时间:2024/04/28 19:25

一、环境

1、平台:MyEclipse8.5/JDK1.5

2、框架:Lucene3.6.1/IKAnalyzer2012/htmlparser

二、目标

1、整合前面连篇文章(Lucene学习——IKAnalyzer中文分词(一)和Lucene学习——初探搜索引擎),使该搜索引擎雏形支持中文站点

2、试图发现些什么

三、开发调试

1、改写原有的搜索引擎程序,利用IKAnalyzer使之支持中文分词,代码如下

package org.cyxl.lucene.test;import java.io.File;import java.io.IOException;import java.util.ArrayList;import java.util.List;import org.apache.lucene.analysis.Analyzer;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;import org.apache.lucene.index.CorruptIndexException;import org.apache.lucene.index.IndexReader;import org.apache.lucene.index.IndexWriter;import org.apache.lucene.index.IndexWriterConfig;import org.apache.lucene.index.IndexWriterConfig.OpenMode;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.ScoreDoc;import org.apache.lucene.search.Searcher;import org.apache.lucene.search.TopScoreDocCollector;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.util.Version;import org.htmlparser.NodeFilter;import org.htmlparser.Parser;import org.htmlparser.beans.StringBean;import org.htmlparser.filters.NodeClassFilter;import org.htmlparser.tags.LinkTag;import org.htmlparser.util.NodeList;import org.htmlparser.util.ParserException;import org.htmlparser.visitors.HtmlPage;import org.wltea.analyzer.lucene.IKAnalyzer;public class ParseURL {//索引目录private static final String INDEX_DIR = "myindex";//已经存在的url列表private static List<String> urls=new ArrayList<String>();/** * 索引器,对目标url创建索引 * @param url目标网址 * @throws IOException * @throws ParserException */@SuppressWarnings("deprecation")private static void indexer(String url) throws IOException, ParserException {//存储索引的目录File indexDir = new File(INDEX_DIR);//目录不存在,创建该目录if (!indexDir.exists()) {indexDir.mkdir();}//获取网页纯文本String content = getText(url);//获取网页标题String title = getTitle(url);System.out.println("title:" + title);if(title==null || content==null || content.trim().equals("")){return;}//System.out.println("content:" + content);//URL path=new URL(url);//InputStream stream=path.openStream();////Reader reader=new InputStreamReader(stream);//Reader reader=new InputStreamReader(new ByteArrayInputStream(content.getBytes()));//Reader reader2=new InputStreamReader(new ByteArrayInputStream(title.getBytes()));Document doc = new Document();//加入url域doc.add(new Field("url", url, Field.Store.YES,Field.Index.NOT_ANALYZED));//加入标题域doc.add(new Field("title", title, Field.Store.YES,Field.Index.ANALYZED));//doc.add(new Field("title",reader2));//Index.ANALYZED分词后构建索引//加入内容域doc.add(new Field("content", content, Field.Store.YES,Field.Index.ANALYZED));//doc.add(new Field("content",reader));//创建IKAnalyzer中文分词对象Analyzer analyzer=new IKAnalyzer();//索引目录Directory dir=FSDirectory.open(indexDir);//配置IndexWriterConfigIndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_36 , analyzer);iwConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);//创建写索引对象IndexWriter writer = new IndexWriter(dir,iwConfig);//写入文档writer.addDocument(doc);//关闭writer.close();//创建了索引的网址加入到已经存在的网址列表中urls.add(url);}/** * 搜索器,根据输入的文本去搜索 * @param words输入的文本 * @param field搜索的域 * @throws CorruptIndexException * @throws IOException * @throws ParseException */@SuppressWarnings("deprecation")private static void searcher(String words,String field) throws CorruptIndexException,IOException, ParseException {File indexDir = new File(INDEX_DIR);//索引目录Directory dir=FSDirectory.open(indexDir);//根据索引目录创建读索引对象IndexReader reader = IndexReader.open(dir);//搜索对象创建IndexSearcher searcher = new IndexSearcher(reader);//IKAnalyzer中文分词Analyzer analyzer = new IKAnalyzer();//创建查询解析对象QueryParser parser = new QueryParser(Version.LUCENE_36,field, analyzer);parser.setDefaultOperator(QueryParser.AND_OPERATOR);//根据域和目标搜索文本创建查询器Query query = parser.parse(words);System.out.println("Searching for: " + query.toString(field));//对结果进行相似度打分排序TopScoreDocCollector collector = TopScoreDocCollector.create(5 * 10,false);searcher.search(query, collector);//获取结果ScoreDoc[] hits = collector.topDocs().scoreDocs;int numTotalHits = collector.getTotalHits();System.out.println(numTotalHits + " total matching pages");//显示搜索结果for (int i = 0; i < hits.length; i++) {Document doc = searcher.doc(hits[i].doc);String url = doc.get("url");String title=doc.get("title");String content=doc.get("content");System.out.println((i + 1) + "." + title);System.out.println("-----------------------------------");System.out.println(content.substring(0,100)+"......");System.out.println("-----------------------------------");System.out.println(url);System.out.println();}}/** * 收入网站 * @param url网站首页url,也可以为网站地图url * @throws ParserException * @throws IOException * @throws ParseException */private static void addSite(String url) throws ParserException, IOException, ParseException{long start=System.currentTimeMillis();System.out.println("start add...");//获取目标网页的所有链接List<String> links = getLinks(url);System.out.println("url count:"+links.size());for(int i=0;i<links.size();i++){String link=links.get(i);System.out.println((i+1)+"."+link);if(!urls.contains(link)){//对未创建过索引的网页创建索引indexer(link);}else{System.out.println("["+link+"] exist");}}System.out.println("end...");long end=System.currentTimeMillis();System.out.println("cost "+(end-start)/1000+" seconds");}/** * 获取网页纯文本 * @param url目标网址 * @return * @throws ParserException */private static String getText(String url) throws ParserException {StringBean sb = new StringBean();// 设置不需要得到页面所包含的链接信息sb.setLinks(false);// 设置将不间断空格由正规空格所替代sb.setReplaceNonBreakingSpaces(true);// 设置将一序列空格由一个单一空格所代替sb.setCollapse(true);// 传入要解析的URLsb.setURL(url);// 返回解析后的网页纯文本信息String content = sb.getStrings();// System.out.println(content);return content;}/** * 获取网页标题 * @param path * @return * @throws IOException * @throws ParserException */private static String getTitle(String path) throws IOException,ParserException {String title = "";try {Parser parser=new Parser(path);HtmlPage page = new HtmlPage(parser);          parser.visitAllNodesWith(page);         title=page.getTitle();} catch (Exception e) {// TODO Auto-generated catch block//e.printStackTrace();title = "no title";}return title.trim();}/** * 获取网页中所有的链接 * @param url * @return * @throws ParserException */private static List<String> getLinks(String url) throws ParserException{List<String> links=new ArrayList<String>();//创建链接节点的过滤器NodeFilter filter = new NodeClassFilter(LinkTag.class);  Parser parser = new Parser();  parser.setURL(url);//设置目标网页的编码方式//parser.setEncoding("utf-8");//因为有些时候不清楚目标网页的编码方式,这里我们采用指定一//个编码集合,然后通过试探的方式得到目标网页的编码方式parser.setEncoding(CharsetAutoSwitch.dectedEncode(url));  NodeList list = parser.extractAllNodesThatMatch(filter);  for (int i = 0; i < list.size(); i++) {  LinkTag node = (LinkTag) list.elementAt(i);//获取链接的目标网址String link=node.extractLink();if(link!=null && !link.trim().equals("") && !link.equals("#")){//将目标网址加入到该页面的所有网址列表中links.add(link);  }}return links;}public static void main(String[] args) throws IOException, ParseException,InterruptedException, ParserException {String url = "http://www.csdn.net/";//收录网站addSite(url);//搜有标题带有“搜索引擎”字眼的网页searcher("搜索引擎","title");}}


2、测试结果,如下

加载扩展词典:ext.dic加载扩展停止词典:stopword.dic加载扩展停止词典:chinese_stopword.dicSearching for: +搜索引擎 +搜索 +索引 +引擎3 total matching pages1.搜索引擎-CSDN.NET-----------------------------------搜索引擎-CSDN.NET业界移动开发云计算软件研发专题程序员杂志产品创业职场人物设计开源iOSAndroidWindowsPhoneH......-----------------------------------http://www.csdn.net/article/tag/%E6%90%9C%E7%B4%A2%E5%BC%95%E6%93%8E2.充分使用HTML5特性进行搜索引擎优化(SEO) | Intel? Developer Zone-----------------------------------充分使用HTML5特性进行搜索引擎优化(SEO) | Intel? Developer Zone跳转到主要内容Intel? Developer Zone社区按行业焦点选择游戏和媒体......-----------------------------------http://g.csdn.net/52316403.庞果网-Pongo.cn -IT互联网计算机通信领域职位搜索引擎-----------------------------------庞果网-Pongo.cn -IT互联网计算机通信领域职位搜索引擎企业用户登录CSDN会员可直接登录帐 号密 码记住我 忘记密码").append("我的pongo |"......-----------------------------------http://www.pongo.cn


3、具体的代码解释根据代码注释进行理解

四、总结

1、由于IKAnalyzer2012只支持Lucene3.3以上版本,所以我们这里采用Lucene3.6.1,和之前的方式稍微有些差别,具体参见代码和注释

2、该程序已经支持了中文站点的收录的搜索,以初步达成了中文分词和搜索的目的

3、试图发现些什么,主要有一下几点

       1)ext.dic自己的词典如何扩展。比如我们这里收录了CSDN网站,由于它是一个以程序开发为主的博客站点,所以我们搜索“搜索引擎”时,应该将其看成一个词,而不是分成“搜索引擎 +搜索 +索引 +引擎”,还有“存储过程”等,我们可以将其加入到扩展词典中。这里主要跟项目的业务关系比较大,所以应该根据项目来确定扩展词典

       2)chinese_stopword.dic的扩展也可以根据项目业务来扩展,但这个相对固定和简单些

       3)对于网站的收录,这里只做了简单的首页中链接的挖掘。实际收录时可以更加深层次的挖掘出所有该站点的页面。但某页面如何判定是否属于该站点对我目前来说是一个难点,希望知者不吝赐教

       4)该程序只是个简单的测试雏形,如何使之有用值得我去思考