Nutch1.7源码再研究之---8 Nutch的generate(续)

接下来的代码是:

// read the subdirectories generated in the temp

// output and turn them into segments

List<Path> generatedSegments = new ArrayList<Path>();

FileStatus[] status = fs.listStatus(tempDir); //获取文件夹的文件列表

try 

{

for (FileStatus stat : status) { //对于每一个文件

Path subfetchlist = stat.getPath(); //获取路径

if (!subfetchlist.getName().startsWith("fetchlist-")) //判断是否以fetchlist开头...

continue;

// start a new partition job for this segment

Path newSeg = partitionSegment(fs, segments, subfetchlist, numLists); //又开启了一个Hadoop任务。

generatedSegments.add(newSeg);

}

catch (Exception e) 

{

LOG.warn("Generator: exception while partitioning segments, exiting ...");

fs.delete(tempDir, true);

return null;

}

  -------------------接下来看看Hadoop任务如何执行的。

先看代码:

// invert again, partition by host/domain/IP, sort by url hash

if (LOG.isInfoEnabled()) {

LOG.info("Generator: Partitioning selected urls for politeness.");

}

Path segment = new Path(segmentsDir, generateSegmentName());

Path output = new Path(segment, CrawlDatum.GENERATE_DIR_NAME);

LOG.info("Generator: segment: " + segment);

NutchJob job = new NutchJob(getConf());

job.setJobName("generate: partition " + segment);

job.setInt("partition.url.seed"new Random().nextInt());

FileInputFormat.addInputPath(job, inputDir);

job.setInputFormat(SequenceFileInputFormat.class);

job.setMapperClass(SelectorInverseMapper.class);

job.setMapOutputKeyClass(Text.class);

job.setMapOutputValueClass(SelectorEntry.class);

job.setPartitionerClass(URLPartitioner.class);

job.setReducerClass(PartitionReducer.class);

job.setNumReduceTasks(numLists);

FileOutputFormat.setOutputPath(job, output);

job.setOutputFormat(SequenceFileOutputFormat.class);

job.setOutputKeyClass(Text.class);

job.setOutputValueClass(CrawlDatum.class);

job.setOutputKeyComparatorClass(HashComparator.class);

JobClient.runJob(job);

return segment;

从中可以看到,这个Hadoop任何的核心还是map类,reduce类。

下面一一进行解释。

------------------------------------------------------

 

job.setMapperClass(SelectorInverseMapper.class);

进入这个类的代码。

这个类的代码真的是叫送福利来了,为啥,因为太简单了。

 

public static class SelectorInverseMapper extends MapReduceBase implements

Mapper<FloatWritable, SelectorEntry, Text, SelectorEntry> {

public void map(FloatWritable key, SelectorEntry value,

OutputCollector<Text, SelectorEntry> output, Reporter reporter)

throws IOException {

SelectorEntry entry = value;

output.collect(entry.url, entry);

}

}

很简单,但是这里需要提醒的是,这里的参数FloatWritable key被丢弃了?

为什么?

说明这里不需要了,那么这里的key怎么回事?实际上这里的key是之前的分数。

分数在这里被丢弃,不需要了,说明上一篇文章做了一个分数排序优先级的概念。

看到这里,我也才明白上一篇文章的精髓之所在。醍醐灌顶。

---------------------------------------------------------------

接下来是Partition分区操作。

job.setPartitionerClass(URLPartitioner.class);

这里的操作跟上一篇的操作时一样的,所以这里也不赘述。

---------------------------------------------------------------

接下来讲解reduce类。

 

job.setReducerClass(PartitionReducer.class);

看一看它的代码。仍然是送福利,太爽了。

 

public static class PartitionReducer extends MapReduceBase implements

Reducer<Text, SelectorEntry, Text, CrawlDatum> {

public void reduce(Text key, Iterator<SelectorEntry> values,

OutputCollector<Text, CrawlDatum> output, Reporter reporter)

throws IOException {

// if using HashComparator, we get only one input key in case of

// hash collision

// so use only URLs from values

while (values.hasNext()) {

SelectorEntry entry = values.next();

output.collect(entry.url, entry.datum);

}

}

}

 这是最容易搞定的代码!

---------------------------------然后,接下来是数据校验

 

if (generatedSegments.size() == 0) {

LOG.warn("Generator: 0 records selected for fetching, exiting ...");

LockUtil.removeLockFile(fs, lock);

fs.delete(tempDir, true);

return null;

}

这段代码很简单,就不赘述了。

------------------------------------------------------

接下来的代码:

 

if (getConf().getBoolean(GENERATE_UPDATE_CRAWLDBfalse)) {

这段默认值是false.所以下面的代码暂时不执行,但是应该可以作为【提高效率的一个点。

后续 有时间再分析这段代码。

---------------------------------------------------------------------------------

接下来的代码是:

 

long end = System.currentTimeMillis();

LOG.info("Generator: finished at " + sdf.format(end) + ", elapsed: "

+ TimingUtil.elapsedTime(start, end));

Path[] patharray = new Path[generatedSegments.size()];

return generatedSegments.toArray(patharray);

返回最终结果,里面是segments的路径。

至此,generate分析完毕!

你可能感兴趣的:(Nutch,generate)