1、引言面对浩瀚的网络资源,搜索引擎为所有网上冲浪的用户提供了一个入口,毫不夸张的说,所有的用户都可以从搜索出发到达自己想去的网上任何一个地方。因此它也成为除了电子邮件以外最多人使用的网上服务。搜索引擎技术伴随着WWW的发展是引人注目的。搜索引擎大约经历了三代的更新发展:第一代搜索引擎出现于1994 年前后。以Altavista, Yahoo 和Infoseek为代表,注重反馈结果的数量,主要特征是“求全”。它主要依靠人工分拣的分类目录搜索,通常由网页制作人自行建立网站名称、网站内容的文字摘要,并将其加入到搜索引擎的资料库中。搜索引擎根据用户键入的信息,根据预先设定的规则进行简单的匹配、排序和显示
2、。这种方法只能进行简单的字符串匹配,无法进行全文搜索。研究表明,搜索引擎性能并没有想象中的那么优秀,在全球11 个主要的搜索引擎中,搜索引擎仅能搜索到国际互联网上全部页面的16%,甚至更低,造成这种情况的原因,主要是这些搜索引擎没有及时更新资料。第二代搜索引擎,利用超链接分析为基础的机器抓取技术,由搜索引擎使用一个程序在网络上撷取资料,并自动将得到的结果存入索引库中。搜索引擎根据用户键入的信息进行匹配、排序和显示。这些引擎的主要特点是提高了查准率,可以用“求精”来描述它的优点,即不需要网站制作人单独键入供搜索的信息,并且从理论上讲,可将任意网站的所有网页加入到它的资料库中。第二代搜索引擎的大多
3、数查询都会返回成千上万条信息,查询结果中无关信息太多,而且查询结果显示比较混乱,使用者仍然难以找到真正想要的资料。第三代搜索引擎是对第二代搜索引擎的改进,相对于前两代,其更注重智能化和用户使用的个性化,主要增加了互动性和个性化等高级的技术,采用了中文自动分类、自动聚类等人工智能技术,而且使用了中文内容分析技术以及区域智能识别技术,增强了搜索引擎的查询能力。同时,搜索技术将更加智能化,可搜索资源将更加广泛,搜索方式也将更加便捷有效,为用户使用搜索引擎获取信息获得更好的体验。在美国搜索引擎通常指的是基于因特网的搜索引擎,他们通过网络机器人程序收集上千万到几亿个网页,并且每一个词都被搜索引擎索引,也
4、就是我们说的全文检索。著名的因特网搜索引擎包括First Search、Google、HotBot百度 AOL等。目录第1章 项目分析51.1项目背景51.2项目目标5第2章 系统分析与设计62.1系统的需求分析62.1.1功能需求62.1.2系统功能模块62.2系统分析62.2.1参与者62.2.2用例72.3系统设计72.3.1顺序图72.3.2活动图82.3.3类图82.4 数据存储设计82.5 界面设计82.5.1界面设计原则82.5.2系统主页设计9第3章 系统的实现103.1更新数据103.2更新索引103.3用户输入搜索113.4用户访问互联网获取11第4章 搜索引擎结构分析12
5、4.1系统概述12第5章系统的测试175.1 测试计划175.1 代码测试18第6章 结束语19第7章 参考文献207.1 文献资料207.1 开发工具、平台及资源:20第8章 测试代码:218.1 爬取部分测试代码:218.2 索引部分测试代码:24第9章 附录源代码:269.1 爬取存取代码:269.2建立索引代码:329.3实现搜索代码:349.4GUI界面代码36第1章 项目分析本章包括问题描述,问题的可行性,技术分析及工程进度计划。问题描述告诉我们项目是做什么的,利用的哪方面的知识。通过技术分析,我们更加明确项目是否可行。而工程进度计划,则将指导项目开发的开发过程,保证项目按时完成。
6、1.1项目背景搜索引擎是指根据一定的策略、运用特定的计算机程序从互联网上搜集信息,在对信息进行组织和处理后,为用户提供检索服务,将用户检索相关的信息展示给用户的系统。搜索引擎包括全文索引、目录索引、元搜索引擎、垂直搜索引擎、集合式搜索引擎、门户搜索引擎与免费链接列表等。百度和谷歌等是搜索引擎的代表搜索引擎的发生背景在因特网发展初期,网站相对较少,闻查找比较容易。然而随着新闻技术的飞速发展,特别是因特网应用的迅速普及,网站越来越多,并且每天全球互联网。网页数目以千万级的数量增加。要在浩瀚的网络新闻中寻找所需要的材料无异于大海捞针这时为满足人人新闻检索需求的搜索网站应运而生。1.2项目目标本搜索引
7、擎,根据新浪首页进行抓取信息。我们成员根据在网上用户对信息的搜索发现,用户想要获得一个信息,就要输入自己查询的内容,结果出来的都是与之相关的内容,本搜索引擎,考虑到用户可能获取和该信息有关URL,并且进行一一列出,方便用户对信息的更为全面的获取。我们根据搜索内容简历索引,以简单的搜索页面给用户,按照一定的顺序输出给用户,尽可能的满足用户的需求。第2章 系统分析与设计2.1系统的需求分析2.1.1功能需求搜索引擎大家都知道,像百度、谷歌一样,为此我们根据系统可知我们的角色就一个。用户:搜索自己想要的信息2.1.2系统功能模块根据系统功能,该系统有该需求功能用户:通过搜索框,搜索到与之相关的信息,
8、通过互联网进行访问2.2系统分析在问题描述的基础上,根据工程分析的方法,进一步对所做的项目进行分析。2.2.1参与者参与者是与系统交互的的人或者物,可以包括人、外部系统和其他机构,位于系统外,不属于系统,通常情况下,根据下面问题来确定参与者:哪些人是你的系统的主要客户?哪些人从你的系统获取信息?哪些人为你的系统提供信息?哪些系统与该系统进行交互?在某个预定的时间是否有事情自动发生?同时参与者的名字应该能准确反映在模型中扮演的角色。使用搜索引擎系统的参与者:用户2.2.2用例用例为参与者提供价值,每个用例表示系统提供的一项服务。2.3系统设计根据系统分析,进一步深入,具体规划项目每一步如何设计。
9、书写成文档形式,有利于项目开发、测试及后期的维护工作。2.3.1顺序图2.3.2活动图2.3.3类图本系统一共有5个类,分别是:Spider,CreateIndex,Searcher,LinkLabel,SearchFrameSpider类:抓取信息CreateIndex类:建立索引Searcher类:实现搜索LinkLabel、SearchFrame类:GUI界面搜索输出2.4 数据存储设计由于数据内容过于大,本系统采取,通过在本地磁盘建立文件夹,进行存储建立一个索引的文件夹,进行存储索引2.5 界面设计2.5.1界面设计原则需求名称详细要求界面风格1:要求界面风格统一、简洁、色调淡雅2:界
10、面美观大方,java风格3:要求结构严谨;操作方便能够明确的标明操作的界面、多使用文字提示,以方便非计算机人员的使用。界面友好要求能方便的输入、输出数据,减少非法数据的输入,有固定分类的地方采用选择方式替代手工录入,减少出错率。2.5.2系统主页设计一个良好的查询界面非常重要,例如Googl百度 就以她简洁的查询界面而闻名。我在设计的时候也充分考虑了实用性和简洁性。第3章 系统的实现3.1更新数据本系统设置抓取上限20013.2更新索引3.3用户输入搜索3.4用户访问互联网获取第4章 搜索引擎结构分析4.1系统概述 搜索引擎是根据用户的查询请求,按照一定算法从索引数据中查找信息返回给用户。为了
11、保证用户查找信息的精度和新鲜度,搜索引擎需要建立并维护一个庞大的索引数据库。一般的搜索引擎由网络机器人程序、索引与搜索程序、索引数据库等部分组成4.2搜索引擎的构成4.2.1网络机器人 网络机器人也称为“网络蜘蛛”(Spider),也就是我们通常说的webCollector(网络爬虫),是一个功能很强的WEB扫描程序。它可以在扫描WEB页面的同时检索其内的超链接并加入扫描队列等待以后扫描。因为WEB中广泛使用超链接,所以一个Spider程序理论上可以访问整个WEB页面。 为了保证网络机器人遍历信息的广度和深度需要设定一些重要的链接并制定相关的扫描策略。Internet是建立在很多相关协议基础上
12、的,而更复杂的协议又建立在系统层协议之上。Web就是建立在HTTP ( Hypertext Transfer Protocol ) 协议基础上,而HTTP又是建立在TCP/IP ( Transmission Control Protocol / Internet Protocol ) 协议之上,它同时也是一种Socket协议。所以网络机器人本质上是一种基于Socket的网络程序。把URL加入等待队列Spider程序工作完成等待队列中是否有URL?否下载从等待队列中得到的网页,并将他送入运行队列中。是这个网页包含其他超级连接吗?将这一网页送入完成队列并继续查看网页上的下一个超连接是否为指向Web
13、的连接?报告其他类型连接连接是否与网页所在主机不同且只处理本地连接?报告外部连接报告网页连接将连接加入等候队列否是否是否是4.2.2索引与搜索 网络机器人将遍历得到的页面存放在临时数据库中,如果通过SQL直接查询信息速度将会难以忍受。为了提高检索效率,需要建立索引,按照倒排文件的格式存放。如果索引不及时跟新的话,用户用搜索引擎也不能检索到。用户输入搜索条件后搜索程序将通过索引数据库进行检索然后把符合查询要求的数据库按照一定的策略进行分级排列并且返回给用户。4.2.3 Web服务器 客户一般通过浏览器进行查询,这就需要系统提供Web服务器并且与索引数据库进行连接。客户在浏览器中输入查询条件,We
14、b服务器接收到客户的查询条件后在索引数据库中进行查询、排列然后返回给客户端。4.3如何解析HTML因为Web中的信息都是建立在HTML协议之上的,所以网络机器人在检索网页时的第一个问题就是如何解析HTML。在解决如何解析之前,先来介绍下HTML中的几种数据。文本:除了脚本和标签之外的所有数据 注释:程序员留下的说明文字,对用户是不可见的 简单标签:由单个表示的HTML标签 开始标签和结束标签:用来控制所包含的HTML代码我们在进行解析的时候不用关心所有的标签,只需要对其中几种重要的进行解析即可。超连接标签:超连接定义了WWW通过Internet链接文档的功能。他们的主要目的是使用户能够任意迁移
15、到新的页面,这正是网络机器人最关心的标签。图像映射标签:图像映射是另一种非常重要的标签。它可以让用户通过点击图片来迁移到新的页面中。表单标签:表单是Web页面中可以输入数据的单元。许多站点让用户填写数据然后通过点击按钮来提交内容,这就是表单的典型应用。表格标签:表格是HTML的构成部分,通常用来格式化存放、显示数据。4.4基于lucene的索引与搜索4.4.1什么是Lucene全文检索Lucene是Jakarta Apache的开源项目。它是一个用Java写的全文索引引擎工具包,可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能。4.4.2 Lucene的原理分析全文检索的实现机制Lu
16、cene的API接口设计的比较通用,输入输出结构都很像数据库的表=记录=字段,所以很多传统的应用的文件、数据库等都可以比较方便的映射到Lucene的存储结构和接口中。总体上看:可以先把Lucene当成一个支持全文索引的数据库系统。索引数据源:doc(field1,field2.) doc(field1,field2.) indexer / _ | Lucene Index| - searcher 结果输出:Hits(doc(field1,field2) doc(field1.) Document:一个需要进行索引的“单元”,一个Document由多个字段组成Field:字段Hits:查询结果集
17、,由匹配的Document组成4.5庖丁解牛中文分词技术4.5.1 pao-ding结合LuceneLucene中对中文的处理是基于自动切分的单字切分,或者二元切分除此之外,还有最大切分(包括向前、向后、以及前后相结合)、最少切分、全切分等等。庖丁中文分词库是一个使用Java开发的,可结合到Lucene应用中的,为互联网、企业内部网使用的中文搜索引擎分词组件。Paoding填补了国内中文分词方面开源组件的空白,致力于此并希翼成为互联网网站首选的中文分词开源组件。Paoding中文分词追求分词的高效率和用户良好体验。PaodingsKnives中文分词具有极高效率和高扩展性。引入隐喻,采用完全的
18、面向对象设计,构思先进。高效率:在PIII1G内存个人机器上,1秒可准确分词100万汉字。采用基于不限制个数的词典文件对文章进行有效切分,使能够将对词汇分类定义,能够对未知的词汇进行合理解析。4.5.2 pao-ding 的配置导入dic字典文件夹4.5线程调度和正则表达式通过分时系统,对线程进行上锁,按照优先级进行处理。分时调度模型是指让所有的线程轮流获得cpu的使用权,并且平均分配每个线程占用的CPU的时间片这个也比较好理解。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。4.6 数据结构通过数据
19、结构中的广度优先搜索算法1、从图中某个顶点V0出发,并访问此顶点;2、从V0出发,访问V0的各个未曾访问的邻接点W1,W2,,Wk;然后,依次从W1,W2,Wk出发访问各自未被访问的邻接点;3、重复步骤2,直到全部顶点都被访问为止。第5章系统的测试5.1 测试计划本系统的测试要完成系统测试阶段的功能测试、界面测试。对测试对象的功能测试应侧重于所有可直接追踪到业务功能和业务规则的测试需求。对此类测试基于黑盒技术,该技术通过图形界面(GUI)与应用程序进行交互,并对交互的输出或结果进行分析,以此来核实应用程序及其内部进程。功能测试和界面测试如下所示。功能测试:测试目标确保测试的功能正常,其中包括导
20、航、数据输入、处理和检索等功能测试范围产品规格说明书中要求的各项功能技术利用有效的和无效的数据来执行各个测试用例,以核实以下内容在使用有效数据时得到预期的结果在使用无效数据时显示相应的错误信息或警告信息各业务规则都得到了正确的应用开始标准完成标准测试重点和优先级需考虑的特殊事项确定或说明那些将对功能测试的实施和执行造成影响的事项或因素。界面测试:测试目标浏览所有页面,包括所有窗口的所有控件,各种访问方法(Tab键、鼠标移动和快捷键)的使用测试范围所有页面技术核实所有页面都可正确地进行浏览,并处于正常的对象状态开始标准完成标准成功地核实出各个窗口都与基准版本保持一致,或符合可接受标准测试重点和优
21、先级需考虑的特殊事项测试进度:测试活动计划开始日期实际开始日期结束日期制定测试计划2012-12-242012-12-242012-12-24编写测试用例2012-12-252012-12-252012-12-25执行测试用例2012-12-252012-12-252012-12-25管理缺陷、编写测试总结报告2012-12-252012-12-252012-12-255.1 代码测试建立爬取部分代码测试结果:var _trace_page_logid = 1137706623;建立索引部分代码测试结果: 第6章 结束语对于这次搜索引擎的设计和实现,在分析和设计以及对于搜索引擎方面的知识有了很
22、大的了解,首先介绍了网络机器人的基本概念,然后具体分析了Spider程序的结构和功能。在最后还结合具体代码进行了详细说明。在进行海量数据搜索时,如果使用单纯的数据库技术,那将是非常痛苦的。速度将是极大的瓶颈。所以提出了使用全文搜索引擎Lucene进行索引、搜索。还结合了具体代码说明了如何把Lucene全文搜索引擎和Spider程序互相集合来实现搜索的功能。通过此次课程设计,使我更加扎实的掌握了有关软件工程方面的知识,在设计过程中虽然遇到了一些问题,但经过一次又一次的思考,一遍又一遍的检查终于找出了原因所在,也暴露出了前期我在这方面的知识欠缺和经验不足。实践出真知,通过亲自动手制作,使我们掌握的
23、知识不再是纸上谈兵。过而能改,善莫大焉。在课程设计过程中,我们不断发现错误,不断改正,不断领悟,不断获取。最终的检测调试环节,本身就是在践行“过而能改,善莫大焉”的知行观。这次课程设计终于顺利完成了,在设计中遇到了很多问题,最后在老师的指导下,终于游逆而解。在今后社会的发展和学习实践过程中,一定要不懈努力,不能遇到问题就想到要退缩,一定要不厌其烦的发现问题所在,然后一一进行解决,只有这样,才能成功的做成想做的事,才能在今后的道路上劈荆斩棘而不是知难而退,那样永远不可能收获成功,收获喜悦,也永远不可能得到社会及他人对你的认可!回顾起此课程设计,至今我仍感慨颇多,从理论到实践,在这段日子里,可以说
24、得是苦多于甜,但是可以学到很多很多的东西,同时不仅可以巩固了以前所学过的知识,而且学到了很多在书本上所没有学到过的知识。通过这次课程设计使我懂得了理论与实际相结合是很重要的,只有理论知识是远远不够的,只有把所学的理论知识与实践相结合起来,从理论中得出结论,才能真正为社会服务,从而提高自己的实际动手能力和独立思考的能力。在设计的过程中遇到问题,可以说得是困难重重,但可喜的是最终都得到了解决。实验过程中,也对团队精神的进行了考察,让我们在合作起来更加默契,在成功后一起体会喜悦的心情。果然是团结就是力量,只有互相之间默契融洽的配合才能换来最终完美的结果。第7章 参考文献7.1 文献资料实用软件工程教
25、程 高等教育出版社深层网络爬虫研究综述 计算机系统应用面向对象与设计 机械工业出版社java程序设计 清华大学出版社java核心技术 卷一 机械工业出版社基于Java的全文搜索引擎 电子工业出版社JAVA编程思想 机械工业出版社数据结构 百度文库7.1 开发工具、平台及资源:网络接口: Myeclipse 2014Sun JDK 1.4.1paoding-analysis-2.0.4-betaLuceneHTMLParser-2.0-SNAPSHOT第8章 测试代码:8.1 爬取部分测试代码:package PaQu;import java.io.*;import .HttpURLConnec
26、tion;import .MalformedURLException;import .URL;import org.htmlparser.Node;import org.htmlparser.NodeFilter;import org.htmlparser.Parser;import org.htmlparser.Tag;import org.htmlparser.filters.HasParentFilter;import org.htmlparser.filters.NodeClassFilter;import org.htmlparser.filters.OrFilter;import
27、org.htmlparser.filters.TagNameFilter;import org.htmlparser.nodes.TextNode;import org.htmlparser.tags.*;import org.htmlparser.util.NodeList;import org.htmlparser.util.ParserException;import org.htmlparser.util.ParserUtils;import org.htmlparser.util.SimpleNodeIterator;import org.htmlparser.visitors.Te
28、xtExtractingVisitor;/!仅供测试public class Test private static String ENCODE = GBK;static Parser parser;private static void message(String szMsg) try System.out.println(szMsg); catch (Exception e) public static String openFile(String szFileName) try BufferedReader bis = new BufferedReader(new InputStrea
29、mReader(new FileInputStream(new File(szFileName), ENCODE);String szContent = ;String szTemp;while (szTemp = bis.readLine() != null) szContent += szTemp + n;bis.close();return szContent; catch (Exception e) return ;public static String htmlInit(String htmlStr) NodeFilter scriptFilter = new NodeClassF
30、ilter(ScriptTag.class);NodeFilter styleFilter = new NodeClassFilter(StyleTag.class);NodeFilter filter = scriptFilter, styleFilter ;OrFilter orFilter = new OrFilter(filter);try htmlStr = ParserUtils.trimTags(htmlStr, orFilter, true, true); catch (Exception e) e.printStackTrace();return htmlStr;public
31、 String getTopicBlock() HasParentFilter acceptedFilter = new HasParentFilter(new TagNameFilter(p);NodeList nodes = null;try nodes = parser.extractAllNodesThatMatch(acceptedFilter); catch (ParserException e) System.err.println(getTopicBlock + e);StringBuffer sb = new StringBuffer();SimpleNodeIterator
32、 iter = nodes.elements();while (iter.hasMoreNodes() Node node = iter.nextNode();sb.append(node.getText() + n);parser.reset();return sb.toString();public static void main(String args) String szContent = openFile(E:/baizeju.html);URL url = null;try url = new URL( catch (MalformedURLException e1) / TOD
33、O Auto-generated catch blocke1.printStackTrace();String s = filterScriptAndStyle(url);System.out.println(s);/* * 过滤掉html中的脚本信息 * param html * return */protected static String filterScriptAndStyle(URL url)tryStringBuilder text = new StringBuilder();Parser parser = new Parser(HttpURLConnection) (url).
34、openConnection();/遍历所有的节点NodeList nodes;nodes = parser.parse(null);for(int i=0;inodes.size();i+)Node node = nodes.elementAt(i);if( (node instanceof ScriptTag)text.append(node.toPlainTextString();return text.toString();catch(Exception e)e.printStackTrace();return url.toString();/* * 脚本过滤器 * author os
35、china */class ScriptFilter implements NodeFilter public boolean accept(Node node) if(node = null)return false;if(node instanceof Tag)String tag = (Tag)node).getTagName();if(iframe.equalsIgnoreCase(tag)return false;if(node instanceof StyleTag)return false;if(node instanceof ScriptTag)return false;if(
36、node instanceof FrameTag)return false;return true;8.2 索引部分测试代码:package index;import java.io.*;import org.apache.lucene.analysis.standard.StandardAnalyzer;import org.apache.lucene.document.Document;import org.apache.lucene.document.Field;import org.apache.lucene.index.IndexWriter;/!仅供测试public class T
37、est public int index(String indexDir, String dataDir) throws IOException File indexDirFile = new File(indexDir); File dataDirFile = new File(dataDir); int numIndexed = index(indexDirFile, dataDirFile); return 0; private int index(File indexDirFile, File dataDirFile) throws IOException if(!dataDirFil
38、e.exists() | !dataDirFile.isDirectory() throw new IOException(dataDirFile + does not exist or is not a directory); IndexWriter writer = new IndexWriter(indexDirFile, new StandardAnalyzer(), true); writer.setUseCompoundFile(false); indexDirectory(writer, dataDirFile); int numIndexed = writer.docCount
39、(); writer.optimize(); writer.close(); return numIndexed; private void indexDirectory(IndexWriter writer, File dataDirFile) throws IOException File files = dataDirFile.listFiles(); for(int i = 0; ifiles.length; i+) File f = filesi; if(f.isDirectory() indexDirectory(writer, f); else if(f.getName().en
40、dsWith(.java) | f.getName().endsWith(.txt)/需要索引的文件类型 indexFile(writer, f); private void indexFile(IndexWriter writer, File f) throws IOException if(f.isHidden() | !f.exists() | !f.canRead() return; System.out.println(Indexing + f.getCanonicalPath(); Document doc = new Document(); Reader txtReader =
41、new FileReader(f); doc.add(new Field(path,f.getCanonicalPath(),Field.Store.YES,Field.Index.UN_TOKENIZED); doc.add(new Field(contents,txtReader); doc.add(new Field(name,f.getName(),Field.Store.YES,Field.Index.UN_TOKENIZED); writer.addDocument(doc); public static void main(String args) String filesRep
42、oDir = E:/htmltextp;/需要被索引的目录 String indexDir = E:/htmltextp/index;/存放索引的目录 Test indexer= new Test(); try indexer.index(indexDir, filesRepoDir); catch (IOException e) / TODO Auto-generated catch blocke.printStackTrace(); 第9章 附录源代码:9.1 爬取存取代码:package PaQu;import java.io.BufferedReader;import java.io.File;import java.io.FileNotFoundException;impor