利用开源工具构建小型搜索引擎项目报告..doc
《利用开源工具构建小型搜索引擎项目报告..doc》由会员分享,可在线阅读,更多相关《利用开源工具构建小型搜索引擎项目报告..doc(22页珍藏版)》请在冰点文库上搜索。
深圳大学考试答题纸
(以论文、报告等形式考核专用)
二○~二○学年度第学期
课程编号
1501320002
课程名称
搜索引擎技术
主讲教师
王旭
评分
学号
姓名
专业年级
教师评语:
题目:
利用开源工具构建小型搜索引擎
一、项目操作环境及基本操作工具:
操作系统:
Win10。
基本操作环境:
基于Heritrix+Lucene;java。
基本操作工具:
JDK1.8,MyEclipseProfessional2014,Tomcat8.0.27,Heritrix1.14.4,Lucene2.1.0, JE-analysis-1.5.3,Htmlparser1.5。
基本操作工具基本功能介绍:
JDK1.8:
JDK(JavaSEDevelopmentKit)包括Java开发包和Java开发工具,是一个写Java 的applet和应用程序的程序开发环境。
它由一个处于操作系统层之上的运行环境还有 开发者编译,调试和运行用Java语言写的applet和应用程序所需的工具组成。
MyEclipseProfessional2014:
Eclipse是一种可扩展的开放源代码IDE。
2001年11月,IBM公 司捐出价值4,000万美元的源代码组建了Eclipse联盟,并由该联盟负责这种工具的后 续开发。
集成开发环境(IDE)经常将其应用范围限定在“开发、构建和调试”的周期 之中。
为了帮助集成开发环境(IDE)克服目前的局限性,业界厂商合作创建了Eclipse 平台。
MyEclipse,是在eclipse 基础上加上自己的插件开发而成的功能强大的企业级集 成开发环境。
Tomcat8.0.27:
Tomcat服务器是一个免费的开放源代码的Web应用服务器,它是Apache软件 基金会(ApacheSoftwareFoundation)的Jakarta项目中的一个核心项目,由Apache、 Sun和其他一些公司及个人共同开发而成。
Tomcat8支持最新的Servlet3.1和JSP2.3 规范。
因为Tomcat技术先进、性能稳定,而且免费,因而深受Java爱好者的喜爱并 得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。
Heritrix1.14.4:
Heritrix是一个开源、可扩展的Web爬虫项目。
Heritrix设计成严格按照robots.txt 文件的排除指示和METArobots标签。
Lucene2.1.0:
Lucene是Apache软件基金会jakarta项目组的一个子项目,是一个开放源代码的 全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的 架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方 语言)。
JE-analysis-1.5.3:
是一个免费的Lucene中文分词组件。
Htmlparser1.5:
是一个纯的java写的html解析的库,Htmlparser不依赖于其它的java库, Htmlparser主要用于改造或提取html。
二、该搜索引擎系统的基本构架:
先通过爬虫爬取原始网页并进行网页搜集;然后进行网页预处理;接着建立索引indexs;最后 进行查询服务。
三、具体搭建和配置过程及问题分析:
(1)基本工具的安装:
a、JDK1.8的安装:
并配置环境变量:
JAVA_HOME:
C:
\ProgramFiles\Java\jdk1.8.0_66
JRE_HOME:
C:
\ProgramFiles\Java\jre1.8.0_66
CLASSPATH:
%JAVA_HOME%\jre\lib\rt.jar;.;
PATH:
%JAVA_HOME%\jre\lib\rt.jar;.;
b、MyEclipse的安装:
运行.exe文件
c、Tomcat的安装:
解压安装;
设置环境变量:
CATALINE_HOME:
D:
\bigwork\anzhuang\apache-tomcat-8.0.30;
设置好之后,测试一下Tomcat。
打开Bin文件夹,运行startup.bat;
打开浏览器,输入http:
//localhost:
8080(或者http:
//127.0.0.1:
8080),如果看到下图所示的界面, 表明Tomcat运行正常:
d、其他工具解压即可。
(2)Heritrix工程的建立:
a、解压Heritrix-1.14.4和Heritrix-1.14.4-src文件,
b、新建项目工程Heritrix:
c、配置该工程:
1、将Heritrix-1.14.4和Heritrix-1.14.4-src文件从上述网站中下载。
2、将文件中的lib放入工程中,右键工程->buildpath->configurebuildpath->addexternaljars, 将lib中所有jar包添加到library中。
3、将文件中src\java\的org和st两个文件夹放到工程文件的src目录下。
4、将src\conf\下的所有文件及其文件夹拖至工程文件下,修改heritrix.properties中的 heritrix.version=1.14.4;heritrix.cmdline.admin=admin:
admin,这是分别是版本号和登录所 需要的用户(左)和密码(右)。
5、将src下除了conf和java以外的所有文件夹,拖至工程文件目录下。
6、运行run,成功时会显示版本:
7、创建好的Heritrix目录结构如下:
d、网页搜集:
1、扩展Heritrix:
新建一个类,叫FrontierSchedulerForScu,派生于org.archive.crawler.postprocessor. FrontierScheduler,它的代码如下:
屏蔽zip、rar、exe文件,只抓取网页,并且抓取的网页中必须包含scu(即四川大学)
打开文件conf\modules\Processor.options
添加新建的module选项:
org.archive.crawler.postprocessor.FrontierSchedulerForSzu|FrontierSchedulerForScu:
取消robots.txt的限制:
找到org.archive.crawler.prefetch中的PreconditionEnforcer类:
找到considerRobotsPreconditions函数,将该函数内的全部代码注释掉或者直接删除
添上returnfalse:
f、网页抓取:
1、登录Heritrix:
运行Tomcat后登录http:
//localhost:
8080(或者http:
//127.0.0.1:
8080)
2、Heritrix的控制台如下:
3、设置seed:
设置为四川大学的URL
4、点击Modules:
设置各个处理模块:
SelectCrawlScope选择org.archive.crawler.scope.BroadScope:
SelectWriters选择org.archive.crawler.writer.MirrorWriterProcessor并将另一个移除:
然后
抓取网页后会生成镜像文件便于查看:
SelectPostProcessors第三项修改为org.archive.crawler.postprocessor.FrontierSchedulerForScu
其他设置如图:
5、参数设置:
点击Settings,这里只需要修改user-agent和from:
@VERSION@表示版本,后面的URL
输入
设置好之后,点击SubmitJob,返回Console界面,刷新一下(start和refresh),就开始运 行:
如图可得到一下的进度条:
左边表示已经下载了得数目,右边表示在队列中等待下载的数目。
6、最终抓取的到的结果在工作区间的Heritrix下的jobs文件夹中:
共抓取约13万个文件。
(3)进行网页预处理:
a、添加htmlparser解析网页:
将下载的htmlparser相关的压缩包解压,找到htmlparser.jar文件,将至导入library中。
b、添加解析网页文件:
Page.java:
代码如下:
c、对Config.properties进行配置:
mirror.path是得到的网页文件的地址:
D:
\bigwork\Heritrix_Lucene-20151208\Heritrix-1.14.4\jobs\
sichuan-university-20151223130135337
files.path是将网页文件解析后存放的文件地址;
Index.path是网页解析文件建立得到的索引的存放地址。
d、添加文件Extractor.java
代码如下:
packagecn.edu.szu.search.extractor;
importorg.htmlparser.*;
importorg.htmlparser.util.*;
importorg.htmlparser.visitors.*;
importorg.htmlparser.nodes.*;
importorg.htmlparser.tags.*;
importcn.edu.szu.search.page.*;
importcn.edu.szu.search.util.*;
publicclassExtractorimplementsRunnable{
privateStringfilename;
privateParserparser;
privatePagepage;
privateStringencode;
publicvoidsetEncode(Stringencode){
this.encode=encode;
}
privateStringcombineNodeText(Node[]nodes){
StringBufferbuffer=newStringBuffer();
for(inti=0;i Nodeanode=(Node)nodes[i];
Stringline=null;
if(anodeinstanceofTextNode){
TextNodetextnode=(TextNode)anode;
line=textnode.getText();
}
elseif(anodeinstanceofLinkTag){
LinkTaglinknode=(LinkTag)anode;
line=linknode.getLinkText();
}
elseif(anodeinstanceofDiv){
if(anode.getChildren()!
=null){
line=combineNodeText(anode.getChildren().toNodeArray());
}
}
elseif(anodeinstanceofParagraphTag){
if(anode.getChildren()!
=null){
line=combineNodeText(anode.getChildren().toNodeArray());
}
}
elseif(anodeinstanceofSpan){
if(anode.getChildren()!
=null){
line=combineNodeText(anode.getChildren().toNodeArray());
}
}
elseif(anodeinstanceofTableTag){
if(anode.getChildren()!
=null){
line=combineNodeText(anode.getChildren().toNodeArray());
}
}
elseif(anodeinstanceofTableRow){
if(anode.getChildren()!
=null){
line=combineNodeText(anode.getChildren().toNodeArray());
}
}
elseif(anodeinstanceofTableColumn){
if(anode.getChildren()!
=null){
line=combineNodeText(anode.getChildren().toNodeArray());
}
}
if(line!
=null){
buffer.append(line);
}
}
returnbuffer.toString();
}
privateStringgetUrl(Stringfilename){
Stringurl=filename;
url=url.replace(ProperConfig.getValue("mirror.path")+"/mirror","");
if(url.lastIndexOf("/")==url.length()-1){
url=url.substring(0,url.length()-1);
}
url=url.substring
(1);
returnurl;
}
privateintgetScore(Stringurl,intscore){
String[]subStr=url.split("/");
score=score-(subStr.length-1);
returnscore;
}
privateStringgetSummary(Stringcontext){
if(context==null){
context="";
}
returnMD5.MD5Encode(context);
}
publicvoidextract(Stringfilename){
System.out.println("Message:
Nowextracting"+filename);
this.filename=filename.replace("\\","/");
run();
if(this.page!
=null){
PageLib.store(this.page);
}
}
@Override
publicvoidrun(){
//TODOAuto-generatedmethodstub
try{
parser=newParser(this.filename);
parser.setEncoding(encode);
HtmlPagevisitor=newHtmlPage(parser);
parser.visitAllNodesWith(visitor);
page=newPage();
//getpage'sURL
System.out.println(this.filename);
System.out.println(getUrl(this.filename));
this.page.setUrl(getUrl(this.filename));
System.out.println(this.page.getUrl());
//getpage'stitle
StringtextInPage=visitor.getTitle();
System.out.println(textInPage);
this.page.setTitle(textInPage);
//testing
isnullornot,ifnull,un-extracting
if(visitor.getBody()==null){
this.page.setContext(null);
}
else{
//ifhavevalue,extracting
this.page.setContext(combineNodeText(visitor.getBody().toNodeArray()));
}
//countpage'sscore
this.page.setScore(getScore(this.page.getUrl(),this.page.getScore()));
//countpage'ssummary
this.page.setSummary(getSummary(this.page.getContext()));
}catch(ParserExceptionpe){
this.page=null;
pe.printStackTrace();
System.out.println("Continue...");
}
}
}
e、PageLib.java文件:
f、ProperConfig.java文件,代码如下:
g、MD5.java文件,代码如下:
h、TestExtractor.java测试类文件:
(4)建立索引:
1、将lucene的jar包和je分词的jar包导入到Project当中,导入方法同前边章节所示的htmlparser
的导入方法,导入成功后,再新建一个包,命名为cn.edu.scu.search.index。
2、添加一个新的类,叫作IndexBuilder。
packagecn.edu.szu.search.index;
importorg.apache.lucene.document.*;
importorg.apache.lucene.index.*;
importjeasy.analysis.*;
importjava.io.IOException;
importjava.io.FileReader;
importjava.io.BufferedReader;
importjava.io.File;
//createindexclass
publicclassIndexBuilder{
IndexWriterwriter;
publicIndexBuilder(Stringpath)throwsIOException{
writer=newIndexWriter(path,newMMAnalyzer());
}
publicvoidbuild(Stringpath)throwsIOException{
BufferedReaderreader=null;
File[]files=newFile(path).listFiles();
for(inti=0;i System.out.println(".");
reader=newBufferedReader(newFileReader(files[i]));
Documentdoc=newDocument();
Field[]fields=newField[5];
fields[0]=newField("id",String.valueOf(i),Field.Store.YES,Field.Index.NO);
fields[1]=newField("url",reader.readLine(),Field.Store.YES,Field.Index.NO);
fields[2]=newField("title",reader.readLine(),Field.Store.YES,Field.Index.TOKENIZED);
fields[3]=newField("score",reader.readLine(),Field.Store.YES,Field.Index.NO);
fields[4]=newField("context",getBodyFile(files[i].getAbsolutePath(),reader), Field.Store.YES,Field.Index.TOKENIZED);
//createDocument
for(intj=0;j doc.add(fields[j]);
}
//writ