Heritrix3.3.0有一个很实用的功能,就是在抓取开始之后,依然可以通过在指定目录里放入种子文件的方式向爬虫添加新的种子。接下来,我们就来看看这个功能是怎样实现的。
这个功能是在org.archive.crawler.framework包下的ActionDirectory类实现的,这个类去掉内容后是这个样子的:
public class ActionDirectory implements ApplicationContextAware, Lifecycle, Runnable
可以看到,它实现了Runnable接口,那么,我们就来看看它的run方法:
/**
* Action taken at scheduled intervals
* @see java.lang.Runnable#run()
*/
public void run() {
scanActionDirectory();
}
run方法又直接调用了scanActionDirectory方法:
/**
* Find any new files in the 'action' directory; process each in
* order.
*
* 在action目录下寻找新文件
*/
protected void scanActionDirectory() {
File dir = actionDir.getFile();
File[] files = dir.listFiles((FileFilter)FileFilterUtils.fileFileFilter());
Arrays.sort(files);
for(File f : files) {
try {
actOn(f);
} catch (Throwable e) {
LOGGER.log(Level.SEVERE,"unhandled exception from actifile: "+f,e);
}
}
}
这个方法在action目录下寻找新的文件,并把发现的文件交给了actOn方法处理。这里有两个问题需要注意:(1)action目录(2)actOn方法。
首先看看存放新文件的目录action的声明:
protected ConfigPath actionDir =
new ConfigPath("ActionDirectory source directory","action");
不要ConfigPath类的具体内容困扰,我们只需要从字面意思来理解就够了,它表示了一个配置路径。这里它定义了我们关注的action目录,该目录默认被设置为action。如果大家曾经用过Heritrix3.3.0(版本3都一样),而且没有去设置过这个值,你会在你的项目录下的jobs目录下的具体job目录下发现名为action的目录,那个目录就是这里所讲的action目录。也就是说,Heritrix默认情况下是去那个action目录下发现新文件的。
从scanActionDirectory方法中可以看到,发现的新文件交给了actOn方法。这个方法在Heritrix3.3.0源码阅读 种子模块(观察者模式实践)一文中已经讲过,它用于从种子文件中读取种子,并发布给观察者。
到此,我们已经清楚了ActionDirectory类加载种子文件和发布种子的流程。接下来,就来看看ActionDirectory如何利用这个流程来实现“动态”载入种子的。其实我们自己就能猜出来,应该是用定时任务,事实也是这样的。
ActionDirectory类里有这个方法:
public void start() {
if (isRunning()) {
return;
}
try {
// create directories
org.archive.util.FileUtils.ensureWriteableDirectory(getActionDir().getFile());
org.archive.util.FileUtils.ensureWriteableDirectory(getDoneDir().getFile());
} catch (IOException e) {
throw new IllegalStateException(e);
}
// start background executor
executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleWithFixedDelay(this, getInitialDelaySeconds(), getDelaySeconds(), TimeUnit.SECONDS);
}
这个方法被调用来启动定时任务。定时任务是通过执行器实现的,而不是Timer。如果大家不知道执行器,可以百度一下,或者看看《java核心技术卷一》十三章关于执行器那一节。
到此,我们搞清楚了Heritrix3.3.0是如何实现动态载入种子的了:用一个定时任务从指定目录加载种子文件,发布文件里的种子。