我的家園

          我的家園

          Nutch 源代碼分析(1) Crawl 類

          Posted on 2012-04-15 16:27 zljpp 閱讀(321) 評論(0)  編輯  收藏
           ?。ㄒ韵路治鲠槍Φ氖?nutch 1.4)

            Crawl 類是運行抓取程序的入口,代碼不多,但關(guān)聯(lián)的其他類不少。
            抓取的流程是:

            1. 將初始的 URL 地址注入到 crawlDb

            2. 從crawldb中生成一個url的子集用于抓取
            3. 抓取網(wǎng)頁
            4. 分析網(wǎng)頁
            5. 更新 crawlDb ,增加新抓取的 url

            6. 循環(huán)執(zhí)行 2-5 步,直到達到指定的抓取深度

            之后,還需要進行鏈接反轉(zhuǎn),將索引導入到 solr 等。

            Crawl 類的聲明如下:
          public class Crawl extends Configured implements Tool
          

            Configured 和 Tool 是 hadoop 中的概念
            Configured 是 hadoop 中用來提供配置信息的,在 ToolRunner.run 方法中,會將創(chuàng)建好的 Configuration 對象通過 Configured.setConf 方法注入到 Crawl 中。
            Tool 是 hadoop 中用來處理命令行參數(shù)并修改 Map-Reduce 任務(wù)的參數(shù),它需要在 run 方法中處理這些命令行參數(shù)。

            因為 Crawl 實現(xiàn)了 Tool 接口,我們可以通過命令行啟動數(shù)據(jù)抓取的 Map-Reduce 任務(wù)。
            啟動 Crawl 的 main 方法如下:
            public static void main(String args[]) throws Exception {
              // 創(chuàng)建 Configuration  對象
              Configuration conf = NutchConfiguration.create();
          
              // 執(zhí)行任務(wù)
              int res = ToolRunner.run(conf, new Crawl(), args);
          
              // 退出程序
              System.exit(res);
            }
          

            NutchConfiguration.create 會加載 nutch-default.xml 和 nutch-site.xml 中的配置信息生成 Configuration  對象。
            ToolRunner.run 方法會將創(chuàng)建好的 Configuration 對象通過 Configured.setConf 方法注入到 Crawl 中(Crawl 繼承了Configured),并將參數(shù)的處理委托給 Tool.run 方法(Crawl 實現(xiàn)了 Tool 接口,因此需要提供 run 方法的實現(xiàn))。
            接下來我們重點分析一下 Crawl 類的 run 方法。

            首先是參數(shù)的設(shè)置:
              // 默認參數(shù)
              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;
          

            這幾個參數(shù)的含義如下:

            rootUrlDir : 要抓取的起始 url 所在的目錄
            dir : 默認情況下,抓取時生成的文件的目錄
            threads : 抓取數(shù)據(jù)的線程數(shù)
            depth : 通過外鏈抓取網(wǎng)頁的深度,從起始 url 算起
            topN : 每輪抓取獲得的新的 url 中,只對分值最高的 topN 個 url 再次抓取
            solrUrl : solr 的地址。用于調(diào)用 solr 的 api 建立用于搜索的索引。


            這些參數(shù)是可以根據(jù)命令行的輸入修改的:
              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]);
                }
              }
          


            然后需要創(chuàng)建抓取程序?qū)⒁玫降膶ο螅?
              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 : 抓取網(wǎng)頁
            parseSegment : 分析網(wǎng)頁
            crawlDbTool : CrawlDb 類的實例,存放將要抓取的 URL
            linkDbTool : 用于存放鏈接之間的引用關(guān)系,便于計算權(quán)重


            完成以上的準備工作之后,就開始執(zhí)行主要的處理邏輯:
              // 初始化 crawlDb
              // 將初始的 URL 地址到 crawlDb 
              injector.inject(crawlDb, rootUrlDir);
          
              int i;
          
              // 循環(huán)執(zhí)行,直到達到指定的抓取深度
              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);  // 抓取網(wǎng)頁
          
                if (!Fetcher.isParsing(job)) {
                  parseSegment.parse(segs[0]);    // 分析網(wǎng)頁
                }
                crawlDbTool.update(crawlDb, segs, true, true); // 更新 crawldb,增加需要抓取的 URL
              }
          

            前面通過抓取和分析網(wǎng)頁得到的鏈接格式為 源鏈接 => 目標鏈接,
            需要通過反轉(zhuǎn),得到目標鏈接對應(yīng)的源鏈接,以便于計算目標鏈接的權(quán)重等:
            linkDbTool.invert(linkDb, segments, true, true, false);
          

            最后,如果指定了 solrUrl,需要將 nutch 索引導入到 solr 中
                // 將索引導入到 solr
                if (solrUrl != null) {
          
                  // 獲取創(chuàng)建好的 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




          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導航:
           
          主站蜘蛛池模板: 威海市| 九龙坡区| 大方县| 交城县| 翼城县| 淳化县| 法库县| 璧山县| 龙胜| 泰州市| 遵义县| 西吉县| 嘉义市| 金昌市| 肥东县| 饶阳县| 乌拉特前旗| 永川市| 崇义县| 涿鹿县| 泽普县| 平舆县| 柏乡县| 惠东县| 辉南县| 雷山县| 九江县| 舟曲县| 龙门县| 图片| 鄢陵县| 中西区| 吕梁市| 安乡县| 庆阳市| 邢台县| 静乐县| 蛟河市| 西丰县| 辽宁省| 绥棱县|