系统程序设计说明书.docx
- 文档编号:2290643
- 上传时间:2022-10-28
- 格式:DOCX
- 页数:26
- 大小:79.49KB
系统程序设计说明书.docx
《系统程序设计说明书.docx》由会员分享,可在线阅读,更多相关《系统程序设计说明书.docx(26页珍藏版)》请在冰豆网上搜索。
系统程序设计说明书
系统程序设计说明书
景德镇陶瓷学院
1Heritrix的架构
1.1抓取任务CrawlOrder
CrawlOrder是整个抓取工作的起点。
在上一节中已经说过,一次抓取任务包括许多的属性,建立一个任务的方式有很多种,最简单的一种就是根据默认的order.xml来配置。
在内存中,order使用CrawlOrder这个类来进行表示。
看一下API文档中CrawlOrder的继承关系图。
CrawlOrder继承自一系列的与属性设置相关的基类,它的最顶层基类是javax.management.Attribute,这是一个JMX中的类,它可以动态的反映出Java容器内某个MBean的属性变化。
CrawlOrder中的属性,是需要被随时读取和监测的。
在org.archive.crawler.settings包下有一个XMLSettingsHandler类,它可以用来帮助读取order.xml。
publicXMLSettingsHandler(FileorderFile)throwsInvalidAttributeValueException
在XMLSettingsHandler的构造函数中,其所传入的参数orderFile正是一个经过对象封装的order.xml的File。
这样,就可以直接调用其构造函数,来创建一个XMLSettingsHandler的实例,以此做为一个读取order.xml的工具。
当一个XMLSettingsHandler的实例被创建后,可以通过getOrder()方法来获取CrawlOrder的实例,这样也就可以进行下一步的工作了。
1.2中央控制器CrawlController
中央控制器是一次抓取任务中的核心组件。
它将决定整个抓取任务的开始和结束。
CrawlController位于org.archive.crawler.framework中,在它的Field声明中,看到如下代码片段。
代码1
//keysubcomponentswhichdefineandimplementacrawlinprogress
privatetransientCrawlOrderorder;
privatetransientCrawlScopescope;
privatetransientProcessorChainListprocessorChains;
privatetransientFrontierfrontier;
privatetransientToePooltoePool;
privatetransientServerCacheserverCache;
//Thisgetspassedintotheinitializemethod.
privatetransientSettingsHandlersettingsHandler;
可以看到,在CrawlController类中,定义了以下几个组件:
CrawlOrder:
这就不用说了,因为一个抓取工作必须要有一个Order对象,它保存了对该次抓取任务中,order.xml的属性配置。
CrawlScope:
这是决定当前的抓取范围的一个组件。
ProcessorChainList:
从名称上很明显就能看出,它表示了处理器链。
Frontier:
很明显,一次抓取任务需要设定一个Frontier,以此来不断为其每个线程提供URI。
ToePool:
这是一个线程池,它管理了所有该抓取任务所创建的子线程。
ServerCache:
这是一个缓存,它保存了所有在当前任务中,抓取过的Host名称和Server名称。
以上组件应该是一次正常的抓取过程中所必需的几项,它们各自的任务很独立,分工明确,但在后台中,它们之间却有着千丝万缕的联系,彼此互相做为构造函数或初始化的参数传入。
那么,究竟该如何获得CrawlController的实例,并且通过自主的编程来使用Heritrix提供的API进行一次抓任务呢?
事实上CrawlController有一个不带参数的构造函数,开发者可以直接通过它的构造函数来构造一个CrawlController的实例。
但是值得注意的一点,在构造一个实例并进行抓取任务时,有几个步骤需要完成:
(1)首先构造一个XMLSettingsHandler对象,将order.xml内的属性信息装入。
(2)调用CrawlController的构造函数,构造一个CrawlController的实例。
(3)调用CrawlController的intialize(SettingsHandler)方法,初始化CrawlController实例。
其中,传入的参数是在第一步是构造的XMLSettingsHandler实例。
(4)当上述3步完成后,CrawlController就已经具备运行的条件,可以开始运行了。
此时,只需调用它的requestCrawlStart()方法,就可以启运线程池和Frontier,然后就可以开始不断的抓取网页了。
使用CrawlController启动抓取任务
在CrawlController的initialize()方法中,Heritrix主要做了以下几件事:
(1)从XMLSettingsHandler中取出Order。
(2)检查了用户设定的UserAgent等信息,看是否符合格式。
(3)设定了开始抓取后保存文件信息的目录结构。
(4)初始化了日志信息的记录工具。
(5)初始化了使用BerkleyDB的一些工具。
(6)初始化了Scope、Frontier以及ProcessorChain。
(7)最后实例化了线程池。
在正常情况下,以上顺序不能够被随意变动,因为后一项功能的初始化很有可能需要前几项功能初始化的结果。
例如线程池的初始化,必须要在先有了Frontier的实例的基础上来进行。
读者可能对其中的BerkeleyDB感到费解,在后面的小节将详细说明。
最终启动抓取工作的是requestCrawlStart()方法。
其代码如下。
代码2
publicvoidrequestCrawlStart(){
//初始化处理器链
runProcessorInitialTasks();
//设置一下抓取状态的改变,以便能够激发一些Listeners
//来处理相应的事件
sendCrawlStateChangeEvent(STARTED,CrawlJob.STATUS_PENDING);
StringjobState;
state=RUNNING;
jobState=CrawlJob.STATUS_RUNNING;
sendCrawlStateChangeEvent(this.state,jobState);
//Aproperexitwillchangethisvalue.
this.sExit=CrawlJob.STATUS_FINISHED_ABNORMAL;
//开始日志线程
ThreadstatLogger=newThread(statistics);
statLogger.setName("StatLogger");
statLogger.start();
//启运Frontier,抓取工作开始
frontier.start();
}
可以看到,启动抓取工作的核心就是要启动Frontier(通过调用其start()方法),以便能够开始向线程池中的工作线程提供URI,供它们抓取。
下面的代码就是BdbFrontier的父类AbstractFrontier中的start()方法和unpause()方法:
代码3
publicvoidstart(){
if(((Boolean)getUncheckedAttribute(null,ATTR_PAUSE_AT_START))
.booleanValue()){
//若配置文件中不允许该次抓取开始
//则停止
controller.requestCrawlPause();
}else{
//若允许开始,则开始
unpause();
}
}
synchronizedpublicvoidunpause(){
//去除当前阻塞变量
shouldPause=false;
//唤醒所有阻塞线程,开始抓取任务
notifyAll();
}
在start()方法中,首先判断配置中的属性是否允许当前线程开始。
若不允许,则令controller停止抓取。
若允许开始,则简单的调用unpause()方法。
unpause()方法更为简单,它首先将阻塞线程的信号量设为false,即允许线程开始活动,然后通过notifyAll()方法,唤醒线程池中所有被阻塞的线程,开始抓取。
Frontier链接制造工厂
Frontier在英文中的意思是“前线,领域”,在Heritrix中,它表示一种为线程提供链接的工具。
它通过一些特定的算法来决定哪个链接将接下来被送入处理器链中,同时,它本身也负责一定的日志和状态报告功能。
事实上,要写出一个合格并且真正能够使用的Frontier绝非一件简单的事情,尽管有了Frontier接口,其中的方法约束了Frontier的行为,也给编码带来了一定的指示。
但是其中还存在着很多问题,需要很好的设计和处理才可以解决。
在Heritrix的官方文档上,有一个Frontier的例子,在此拿出来进行一下讲解,以此来向读者说明一个最简单的Frontier都能够做什么事。
以下就是这个Frontier的代码。
代码4
publicclassMyFrontierextendsModuleTypeimplementsFrontier,
FetchStatusCodes{
//列表中保存了还未被抓取的链接
ListpendingURIs=newArrayList();
//这个列表中保存了一系列的链接,它们的优先级
//要高于pendingURIs那个List中的任何一个链接
//表中的链接表示一些需要被满足的先决条件
Listprerequisites=newArrayList();
//一个HashMap,用于存储那些已经抓取过的链接
MapalreadyIncluded=newHashMap();
//CrawlController对象
CrawlControllercontroller;
//用于标识是否一个链接正在被处理
booleanuriInProcess=false;
//成功下载的数量
longsuccessCount=0;
//失败的数量
longfailedCount=0;
//抛弃掉链接的数量
longdisregardedCount=0;
//总共下载的字节数
longtotalProcessedBytes=0;
//构造函数
publicMyFrontier(Stringname){
super(Frontier.ATTR_NAME,"Asimplefrontier.");
}
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 系统 程序设计 说明书
![提示](https://static.bdocx.com/images/bang_tan.gif)