剖析NUTCH爬虫

1.    简介 开源项目NUTCH搜索引擎大致包括三个部分: (1)  爬虫:寻找并抓取网页 (2)  网页库:存储已知URL和已抓取网页的数据库 (3)  索引器:解析网页并按照主题字典建立索引 2. NUTCH命令脚本 NUTCH使用多个"bin/nutch"命令脚本进行操作,其中每个脚本命令与一个java类相对应 对于整个网络网页的抓取,你需要利用下面的命令逐步进行: $ bin/nutch admin db -create $ bin/nutch inject db ... $ bin/nutch generate db segments $ bin/nutch fetch ... $ bin/nutch updatedb ... $ bin/nutch analyze .

  每个命令对应的java类如下所示: admin: net.nutch.tools.WebDBAdminTool inject: net.nutch.db.WebDBInjector generate: net.nutch.tools.FetchListTool fetch: net.nutch.fetcher.Fetcher updatedb: net.nutch.tools.UpdateDatabaseTool analyze: net.nutch.tools.LinkAnalysisTool

  3.CRAWL命令:net.nutch.tools.CrawlTool类

  CrawlTool类的作用很好理解,它就是将爬行整个网络的一系列命令操作综合 在一起并加以限制条件实现了局域性网络的爬行。 它主要包括了两个静态函数和一个main函数。下面是操作细节:

  操  作:                对应的函数:

  - start logger:            LogFormatter.getLogger(...)

  - load "crawl-tool.xml" config file:  NutchConf.addConfResource(...)(加载配置文件)

  - read arguments from command-line   (读取命令行参数,如爬行深度等) - create a new web db:          WebDBAdminTool.main(...)(生成一个新网页库)

  - add rootURLs into the db:       WebDBInjector.main(...)(将种子URL写入网页库)

  - for 1 to depth (=5 by default):

  - generate a new segment:      FetchListTool.main(...)

  - fetch the segment:         Fetcher.main(...)

  - update the db:           UpdateDatabaseTool.main(...)(爬行网页并更新网页库)

  - comment:

  "Re-fetch everything to get complete set of incoming anchor texts"

  - delete all old segment data:     FileUtil.fullyDelete(...)(根据网页锚文本爬行链接网页)

  - make a single segment with all pages:FetchListTool.main(...)

  - re-fetch everything:          Fetcher.main(...)

  - index:                 IndexSegment.main(...)

  - dedup:                 DeleteDuplicates.main(...)

  - merge:                 IndexMerger.main(...)

  a

  将以上各步还原为NUTCH命令脚本你就会发现,其实它和爬行整个网络所进行的操作是一码事。

  - (start logger, etc)

  - bin/nutch admin db -create

  - bin/nutch inject db ...

  - (for 1 to depth:)

  - bin/nutch generate ...

  - bin/nutch fetch ...

  - bin/nutch updatedb ...

  - (call net.nutch.FileUtil.fullyDelete(...))

  - bin/nutch generate ...

  - bin/nutch index ...

  - bin/nutch dedup ...

  - bin/nutch merge ...

  如果我们想在自己的程序中使用爬虫功能,那么我们可以将这个类拷贝到我们自己的程序中需要的地方,然后通过

  bin/nutch调用这个类的命令爬行网络,但是,因为实际的爬行抓取功能主要在Fethcer.mian()中实现的, 只通过这个类我们并没有进行什么实质的饿自定义爬行, 而知识调用了Nutch已有的爬行功能.

  接下来的几个命令和命令调用的类,主要是为最核心的fetch工作做准备的, 我们首先来看看以下这些操作,然后集中精力再看fetch类。

  Admin -creat 命令:net.nutch.tools.WebDBAdminTool类 Admin命令的作用主要是对网页库进行管理操作。其命令格式如下:

  java net.nutch.tools.WebDBAdminTool db [-create] [-textdump dumpPrefix] [-scoredump] [-top k]

  其中[-creat]选项的含义就是创建网页库,它通过生成WEBDBWriter对象来完成工作,然后再关闭此对象。

  利用spam作为文件夹执行此命令,执行后生产的网页库物理文件如下所示:

  $ bin/nutch admin spam -create

  $ find spam -type file | xargs ls -l

  -rw-r--r-- 1 kangas users  0 Oct 25 18:31 spam/dbreadlock

  -rw-r--r-- 1 kangas users  0 Oct 25 18:31 spam/dbwritelock

  -rw-r--r-- 1 kangas users 16 Oct 25 18:31 spam/webdb/linksByMD5/data

  -rw-r--r-- 1 kangas users 16 Oct 25 18:31 spam/webdb/linksByMD5/index

  -rw-r--r-- 1 kangas users 16 Oct 25 18:31 spam/webdb/linksByURL/data

  -rw-r--r-- 1 kangas users 16 Oct 25 18:31 spam/webdb/linksByURL/index

  -rw-r--r-- 1 kangas users 16 Oct 25 18:31 spam/webdb/pagesByMD5/data

  -rw-r--r-- 1 kangas users 16 Oct 25 18:31 spam/webdb/pagesByMD5/index

  -rw-r--r-- 1 kangas users 16 Oct 25 18:31 spam/webdb/pagesByURL/data

  -rw-r--r-- 1 kangas users 16 Oct 25 18:31 spam/webdb/pagesByURL/index

  inject命令:net.nutch.db.WebDBInjector类

  此命令的主要作用就是将新的URL写入网页库,命令格式如下:

  WebDBInjector

  WebDBInjector.main() 可以接受两个选择项.我们首先建立spam_url.txt文件, 在文件里面写入一个url,然后运行bin/nutch inject命令。结果如下:

  $ vi spam_url.txt

  $ bin/nutch inject spam -urlfile spam_url.txt

  $ find spam -type file | xargs ls -l

  -rw-r--r-- 1 kangas users  0 Oct 25 18:57 spam/dbreadlock

  -rw-r--r-- 1 kangas users  0 Oct 25 18:57 spam/dbwritelock

  -rw-r--r-- 1 kangas users  16 Oct 25 18:57 spam/webdb/linksByMD5/data

  -rw-r--r-- 1 kangas users  16 Oct 25 18:57 spam/webdb/linksByMD5/index

  -rw-r--r-- 1 kangas users  16 Oct 25 18:57 spam/webdb/linksByURL/data

  -rw-r--r-- 1 kangas users  16 Oct 25 18:57 spam/webdb/linksByURL/index

  -rw-r--r-- 1 kangas users  89 Oct 25 18:57 spam/webdb/pagesByMD5/data

  -rw-r--r-- 1 kangas users  97 Oct 25 18:57 spam/webdb/pagesByMD5/index

  -rw-r--r-- 1 kangas users 115 Oct 25 18:57 spam/webdb/pagesByURL/data

  -rw-r--r-- 1 kangas users  58 Oct 25 18:57 spam/webdb/pagesByURL/index

  -rw-r--r-- 1 kangas users  17 Oct 25 18:57 spam/webdb/stats

  我们可以看到,一个新的state文件生成,并且在文件夹pagesby…中的data/index文件被修改

  Generate命令:net.nutch.tools.FetchListTool类

  此命令的主要作用是为fetch命令的执行做准备,产生其所需的新segments。格式:

  FetchListTool [-refetchonly] [-anchoroptimize linkdb] [-topN N] [-cutoff cutoffscore] [-numFetchers numFetchers] [-adddays numDays]

  FetchListTool 被用于生成一个或者多个segments。那Segmnet是什么呢?

  Segment代表一个网页集合,这个集合中的网页被作为一个小的单元统一地进行抓取和索引。 它里面存储的数据主要有三个类型:

  ·     a "fetchlist": 将要被抓取的网页的名称列表

  ·     the "fetcher output": 被抓取回来的网页的文件集合

  ·     the "index":利用lucene为 the fetcher output 建立的索引 FetchListTool.main()在CrawlTool.main()中被调用,调用时带了两个参数(dir + "/db", dir + "/segments"), 在处理这些参数的基础上返回一个自身的实例对象flt.emitFetchList()。运行此命令,详情如下所示:

  $ bin/nutch generate spam spam_segments

  $ find spam -type file | xargs ls -l

  -rw-r--r-- 1 kangas users  0 Oct 25 20:18 spam/dbreadlock

  -rw-r--r-- 1 kangas users  0 Oct 25 20:18 spam/dbwritelock

  -rw-r--r-- 1 kangas users  16 Oct 25 20:18 spam/webdb/linksByMD5/data

  -rw-r--r-- 1 kangas users  16 Oct 25 20:18 spam/webdb/linksByMD5/index

  -rw-r--r-- 1 kangas users  16 Oct 25 20:18 spam/webdb/linksByURL/data

  -rw-r--r-- 1 kangas users  16 Oct 25 20:18 spam/webdb/linksByURL/index

  -rw-r--r-- 1 kangas users  89 Oct 25 20:18 spam/webdb/pagesByMD5/data

  -rw-r--r-- 1 kangas users  97 Oct 25 20:18 spam/webdb/pagesByMD5/index

  -rw-r--r-- 1 kangas users 115 Oct 25 20:18 spam/webdb/pagesByURL/data

  -rw-r--r-- 1 kangas users  58 Oct 25 20:18 spam/webdb/pagesByURL/index

  -rw-r--r-- 1 kangas users  17 Oct 25 20:18 spam/webdb/stats

  $ find spam_segments/ -type file | xargs ls -l

  -rw-r--r-- 1 kangas users 113 Oct 25 20:18 spam_segments/20041026001828/fetchlist/data

  -rw-r--r-- 1 kangas users  40 Oct 25 20:18 spam_segments/20041026001828/fetchlist/index

  我们可以看到,网页库的文件夹(spam)没有变化,但是segment的文件夹被创建了,里面包括data和index文件。

  下面我们来研究一下fetch操作,在爬虫中,抓取是最主要的操作。

  Fetch命令:net.nutch.fetcher.Fetcher

  此命令的作用就是抓取网页,但是需要注意的是,抓取的单位不是单个的网页, 而是同属于一个segment的网页集合。命令格式:

  Fetcher [-logLevel level] [-showThreadID] [-threads n] dir

  在进行fetch之前,我们已经生成了webdb,在其中初始化写入了URL,并且生成了segment留待写入抓取内容。 我们首先看一下Fetcher类,然后运行一下看其效果。

  net.nutch.fetcher.Fetcher类依靠下面几个类:

  l     FetcherThread, an inner class

  l     net.nutch.parse.ParserFactory

  l     net.nutch.plugin.PluginRepository

  l     and, of course, any "plugin" classes loaded by the PluginRepository

  Fetcher类中的main()函数的功能主要是读取参数,实例化一个Fetcher对象,设置选项,然后调用run()函数。 Fetcher类的构造函数很简单, 它只是实例化了所有的输入输出流:

  Run()函数逐个的实例化抓取线程FetcherThread对象,然后触发各个线程的start()函数, 在其共初始化threadCount个线程并等待线程结束后或者出现大的异常后, 此函数调用close()结束输入输出流。

  FetcherThread是Fetcher类的一个内部类,它继承于java.lang.Thread类,它只有一个实体方法run()和 三个静态函数:handleFetch(), handleNoFetch(), and logError().

  FetcherThread.run()实例化了一个新的FetchListEntry实例名叫”fle”,然后执行以下循环:

  1.   如果出现错误,记录并退出循环

  2.    从FetchList中取得下一个URL集,如果取得结果为空,退出循环

  3.    从FetchListEntry解析出URL

  4.    如果FetchListEntry没有被标记为”fetch”(未抓取此URL的网页), 那么调用this.handleNoFetch()函数,设置status=1。然后逐步执行:

  a     取得此URL的MD5摘要

  b     建立FetcherOutput(fle, hash, status)

  c     建立空的Content、ParseText和 ParseData对象

  d     利用这些对象调用Fetcher.outputPage()函数

  5.   如果标记为”fetch”(已抓取此URL的网页),调用ProtocolFactory并取得符合此URL的协议和内容对象。

  6.    调用Call this.handleFetch(url, fle, content).然后逐步执行:

  a     调用符合此内容类型的ParserFactory.getParser()

  b     执行parser.getParse(content)

  c     利用新建立的FetcherOutput和URL的MD5摘要,产生的内容对象和 已解析的ParseText调用Fetcher.outputPage()函数

  7.    循环100次,在log中记录


  8.    扑捉各种小的异常以及记录写入log文件

  我们可以看出,Fetcher利用Factory类来选择合适的code去处理不同的内容类型:ProtocolFactory()获取URL的协议类型, ParserFactory 根据文件类型进行合适的内容解析。

  我们可以看出,如果我们想对nutch爬虫进行功能上的扩充,比方说增加可抓取的web资源类型,如PDF什么的, 我们就可以通过对ProtocolFactory和ParserFactory的扩充来进行实现。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值