Java应用开源框架实现简易web搜索引擎
引言
应用Java的开源库,编写一个搜索引擎,这个引擎能爬取一个网站的内容。并根据网页内容进行深度爬取,获取所有相关的网页地址和内容,用户可以通过关键词,搜索所有相关的网址。
具体功能
(1)用户可以指定爬取一个url对应的网页的内容。
(2)对网页内容进行解析,并获取其中所有的url链接地址。
(3)用户可以设定爬取深度,代表着从初始url对应的页面开始,可以爬取其中所有的url对应的网页内的url,以此类推。深度越大,能爬取到的网站越多。
(4)对爬取到的url内容进行保存、建立索引。建立索引的内容是url地址本身,和url对应的网页标题。
(5)用户可以通过关键词对网址进行搜索,找出有该关键词的url地址。
(6)建立索引和搜索索引的过程能智能识别中文关键词,能对关键词进行分词操作。
(7)用户可以指定保存索引的地址、初始url、爬取深度、进行搜索的关键词和最大匹配项。
开源框架
- Lucene
- Jsoup
源码
爬虫部分:Spider.java
packagewebCrawler.Spider; importjava.io.IOException; importjava.util.ArrayList; importjava.util.HashSet; importjava.util.Scanner; importorg.jsoup.Jsoup; importorg.jsoup.nodes.Document; importorg.jsoup.nodes.Element; importorg.jsoup.select.Elements; importwebCrawler.Index.BuildIndex; /** *@authorlannooo */ publicclassSpider{ ArrayListURLs; privateStringstartURL; privateintdigLevel; /** *@paramstartURL爬虫的起始URL *@paramdigLevel爬取深度 */ publicSpider(StringstartURL,intdigLevel){ this.startURL=startURL; this.digLevel=digLevel; this.URLs=newArrayList<>(); } /** *@paramlevel当前爬取的深度剩余 *@paramarrayList需要进行下一轮爬去的URL集 *@return从一格url集爬取到的新的URL集 *@throwsIOException */ publicArrayList getLevelURLs(intlevel,ArrayList arrayList) throwsIOException{ ArrayList total=null; if(level>0){ total=newArrayList<>(); for(Stringurl:arrayList){ /*对于每个arrayList中的URL,首先解析其网页内容,并获得里面所有URL项*/ for(Stringeach:getBareLinks(url)){ total.add(each); } } /*用HashSet这个容器将total里面重复项删除*/ HashSet hashSet=newHashSet<>(total); total=newArrayList<>(hashSet); } returntotal; } /** *从startURL开始,爬取所有相关URLs *@throwsIOException */ publicvoidgetAll()throwsIOException{ ArrayList newURLs; ArrayList currentURLs=newArrayList<>(); /*把startURL加入currentURLs这个列表中,从这个url开始爬*/ currentURLs.add(startURL); for(inti=digLevel;i>0;i--){ /* *对于每一层,都要获取一次由这个url引申出去的url集 *然后把当前集的已经爬去过的url加入到总的URL集中 *最后newURLs作为新的需要进行深度爬取的集进入下一轮循环 */ System.out.println("Digintolevel:"+(digLevel-i+1)); newURLs=getLevelURLs(i,currentURLs); for(Stringeach:currentURLs){ URLs.add(each); } currentURLs=newURLs; } for(Stringeach:currentURLs){ URLs.add(each); } HashSet hashSet=newHashSet<>(URLs); URLs=newArrayList<>(hashSet); } /** *@parampath保存索引的路径 *@throwsIOException */ publicvoidstoreURLsAndInfo(Stringpath)throwsIOException{ BuildIndexbuild=newBuildIndex(path); /*把URLs中的所有url进行实际网页标题的爬取*/ for(Stringeach:URLs){ Stringtext=getLinkText(each); if(text!=null){ build.addField("url",each); build.addField("text",text); /*将这一个entry加入索引中*/ build.pushIndex(); } } build.close(); } /** *@paramurl需要获取网页标题的url *@return标题内容 *@throwsIOException */ publicStringgetLinkText(Stringurl)throwsIOException{ Documentdocument=null; try{ /*用Jsoup进行连接,设置超时时间为3秒*/ document=Jsoup.connect(url).timeout(3000).get(); }catch(Exceptione){ System.out.println("[TIMEOUT]Gettitleofurl:"+url); returnnull; } Stringtitle=document.title(); returntitle; } /** *@paramurl进行内容解析的url *@return返回该url的网页内容内的所有urls列表 *@throwsIOException */ publicArrayList getBareLinks(Stringurl)throwsIOException{ ArrayList linksList=newArrayList<>(); Documentdocument; try{ document=Jsoup.connect(url).timeout(2000).get(); }catch(Exceptione){ returnlinksList; } /*获取标签理的所有带href属性的标签*/ Elementslinks=document.select("body").select("a[href]"); for(Elementlink:links){ /*从每一个解析得到的标签中提取url,并去除锚点*/ Stringhref=link.attr("abs:href").replaceAll("#",""); /*只添加含有zju.edu.cn字符的url,去除末尾的'/'*/ if(href.contains("zju.edu.cn")){ if(href.endsWith("/")){ href=href.substring(0,href.length()-1); } linksList.add(href); } } HashSet hashSet=newHashSet<>(linksList); ArrayList arrayList=newArrayList<>(hashSet); returnarrayList; } publicstaticvoidmain(String[]args){ Scannerin=newScanner(System.in); System.out.println("Enterurl:"); Stringurl=in.nextLine().trim(); while(!url.startsWith("http://")){ System.out.println("http://isneeded!"); System.out.println("Enterurl:"); url=in.nextLine().trim(); } System.out.println("Enterdepthtodigmoreurls[<=3recommended]:"); intdepth=in.nextInt(); Spiderspider=newSpider(url,depth); System.out.println("Enterpathyouwanttosave[default=d:/index-spider]:"); Stringpath=in.nextLine().trim(); if(path.length()==0){ path="d:/index-spider"; } try{ System.out.println("Startfetching..."); spider.getAll(); System.out.println("Urlsgotsuccess!"); spider.storeURLsAndInfo(path); System.out.println("Storedsuccess!"); }catch(IOExceptione){ e.printStackTrace(); } } }
建立索引:BuildIndex.java
packagewebCrawler.Index; importjava.io.*; importorg.apache.lucene.analysis.Analyzer; importorg.apache.lucene.document.Document; importorg.apache.lucene.document.Field; importorg.apache.lucene.document.TextField; importorg.apache.lucene.index.IndexWriter; importorg.apache.lucene.index.IndexWriterConfig; importorg.apache.lucene.store.Directory; importorg.apache.lucene.store.FSDirectory; importorg.apache.lucene.util.Version; importorg.wltea.analyzer.lucene.IKAnalyzer; /** *@authorlannooo * */ publicclassBuildIndex{ privateFilefile; privateDirectorydirectory; privateIndexWriterindexWriter; privateIndexWriterConfigconfig; privateAnalyzeranalyzer; privateDocumentdocument; /** *@parampath建立索引的路径 */ publicBuildIndex(Stringpath){ try{ file=newFile(path); directory=FSDirectory.open(file); document=newDocument(); analyzer=newIKAnalyzer();/*中文分词工具类*/ config=newIndexWriterConfig(Version.LUCENE_4_10_0,analyzer); indexWriter=newIndexWriter(directory,config); }catch(Exceptione){ e.printStackTrace(); } } /** *@paramfieldName加入到document中的新的一项的名称 *@paramfieldText新的一项的内容 */ publicvoidaddField(StringfieldName,StringfieldText){ try{ Fieldfield=newTextField(fieldName,fieldText,Field.Store.YES); document.add(field); }catch(Exceptione){ e.printStackTrace(); } } /** *将document加入到索引中 */ publicvoidpushIndex(){ try{ indexWriter.addDocument(document); document=newDocument(); }catch(Exceptione){ e.printStackTrace(); } } /** *加入完整的一个document并保存到索引中 *@paramurl加入的url地址 *@paramtexturl对应的文本 */ publicvoidaddOneIndex(Stringurl,Stringtext){ this.addField("url",url); this.addField("text",text); this.pushIndex(); } /** *关闭索引写入 */ publicvoidclose(){ try{ indexWriter.close(); }catch(Exceptione){ e.printStackTrace(); } } }
搜索索引
packagewebCrawler.Index; importjava.io.File; importjava.util.Scanner; importorg.apache.lucene.analysis.Analyzer; importorg.apache.lucene.document.Document; importorg.apache.lucene.index.DirectoryReader; importorg.apache.lucene.queryparser.classic.QueryParser; importorg.apache.lucene.search.IndexSearcher; importorg.apache.lucene.search.Query; importorg.apache.lucene.search.ScoreDoc; importorg.apache.lucene.search.TopDocs; importorg.apache.lucene.store.FSDirectory; importorg.wltea.analyzer.lucene.IKAnalyzer; /** *@authorlannooo * */ publicclassSearchIndex{ privateIndexSearcherindexSearcher; privateAnalyzeranalyzer; privateQueryParserparser; privateQueryquery; privateTopDocshits; privateDirectoryReaderreader; /** *@parampath进行索引搜索的路径 */ publicSearchIndex(Stringpath){ try{ reader=DirectoryReader.open(FSDirectory.open(newFile(path))); indexSearcher=newIndexSearcher(reader); analyzer=newIKAnalyzer(); }catch(Exceptione){ e.printStackTrace(); } } /** *@paramfieldName搜索的域名称 *@paramtext搜索的内容 *@parammatchNumber最大匹配项数 *@return搜索到的最大匹配数 */ publicintsearch(StringfieldName,Stringtext,intmatchNumber){ try{ parser=newQueryParser(fieldName,analyzer); query=parser.parse(text); hits=indexSearcher.search(query,matchNumber); returnhits.totalHits; }catch(Exceptione){ e.printStackTrace(); } return-1; } /** *打印所有的匹配项 */ publicvoidprintHits(){ try{ System.out.println("Totalhitsnumber:"+hits.totalHits); for(ScoreDocdoc:hits.scoreDocs){ Documentdocument=indexSearcher.doc(doc.doc); System.out.println(document.get("url")); System.out.println(document.get("text")); } reader.close(); }catch(Exceptione){ e.printStackTrace(); } } publicstaticvoidmain(String[]args){ /*输入关键词*/ Scannerin=newScanner(System.in); System.out.println("Enterpathoftheindex:"); Stringpath=in.nextLine().trim(); while(path.length()==0){ System.out.println("Enterpathoftheindex:"); path=in.nextLine().trim(); } System.out.println("Entermaxhitnumber:"); intmax=in.nextInt(); while(max<0){ System.out.println("Entermaxhitnumber:"); max=in.nextInt(); } in.nextLine(); System.out.print("Search>>>"); Stringtext=in.nextLine().trim(); /*循环读入用户的关键词,如果是q则退出,长度为0也退出*/ while(!text.equals("q")){ if(text.length()>0){ SearchIndexsearch=newSearchIndex(path); inthits=search.search("text",text,max); if(hits!=-1){ search.printHits(); } } System.out.print("Search>>>"); text=in.nextLine().trim(); } } }
UI界面(这里为了方便只是命令行的形式,可以根据需求写一个GUI界面)
packagewebCrawler.UI; importjava.util.Scanner; importwebCrawler.Index.SearchIndex; /** *@authorlannooo * */ publicclassUI{ publicstaticvoidmain(String[]args){ /*输入关键词*/ Scannerin=newScanner(System.in); System.out.print("Search>>>"); Stringtext=in.nextLine().trim(); /*对于用户的关键词,如果是q则退出,长度为0也退出*/ while(!text.equals("q")&&text.length()>0){ SearchIndexsearch=newSearchIndex("d:/index-spider2"); inthits=search.search("text",text,20); if(hits!=-1){ search.printHits(); } System.out.print("Search>>>"); text=in.nextLine().trim(); } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。