最近在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. Android--短信

    1.Android 提供一系列 API,可以是我们在自己的程序中发送和接收短信: 2.接收短信: 1)当手机接收到一条短信时,系统会发出一条值为 android.provider.Telephony. ...

  2. MVVM和MVC的区别

    MVVM(Model-View-ViewModel) 优点:低耦合:可重用:独立开发:可测试 即,将页面与数据分离的模式:将数据绑定工作放到javaScript文件中实现,javaScript文件的主 ...

  3. unity发布安卓 手指控制物体缩放和旋转

    直接帮到物体的身上就可以了 using UnityEngine; using System.Collections;using System.IO;public class hehe : MonoBe ...

  4. SQL入门经典(九) 之自定义函数

    UDF和存储过程很类似,用户自定义函数是一组有序的T-SQL语句,这些语句被预先优化和编译,并且可以作为一个单元来测试调用.UDF和存储过程的主要区别在于结果返回方式,为了能支持更多返回值,UDF比存 ...

  5. Javascrpt无刷新文件上传

    最近工作中遇到上传文件问题,主要需求是一步点击上传,兼容ie8+,当时用的dojox/form/uploader控件,这两天扒了一下源码,明白了原理拿出来分享一下. 总体思路如下: 1.对于支持XML ...

  6. 做NavMesh相关工作时收集的一些文章

    三角形拾取 http://www.blackpawn.com/texts/pointinpoly/default.htmlCS NavMesh使用手册https://developer.valveso ...

  7. 难道只有我一个人想吐槽npm这种包管理方式么

    实在忍不住吐槽 说实话有强迫症的我忍了很久了,实在是忍不住写篇文章来吐槽一下. 标题可能说的有点大了,我要吐槽的是:我可能只需要某一个小小的功能模块A,结果模块A依赖B-F这5个模块,然后B又依赖这1 ...

  8. 使用MYSQL命令直接导入导出SQL文件

    很多时候,我们的数据开发都会用到很多开发利器,比如powerdesigner, navicat等这些软件,虽然好用,但是要收费,在公司里面是禁止使用盗版软件的,怕罚款各方面的,所以我们也不敢直接在公司 ...

  9. ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇

    在之前的文章中,我为大家介绍了OWIN和Katana,有了对它们的基本了解后,才能更好的去学习ASP.NET Identity,因为它已经对OWIN 有了良好的集成. 在这篇文章中,我主要关注ASP. ...

  10. Spring-Context之六:基于Setter方法进行依赖注入

    上文讲了基于构造器进行依赖注入,这里讲解基于Setter方法进行注入.在Java世界中有个约定(Convention),那就是属性的设置和获取的方法名一般是:set+属性名(参数)及get+属性名() ...