之前對nutch進行些分析,打算在基礎上進行一些應用,不過最近忙着,也沒弄出個所以然,先把閱讀心得貼出來,裏邊可能有不少理解上的錯誤,僅供參考用,萬一突然有人轉載了,請保留blog出處 。也希望能認識跟多對此話題感興趣的朋友。
主要類分析:
一、org.apache.nutch.crawl.Injector:
1,注入url.txt
2,url標準化
3,攔截url,進行正則校驗(regex-urlfilter.txt)
4,對符URL標準的url進行map對構造<url, CrawlDatum>,在構造過程中給CrawlDatum初始化得分,分數可影響url host的搜索排序,和採集優先級!
5,reduce只做一件事,判斷url是不是在crawldb中已經存在,如果存在則直接讀取原來CrawlDatum,如果是新host,則把相應狀態存儲到裏邊(STATUS_DB_UNFETCHED(狀態意思爲沒有采集過))
二、org.apache.nutch.crawl.Generator:
1,過濾不及格url (使用url過濾插件)
2,檢測URL是否在有效更新時間裏
3,獲取URL metaData,metaData記錄了url上次更新時間
4,對url進行打分
5,將url載入相應任務組(以host爲分組)
6,計算url hash值
7,收集url, 直至到達 topN 指定量
三、org.apache.nutch.crawl.Fetcher:
1,從segment中讀取<url, CrawlDatum>,將它放入相應的隊列中,隊列以queueId爲分類,而queueId是由 協議://ip 組成,在放入隊列過程中,
如果不存在隊列則創建(比如javaeye的所有地址都屬於這個隊列:http://221.130.184.141) --> queues.addFetchItem(url, datum);
2,檢查機器人協議是否允許該url被爬行(robots.txt) --> protocol.getRobotRules(fit.url, fit.datum);
3,檢查url是否在有效的更新時間裏 --> if (rules.getCrawlDelay() > 0)
4,針對不同協議採用不同的協議採用不同機器人,可以是http、ftp、file,這地方已經將內容保存下來(Content)。 --> protocol.getProtocolOutput(fit.url, fit.datum);
5,成功取回Content後,在次對HTTP狀態進行識別(如200、404)。--> case ProtocolStatus.SUCCESS:
6,內容成功保存,進入ProtocolStatus.SUCCESS區域,在這區域裏,系統對輸出內容進行構造。 --> output(fit.url, fit.datum, content, status, CrawlDatum.STATUS_FETCH_SUCCESS);
7,在內容構造過程中,調取內容解析器插件(parseUtil),如mp3\html\pdf\word\zip\jsp\swf……。 --> this.parseUtil.parse(content); --> parsers[i].getParse(content);
8,我們現在研究html解析,所以只簡略說明HtmlParser,HtmlParser中,會解析出text,title, outlinks, metadata。
text:過濾所有HTML元素;title:網頁標題;outlinks:url下的所有鏈接;metadata:這東西分別做那麼幾件事情 首先檢測url頭部的meta name="robots" 看看是否允許蜘蛛爬行,
其次通過對meta http-equiv
refresh等屬性進行識別記錄,看頁面是否需要轉向。
四、org.apache.nutch.parse.ParseSegment:
1,這個類邏輯就相對簡單很多了哦,它對我們也是很有價值的,它只做一件事情,就是對爬行下來的Content(原始HTML)進行解析,具體解析通過插件來實現。
比如我們要做的數據分析、數據統計都可以在這進行實現。
2,執行完成後,輸出三個Map對<url,ParseText>解析內容、<url,ParseData>包含所有鏈接的分析後的結果 、<url,CrawlDatum>outlinks
五、org.apache.nutch.crawl.CrawlDb:
主要根據crawld_fatch輸出更新crawldb。
1,map對crawld_fatch、crawldb地址進行標準化(nomalizer)和攔截操作(filte);
2,reduce在對兩crawld_fatch和crawldb進行合併更新。
六、org.apache.nutch.crawl.LinkDb:
這個類的作用是管理新轉化進來的鏈接映射,並列出每個url的外部鏈接(incoming links)。
1,先是對每一個url取出它的outLinks,作map操作把這個url作爲每個outLinks的incoming link,
2,在reduce裏把根據每個key來把一個url的所有incoming link都加到inlinks裏。
3,這樣就把每個url的外部鏈接統計出來了,注意,系統對只對外部鏈接進行統計,什麼叫外部鏈接呢,就是隻對不同host進行統計,
記住iteye.com和biaowen.iteye.com是兩個不同的host哦。 --> boolean ignoreInternalLinks = true;
4,然後一步是對這些新加進來的鏈接進行合併。
七、org.apache.nutch.crawl.Indexer:
這個類的任務是另一方面的工作了,它是基於hadoop和lucene的分佈式索引。它就是爲前面爬蟲抓取回來的數據進行索引好讓用戶可以搜索到這些數據。
這裏的輸入就比較多了,有segments下的fetch_dir,parseData和parseText,還有crawldb下的 current_dir和linkdb下的current_dir。
1,在這個類裏,map將所有輸入都裝載到一個容器裏邊,
2,在到reduce進行分類處理,
3,實現攔截 --> this.filters.filter(doc, parse, key, fetchDatum, inlinks);
4,打分 --> this.scfilters.indexerScore(key, doc, dbDatum,fetchDatum, parse, inlinks, boost);
5,當然要把這些數據體組合成一個 lucene的document讓它索引了。
6,在reduce裏組裝好後收集時是<url,doc>,最後在輸出的OutputFormat類裏進行真正的索引。
doc裏有如下幾個field
content(正文)
site (所屬主地址)
title (標題)
host (host)
segement (屬於哪個segement)
digest (MD5碼,去重時候用到)
tstamp (暫時不知道什麼東西)
url (當前URL地址)
載了一個例子:
doc =
{content=[biaowen - JavaEye技術網站 首頁 新聞 論壇 博客 招聘 更多 ▼ 問答 ………………(內容省略)………… biaowen 永NF/ICP備05023328號],
site=[biaowen.iteye.com],
title=[biaowen - JavaEye技術網站],
host=[biaowen.iteye.com],
segment=[20090725083125],
digest=[063ba8430fa84e614ce71276e176f4ce],
tstamp=[20090725003318265],
url=[http://biaowen.iteye.com/]}
八、org.apache.nutch.crawl.DeleteDuplicates:
這個類的作用就是這它的名字所寫的意思--去重。
前面索引後(當然不是一次時的情況)會有重複,所以要去重。爲什麼呢,在一次索引時是不重複的,可是多次抓取後就會有重複了。
就是這個原因纔要去重。當然去重的規則有兩種一個是以時間爲標準,一種是以內容的md5值爲標準。
九、org.apache.nutch.indexer.IndexMerger:
這個類就相對簡單了,目的將多個indexes合併爲一個index,直接調用lucene方法實現!
附帶些參考資料:
目錄結構,參考自《Lucene+Nutch搜索引擎開發》
一、crawldb 下載的url,以及下載日期,用來進行頁面更新
二、segements 存放抓取頁面和分析結果
1、crawl_generate:待下載url
2、crawl_fetch:每個下載url的狀態
3、content:每個下載頁面的內容
4、parse_text:包含每個解析過的url文本內容
5、parse_data:每個url解析出的外部鏈接和元數據
6、crawl_parse:用來更新crawl的外部鏈接庫
三、linkdb 存放url的互聯關係
四、indexes:存放每次下載的獨立索引目錄
五、index:符合lucene格式的索引目錄,是indexes裏所有index合併後的完整索引