Nutch 源代码分析(1) Crawl 类
程序员文章站
2022-04-26 12:06:24
...
(以下分析针对的是 nutch 1.4)
Crawl 类是运行抓取程序的入口,代码不多,但关联的其他类不少。
抓取的流程是:
1. 将初始的 URL 地址注入到 crawlDb
2. 从crawldb中生成一个url的子集用于抓取
3. 抓取网页
4. 分析网页
5. 更新 crawlDb ,增加新抓取的 url
6. 循环执行 2-5 步,直到达到指定的抓取深度
之后,还需要进行链接反转,将索引导入到 solr 等。
Crawl 类的声明如下:
Configured 和 Tool 是 hadoop 中的概念
Configured 是 hadoop 中用来提供配置信息的,在 ToolRunner.run 方法中,会将创建好的 Configuration 对象通过 Configured.setConf 方法注入到 Crawl 中。
Tool 是 hadoop 中用来处理命令行参数并修改 Map-Reduce 任务的参数,它需要在 run 方法中处理这些命令行参数。
因为 Crawl 实现了 Tool 接口,我们可以通过命令行启动数据抓取的 Map-Reduce 任务。
启动 Crawl 的 main 方法如下:
NutchConfiguration.create 会加载 nutch-default.xml 和 nutch-site.xml 中的配置信息生成 Configuration 对象。
ToolRunner.run 方法会将创建好的 Configuration 对象通过 Configured.setConf 方法注入到 Crawl 中(Crawl 继承了Configured),并将参数的处理委托给 Tool.run 方法(Crawl 实现了 Tool 接口,因此需要提供 run 方法的实现)。
接下来我们重点分析一下 Crawl 类的 run 方法。
首先是参数的设置:
这几个参数的含义如下:
rootUrlDir : 要抓取的起始 url 所在的目录
dir : 默认情况下,抓取时生成的文件的目录
threads : 抓取数据的线程数
depth : 通过外链抓取网页的深度,从起始 url 算起
topN : 每轮抓取获得的新的 url 中,只对分值最高的 topN 个 url 再次抓取
solrUrl : solr 的地址。用于调用 solr 的 api 建立用于搜索的索引。
这些参数是可以根据命令行的输入修改的:
然后需要创建抓取程序将要用到的对象:
这里简要说明一下这些对象的作用:
injector : 将初始的 URL 地址到 crawlDb
generator : 生成要抓取的 URL
fetcher : 抓取网页
parseSegment : 分析网页
crawlDbTool : CrawlDb 类的实例,存放将要抓取的 URL
linkDbTool : 用于存放链接之间的引用关系,便于计算权重
完成以上的准备工作之后,就开始执行主要的处理逻辑:
前面通过抓取和分析网页得到的链接格式为 源链接 => 目标链接,
需要通过反转,得到目标链接对应的源链接,以便于计算目标链接的权重等:
最后,如果指定了 solrUrl,需要将 nutch 索引导入到 solr 中
以上只是对源代码进行字面上的分析,更深入的分析可以参考以下文章:
http://blog.csdn.net/kauu/article/details/1823830
http://www.diybl.com/course/3_program/java/javajs/20100719/459450.html
Crawl 类是运行抓取程序的入口,代码不多,但关联的其他类不少。
抓取的流程是:
1. 将初始的 URL 地址注入到 crawlDb
2. 从crawldb中生成一个url的子集用于抓取
3. 抓取网页
4. 分析网页
5. 更新 crawlDb ,增加新抓取的 url
6. 循环执行 2-5 步,直到达到指定的抓取深度
之后,还需要进行链接反转,将索引导入到 solr 等。
Crawl 类的声明如下:
public class Crawl extends Configured implements Tool
Configured 和 Tool 是 hadoop 中的概念
Configured 是 hadoop 中用来提供配置信息的,在 ToolRunner.run 方法中,会将创建好的 Configuration 对象通过 Configured.setConf 方法注入到 Crawl 中。
Tool 是 hadoop 中用来处理命令行参数并修改 Map-Reduce 任务的参数,它需要在 run 方法中处理这些命令行参数。
因为 Crawl 实现了 Tool 接口,我们可以通过命令行启动数据抓取的 Map-Reduce 任务。
启动 Crawl 的 main 方法如下:
public static void main(String args[]) throws Exception { // 创建 Configuration 对象 Configuration conf = NutchConfiguration.create(); // 执行任务 int res = ToolRunner.run(conf, new Crawl(), args); // 退出程序 System.exit(res); }
NutchConfiguration.create 会加载 nutch-default.xml 和 nutch-site.xml 中的配置信息生成 Configuration 对象。
ToolRunner.run 方法会将创建好的 Configuration 对象通过 Configured.setConf 方法注入到 Crawl 中(Crawl 继承了Configured),并将参数的处理委托给 Tool.run 方法(Crawl 实现了 Tool 接口,因此需要提供 run 方法的实现)。
接下来我们重点分析一下 Crawl 类的 run 方法。
首先是参数的设置:
// 默认参数 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;
这几个参数的含义如下:
rootUrlDir : 要抓取的起始 url 所在的目录
dir : 默认情况下,抓取时生成的文件的目录
threads : 抓取数据的线程数
depth : 通过外链抓取网页的深度,从起始 url 算起
topN : 每轮抓取获得的新的 url 中,只对分值最高的 topN 个 url 再次抓取
solrUrl : solr 的地址。用于调用 solr 的 api 建立用于搜索的索引。
这些参数是可以根据命令行的输入修改的:
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());
这里简要说明一下这些对象的作用:
injector : 将初始的 URL 地址到 crawlDb
generator : 生成要抓取的 URL
fetcher : 抓取网页
parseSegment : 分析网页
crawlDbTool : CrawlDb 类的实例,存放将要抓取的 URL
linkDbTool : 用于存放链接之间的引用关系,便于计算权重
完成以上的准备工作之后,就开始执行主要的处理逻辑:
// 初始化 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);
最后,如果指定了 solrUrl,需要将 nutch 索引导入到 solr 中
// 将索引导入到 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); }
以上只是对源代码进行字面上的分析,更深入的分析可以参考以下文章:
http://blog.csdn.net/kauu/article/details/1823830
http://www.diybl.com/course/3_program/java/javajs/20100719/459450.html
下一篇: JAVA NIO 全书 译稿
推荐阅读
-
深入分析:用1K内存实现高效I/O的RandomAccessFile类的详解
-
深入分析:用1K内存实现高效I/O的RandomAccessFile类的详解
-
PHP 源代码分析 Zend HashTable详解第1/3页
-
Java基础之Collections框架Map接口实现类HashMap及其源码分析(1)
-
JVM系列(1)深入浅出分析JVM类加载机制
-
java【集合类】源代码分析--ArrayList
-
1. 实例演示Ement常用语法 2. 实例演示元素四类属性 3. 实例演示布局标签,并分析div+class与 html5语义化标签的优缺点
-
PHP 源代码分析 Zend HashTable详解第1/3页
-
1. 实例演示Ement常用语法 2. 实例演示元素四类属性 3. 实例演示布局标签,并分析div+class与 html5语义化标签的优缺点
-
hashtable PHP 源代码分析 Zend HashTable详解第1/3页