Nutch 源代码分析(1) Crawl 类
(以下分析针对的是 nutch 1.4)
Crawl 类是运行抓取程序的入口,代码不多,但关联的其他类不少。
抓取的流程是:
1. 将初始的 URL 地址注入到 crawlDb
2. 从crawldb中生成一个url的子集用于抓取
3. 抓取网页
4. 分析网页
5. 更新 crawlDb ,增加新抓取的 url
6. 循环执行 2-5 步,直到达到指定的抓取深度
之后,还需要进行链接反转,将索引导入到 solr 等。
Crawl 类的声明如下:
public class Crawl extends Configured implements Tool
public static void main(String args[]) throws Exception { // 创建 Configuration 对象 Configuration conf = NutchConfiguration.create(); // 执行任务 int res = ToolRunner.run(conf, new Crawl(), args); // 退出程序 System.exit(res); } // 默认参数 Path rootUrlDir = null; Path dir = new Path("crawl-" + getDate()); int threads = getConf().getInt("fetcher.threads.fetch", 10); int depth = 5; long topN = Long.MAX_VALUE; String solrUrl = null; for (int i = 0; i < args.length; i++) { if ("-dir".equals(args[i])) { dir = new Path(args[i+1]); i++; } else if ("-threads".equals(args[i])) { threads = Integer.parseInt(args[i+1]); i++; } else if ("-depth".equals(args[i])) { depth = Integer.parseInt(args[i+1]); i++; } else if ("-topN".equals(args[i])) { topN = Integer.parseInt(args[i+1]); i++; } else if ("-solr".equals(args[i])) { solrUrl = StringUtils.lowerCase(args[i + 1]); i++; } else if (args[i] != null) { rootUrlDir = new Path(args[i]); } } Path tmpDir = job.getLocalPath("crawl"+Path.SEPARATOR+getDate()); Injector injector = new Injector(getConf()); Generator generator = new Generator(getConf()); Fetcher fetcher = new Fetcher(getConf()); ParseSegment parseSegment = new ParseSegment(getConf()); CrawlDb crawlDbTool = new CrawlDb(getConf()); LinkDb linkDbTool = new LinkDb(getConf()); // 初始化 crawlDb // 将初始的 URL 地址到 crawlDb injector.inject(crawlDb, rootUrlDir); int i; // 循环执行,直到达到指定的抓取深度 for (i = 0; i < depth; i++) { // 生成要抓取的 URL Path[] segs = generator.generate(crawlDb, segments, -1, topN, System.currentTimeMillis()); // 没有需要抓取的 URL 了,提前中止抓取过程 if (segs == null) { LOG.info("Stopping at depth=" + i + " - no more URLs to fetch."); break; } fetcher.fetch(segs[0], threads); // 抓取网页 if (!Fetcher.isParsing(job)) { parseSegment.parse(segs[0]); // 分析网页 } crawlDbTool.update(crawlDb, segs, true, true); // 更新 crawldb,增加需要抓取的 URL }linkDbTool.invert(linkDb, segments, true, true, false);
// 将索引导入到 solr if (solrUrl != null) { // 获取创建好的 nutch 索引的文件索引 FileStatus[] fstats = fs.listStatus(segments, HadoopFSUtil.getPassDirectoriesFilter(fs)); // 建立 Solr 索引 SolrIndexer indexer = new SolrIndexer(getConf()); indexer.indexSolr(solrUrl, crawlDb, linkDb, Arrays.asList(HadoopFSUtil.getPaths(fstats))); // 去重 SolrDeleteDuplicates dedup = new SolrDeleteDuplicates(); dedup.setConf(getConf()); dedup.dedup(solrUrl); }