最近在Ubuntu下配置好了nutch和solr的环境,也用nutch爬取了一些网页,通过solr界面呈现,也过了一把自己建立小搜索引擎的瘾,现在该静下心来好好看看nutch的源码了,先从Inject开始吧~~~
1.从crawl.java的main函数进入,执行: Configuration conf = NutchConfiguration.create();
再进入NutchConfiguration(NutchConfiguration负责加载管理nutch的配置文件信息,该类继承自Configuration,继承了Configuration所有功能,加载配置文件功能也是继承自Configuration类)类的create方法,执行:Configuration conf = new Configuration();从执行结果可以看出在类Configuration的静态代码块中代码 addDefaultResource("core-default.xml");addDefaultResource("core-site.xml");可以看出是加载了core-default.xml, core-site.xml两个文件;
 
2.通过Configuration完成指定配置文件的加载,加载后的conf为:Configuration: core-default.xml, core-site.xml, nutch-default.xml, nutch-site.xml共四个配置文件;
之后回到crawl的main函数中执行:int res = ToolRunner.run(conf, new Crawl(), args);参数conf是刚刚加载好配置文件的Configuration对象,Crawl是要执行的对象类,args是用户输入的参数串,这里是使用hadoop的工具类ToolRunner运行实例Crawl类,即进入核心的爬虫模块;
然后进入ToolRunner类的run()方法,第一步就是利用类GenericOptionsParser(备注:GenericOptionsParser是hadoop框架中解析命令行参数的基本类。它能够辨别一些标准的命令行参数,能够使应用程序轻易地指定namenode,jobtracker,以及其他额外的配置资源)对输入的命令行参数args(如[urls, -dir, crawl20140724, -depth, 2, -threads, 8, -topN, 100])进行解析,再执行:String[] toolArgs = parser.getRemainingArgs();获得解析后的参数数组(比如[urls, -dir, crawl20140724, -depth, 2, -threads, 8, -topN, 100]);
然后执行返回语句:return tool.run(toolArgs);这里的tool就是Crawl类的对象,run()方法也是Crawl类中的run方法;
 
3.解析完用户的输入参数后,执行Crawl类的run()方法。第一步就是配置程序的默认参数,如果用户没有相应的参数赋值就使用这些默认的参数。注意这里有一点编程思想可以借鉴:
int threads = getConf().getInt("fetcher.threads.fetch", 10);该行代码的getInt方法具体如下:
public int getInt(String name, int defaultValue) {
String valueString = get(name);//get的核心代码为:return substituteVars(getProps().getProperty(name));,主要是从配置文件中查找有没有相应的赋值
if (valueString == null)
    return defaultValue;//如果配置文件中没有赋值,则valueString为null,这是getInt方法的返回值就是默认值10,即defaultValue
try {
    String hexString = getHexDigits(valueString);
    if (hexString != null) {
        return Integer.parseInt(hexString, 16);
    }
    return Integer.parseInt(valueString);
} catch (NumberFormatException e) {
    return defaultValue;
    }
}
后面就是遍历args参数串,如果发现匹配的则对相应的变量赋值
第二步初始化jobconf:JobConf job = new NutchJob(getConf());执行后job为Configuration: core-default.xml, core-site.xml, mapred-default.xml, mapred-site.xml, nutch-default.xml, nutch-site.xml等于讲conf的加入后还在JobConf类中的静态代码块中加入了配置文件mapred-default.xml, mapred-site.xml。
 
后面又初始化文件系统:FileSystem fs = FileSystem.get(job);下面是网上关于FileSystem的介绍(备注:

就像上节所说的,有时候我们无法通过设置URLStreamHandlerFactory方法的方式来通过URL读取数据,这时FIleSystem API就派上用场了。 
Hadoop文件系统中的文件是用Hadoop的Path对象来表示的(而不是java中的java.io.File对象,因为它的语义太接近于本地文件系统了)。你可以把一个Path对象看做Hadoop文件系统中的某一个URL,如上例中的“hdfs://localhost/user/tom/quangle.txt”。 
Filesystem是一个通用的文件系统API,所以使用它的第一步就是先抽取出它的一个实例出来——在这个例子中是HDFS。下面列出了几个Filesystem的用于抽取Filesystem实例的几个静态方法:

public static FileSystem get(Configuration conf) throws IOException 
public static FileSystem get(URI uri, Configuration conf) throws IOException 
public static FileSystem get(URI uri, Configuration conf, String user) throws IOException

一个Configuration对象封装了客户端或服务器端的配置信息,这些配置信息是通过从conf/core-size.xml之类的配置文件中读取出来的名值对来设置的。下面我们一一说明上面的三个方法: 
1)第一个方法返回一个默认的文件系统(在conf/core-site.xml中通过fs.default.name来指定的,如果在conf/core-site.xml中没有设置则返回本地文件系统)。 
2)第二个方法通过uri来指定要返回的文件系统(例如,如果uri是上个测试例子中的hdfs://localhost/user/tom/quangle.txt,也即以hdfs标识开头,那么就返回一个hdfs文件系统,如果uri中没有相应的标识则返回本地文件系统)。 
3)第三个方法返回文件系统的机理同(2)是相同的,但它同时又限定了该文件系统的用户,这在安全方面是很重要的。

 
4.初始化jobconf和filesystem后,主要是一些参数的界面输出,以及明确临时文件的存放位置并初始化nutch爬取的几个流程类inject、generate、fetch、parse和update等;
然后执行:injector.inject(crawlDb, rootUrlDir);初始化CrawlDb,实现将url转换为指定格式的输入;
进入该方法后,设置一些的参数,包括输入输出,mapper类等,最后提交job交由mapreduce执行,JobClient.runJob(sortJob);
通过调试模式看到,程序是先进入了Inject类的configurable方法进行了一些参数的赋值,然后跳到Inject类的map方法,该方法主要包括:读取url,对url进行分割,url规范化和过滤的操作,然后返回一个处理后的url;
然后再生声明CrawlDatum类:CrawlDatum datum = new CrawlDatum(CrawlDatum.STATUS_INJECTED, customInterval);,最终是要将输入数据转换为<Text,CrawlDatum >格式的,设置一些url的初始化数据(在ScroingFilters类中的injectedScore方法可以看到的datum值为:
Version: 7
Status: 66 (injected)
Fetch time: Thu Jul 24 23:04:37 CST 2014
Modified time: Thu Jan 01 08:00:00 CST 1970
Retries since fetch: 0
Retry interval: 2592000 seconds (30 days)
Score: 1.0
Signature: null
Metadata: 
 
通过调试看到程序执行完Inject的map方法后会跳到MapRunner中的run方法,部分代码如下:
public void run(RecordReader<K1, V1> input, OutputCollector<K2, V2> output,
Reporter reporter)
throws IOException {
try {
// allocate key & value instances that are re-used for all entries
K1 key = input.createKey();
V1 value = input.createValue();

while (input.next(key, value)) {

……
其中in就是url存放的文件的读入流;
然后又跳入LoadJobRunner类中执行代码,在这里会执行:ReduceTask reduce =
new ReduceTask(systemJobFile.toString(), reduceId, 0, mapIds.size(),
1);……reduce.run(localConf, this);……的代码
 
之后会有一些输入输出流的关闭以及杀死一些线程,还有删除本地的一些临时文件
以上便是nutch的Inject部分的实现流程。
 
参考博文:http://blog.csdn.net/amuseme_lu/article/details/6713386

友情赞助

如果你觉得博主的文章对你那么一点小帮助,恰巧你又有想打赏博主的小冲动,那么事不宜迟,赶紧扫一扫,小额地赞助下,攒个奶粉钱,也是让博主有动力继续努力,写出更好的文章^^。

    1. 支付宝                          2. 微信

                      

Nutch源码阅读进程1---inject的更多相关文章

  1. Nutch源码阅读进程5---updatedb

    看nutch的源码仿佛就是一场谍战片,而构成这精彩绝伦的谍战剧情的就是nutch的每一个从inject->generate->fetch->parse->update的环节,首 ...

  2. Nutch源码阅读进程3---fetch

    走了一遍Inject和Generate,基本了解了nutch在执行爬取前的一些前期预热工作,包括url的过滤.规则化.分值计算以及其与mapreduce的联系紧密性等,自我感觉nutch的整个流程是很 ...

  3. Nutch源码阅读进程2---Generate

    继之前仓促走完nutch的第一个流程Inject后,再次起航,Debug模式走起,进入第二个预热阶段Generate~~~   上期回顾:Inject主要是将爬取列表中的url转换为指定格式<T ...

  4. Nutch源码阅读进程3

    走了一遍Inject和Generate,基本了解了nutch在执行爬取前的一些前期预热工作,包括url的过滤.规则化.分值计算以及其与mapreduce的联系紧密性等,自我感觉nutch的整个流程是很 ...

  5. Nutch源码阅读进程5

    看nutch的源码仿佛就是一场谍战片,而构成这精彩绝伦的谍战剧情的就是nutch的每一个从inject->generate->fetch->parse->update的环节,首 ...

  6. Nutch源码阅读进程4---parseSegment

    前面依次看了nutch的准备工作inject和generate部分,抓取的fetch部分的代码,趁热打铁,我们下面来一睹parse即页面解析部分的代码,这块代码主要是集中在ParseSegment类里 ...

  7. Nutch源码阅读进程4

    前面依次看了nutch的准备工作inject和generate部分,抓取的fetch部分的代码,趁热打铁,我们下面来一睹parse即页面解析部分的代码,这块代码主要是集中在ParseSegment类里 ...

  8. Linux 源码阅读 进程管理

    Linux 源码阅读 进程管理 版本:2.6.24 1.准备知识 1.1 Linux系统中,进程是最小的调度单位: 1.2 PCB数据结构:task_struct (Location:linux-2. ...

  9. golang martini 源码阅读笔记之inject

    martini是go语言写的一个超级轻量的web开源框架,具体源码可在github搜索找到.13年那会开始接触go语言时有稍微看过这个框架,由于之后没有继续使用go就慢慢忽略了,最近由于手头项目可能会 ...

随机推荐

  1. angularjs 表单验证(不完整版)

    针对项目实践表单验证总结: angular 的 form表单验证:form内需要novalidate取消默认验证,用ng自己的验证,form的名字是非常必要的 栗子:以注册为栗子,下面是注册的部分: ...

  2. 深入分析PHP优化及注意事项

    深入分析PHP优化及注意事项 1.尽量静态化: 如果一个方法能被静态,那就声明它为静态的,速度可提高1/4,甚至我测试的时候,这个提高了近三倍. 当然了,这个测试方法需要在十万级以上次执行,效果才明显 ...

  3. 用canvas制作酷炫射击游戏--part1

    好久没写博客了,因为过年后一直在学游戏制作方面的知识.学得差不多后又花了3个月时间做了个作品出来,现在正拿着这个作品找工作. 作品地址:https://betasu.github.io/Crimonl ...

  4. iOS图片加载框架-SDWebImage解读

    在iOS的图片加载框架中,SDWebImage可谓是占据大半壁江山.它支持从网络中下载且缓存图片,并设置图片到对应的UIImageView控件或者UIButton控件.在项目中使用SDWebImage ...

  5. markdown语法记录

    换行:在结尾加两个空格后回车. 缩进:将输入法切换到全角,两个空格就是两个汉字的大小.

  6. 解剖SQLSERVER 第十三篇 Integers在行压缩和页压缩里的存储格式揭秘(译)

    解剖SQLSERVER 第十三篇    Integers在行压缩和页压缩里的存储格式揭秘(译) http://improve.dk/the-anatomy-of-row-amp-page-compre ...

  7. Angular 2 + Electron 开发web和桌面应用

    https://github.com/zhongzf/angular2-electron-quickstart Web用法: # Clone this repository git clone htt ...

  8. 如何利用Github+Appveyor+Nuget打造自己的.net core开源库

    以下教程基于你有一个托管在Github上的.net core项目,如果没有的可以自己fork一个或者自己创建了默认的项目即可. 我们打开需要生成nuget包的项目中的project.json文件,有关 ...

  9. DataTables 控件使用和心得 (2) - 参数Options

    什么是DataTables参数(Options) 上篇我们说了,DataTables控件的加载函数dataTable()一般都有一个对象参数,这个对象参数就是整个DataTables控件的参数(Opt ...

  10. 如何实现:录制视频聊天的全过程? 【低调赠送:QQ高仿版GG 4.3 最新源码】

    前段时间做个项目,客户需要将视频对话的整个过程录制下来,这样,以后就可以随时观看.想来录制整个视频聊天的过程这样的功能应该是个比较常见的需求,比如,基于网络语音视频的1:1的英语口语辅导,如果能将辅导 ...