Heritrix3.3.0的org.archive.crawler.datamodel.UriUniqFilter接口提供对下载的uri的唯一性保证,它的子类org.archive.crawler.util.SetBasedUriUniqFilter实现了保证发送到下载队列的uri的是唯一的方法:
public void add(String key, CrawlURI value) {
profileLog(key);
if (setAdd(key)) {
this.receiver.receive(value);
if (setCount() % 50000 == 0) {
LOGGER.log(Level.FINE, "count: " + setCount() + " totalDups: "
+ duplicateCount + " recentDups: "
+ (duplicateCount - duplicatesAtLastSample));
duplicatesAtLastSample = duplicateCount;
}
} else {
duplicateCount++;
}
}
只有当setAdd()方法返回true的时候,receiver才接受这个uri,也就是说,只有当这个uri没有被下载过,就把这个uri放入下载队列。我们只需要把这个方法改为下面这个样子,爬虫就不会拒绝下载那些曾经下载过的uri了:
public void add(String key, CrawlURI value) {
profileLog(key);
// 实际上取消了重复判断
boolean isDuplicate = false;
if (!isDuplicate) {
this.receiver.receive(value);
if (setCount() % 50000 == 0) {
LOGGER.log(Level.FINE, "count: " + setCount() + " totalDups: "
+ duplicateCount + " recentDups: "
+ (duplicateCount - duplicatesAtLastSample));
duplicatesAtLastSample = duplicateCount;
}
} else {
duplicateCount++;
}
}
这样的修改在你需要它是一个随时接受你的下载任务的而不是一个通常的爬虫时会很有用。
如果,你是采用的镜像下载方式,你还得修改org.archive.modules.writer.MirrorWriterProcessor的writeToPath(),因为该方法往磁盘上写文件时,如果目标文件之前已经存在,就会抛出异常。我们在该方法中添加检查目标文件是否存在的代码,如果存在,就将文件删除。修改后的方法如下:
private void writeToPath(RecordingInputStream recis, File dest)
throws IOException {
File tf = new File (dest.getPath() + "N");
ReplayInputStream replayis = null;
FileOutputStream fos = null;
try {
replayis = recis.getMessageBodyReplayInputStream();
fos = new FileOutputStream(tf);
// 添加的部分
if (dest.isFile() && dest.exists()) {
dest.delete();
}
replayis.readFullyTo(fos);
} finally {
IOUtils.closeQuietly(replayis);
IOUtils.closeQuietly(fos);
}
if (!tf.renameTo(dest)) {
throw new IOException("Can not rename " + tf.getAbsolutePath()
+ " to " + dest.getAbsolutePath());
}
}