深圳大学考试答题纸(以论文、报告等形式考核专用)二○~二○学年度第学期课程编号1501320002 课程名称搜索引擎技术主讲教师王旭评分学号姓名专业年级题目:利用开源工具构建小型搜索引擎一、项目操作环境及基本操作工具:操作系统:Win10。
基本操作环境:基于Heritrix+ Lucene;java。
基本操作工具:JDK 1.8,MyEclipse Professional 2014,Tomcat 8.0.27,Heritrix 1.14.4,Lucene 2.1.0,— JE-analysis-1.5.3, Htmlparser 1.5。
基本操作工具基本功能介绍:JDK 1.8:JDK(Java SE Development Kit)包括Java开发包和Java开发工具,是一个写Java 的applet和应用程序的程序开发环境。
它由一个处于操作系统层之上的运行环境还有开发者编译,调试和运行用Java语言写的applet和应用程序所需的工具组成。
MyEclipse Professional 2014: Eclipse是一种可扩展的开放源代码IDE。
2001年11月,IBM公司捐出价值4,000万美元的源代码组建了Eclipse联盟,并由该联盟负责这种工具的后续开发。
集成开发环境(IDE)经常将其应用范围限定在“开发、构建和调试”的周期之中。
为了帮助集成开发环境(IDE)克服目前的局限性,业界厂商合作创建了Eclipse平台。
MyEclipse,是在eclipse 基础上加上自己的插件开发而成的功能强大的企业级集成开发环境。
Tomcat 8.0.27:—Tomcat服务器是一个免费的开放源代码的Web 应用服务器,它是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。
—Tomcat 8支持最新的Servlet 3.1 和JSP 2.3 规范。
因为Tomcat技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web应用服务器。
Heritrix 1.14.4:Heritrix是一个开源、可扩展的Web爬虫项目。
Heritrix设计成严格按照robots.txt 文件的排除指示和META robots标签。
Lucene 2.1.0:—Lucene是Apache软件基金会jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。
JE-analysis-1.5.3:是一个免费的Lucene中文分词组件。
Htmlparser 1.5:是一个纯的java写的html解析的库,Htmlparser不依赖于其它的java库,Htmlparser主要用于改造或提取html。
二、该搜索引擎系统的基本构架:先通过爬虫爬取原始网页并进行网页搜集;然后进行网页预处理;接着建立索引indexs;最后进行查询服务。
三、具体搭建和配置过程及问题分析:(1)基本工具的安装:a、JDK1.8的安装:并配置环境变量:JA V A_HOME:C:\Program Files\Java\jdk1.8.0_66JRE_HOME:C:\Program Files\Java\jre1.8.0_66CLASSPATH:%JA V A_HOME%\jre\lib\rt.jar;.;PA TH:%JA V A_HOME%\jre\lib\rt.jar;.;b、MyEclipse的安装:运行.exe文件c、Tomcat的安装:解压安装;设置环境变量:CATALINE_HOME:D:\big work\an zhuang\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放入工程中,右键工程->build path->configure build path->add external jars,将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函数,将该函数内的全部代码注释掉或者直接删除添上return false:f、网页抓取:1、登录Heritrix:运行Tomcat后登录http://localhost:8080(或者http://127.0.0.1:8080)2、Heritrix的控制台如下:3、设置seed:设置为四川大学的URLSelect Crawl Scope选择org.archive.crawler.scope.BroadScope:抓取网页后会生成镜像文件便于查看:Select Post Processors第三项修改为org.archive.crawler.postprocessor.FrontierSchedulerForScu其他设置如图:5、参数设置:—点击Settings ,这里只需要修改user-agent 和from :@VERSION@表示版本,后面的URL 输入/。
Email 也同样是输入一个有效的email 。
—设置好之后,点击Submit Job ,返回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-20151223130135337files.path是将网页文件解析后存放的文件地址;Index.path是网页解析文件建立得到的索引的存放地址。
d、添加文件Extractor.java代码如下:package .szu.search.extractor;import org.htmlparser.*;import org.htmlparser.util.*;import org.htmlparser.visitors.*;import org.htmlparser.nodes.*;import org.htmlparser.tags.*;import .szu.search.page.*;import .szu.search.util.*;public class Extractor implements Runnable{private String filename;private Parser parser;private Page page;private String encode;public void setEncode(String encode) {this.encode = encode;}private String combineNodeText(Node[] nodes) {StringBuffer buffer = new StringBuffer();for (int i = 0; i < nodes.length; i++) {Node anode = (Node)nodes[i];String line = null;if (anode instanceof TextNode) {TextNode textnode = (TextNode)anode;line = textnode.getText();}else if (anode instanceof LinkTag) {LinkTag linknode = (LinkTag)anode;line = linknode.getLinkText();}else if (anode instanceof Div) {if (anode.getChildren() != null) {line = combineNodeText(anode.getChildren().toNodeArray());}}else if (anode instanceof ParagraphTag) {if (anode.getChildren() != null) {line = combineNodeText(anode.getChildren().toNodeArray());}}else if (anode instanceof Span) {if (anode.getChildren() != null) {line = combineNodeText(anode.getChildren().toNodeArray());}}else if (anode instanceof TableTag) {if (anode.getChildren() != null) {line = combineNodeText(anode.getChildren().toNodeArray());}}else if (anode instanceof TableRow) {if (anode.getChildren() != null) {line = combineNodeText(anode.getChildren().toNodeArray());}}else if (anode instanceof TableColumn) {if (anode.getChildren() != null) {line = combineNodeText(anode.getChildren().toNodeArray());}}if (line != null) {buffer.append(line);}}return buffer.toString();}private String getUrl (String filename) {String url = filename;url = url.replace(ProperConfig.getValue("mirror.path")+"/mirror", "");if (stIndexOf("/") == url.length()-1) {url = url.substring(0,url.length()-1);}url = url.substring(1);return url;}private int getScore(String url, int score) {String[] subStr = url.split("/");score = score - (subStr.length-1);return score;}private String getSummary(String context) {if (context == null) {context = "";}return MD5.MD5Encode(context);}public void extract(String filename) {System.out.println("Message: Now extracting " + filename);this.filename = filename.replace("\\", "/");run();if (this.page != null) {PageLib.store(this.page);}}@Overridepublic void run() {// TODO Auto-generated method stubtry {parser = new Parser(this.filename);parser.setEncoding(encode);HtmlPage visitor = new HtmlPage(parser);parser.visitAllNodesWith(visitor);page = new Page();// get page's URLSystem.out.println(this.filename);System.out.println(getUrl(this.filename));this.page.setUrl(getUrl(this.filename));System.out.println(this.page.getUrl());// get page's titleString textInPage = visitor.getTitle();System.out.println(textInPage);this.page.setTitle(textInPage);// testing <body> is null or not, if null, un-extractingif (visitor.getBody() == null) {this.page.setContext(null);}else {// if have value, extractingthis.page.setContext(combineNodeText(visitor.getBody().toNodeArray()));}// count page's scorethis.page.setScore(getScore(this.page.getUrl(), this.page.getScore()));// count page's summarythis.page.setSummary(getSummary(this.page.getContext()));}catch (ParserException pe) {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的导入方法,导入成功后,再新建一个包,命名为.scu.search.index。