一、簡介
在本教程中,我們將了解Apache Nutch 。我們將了解它是什麼、我們可以用它做什麼以及如何使用它。
Apache Nutch 是現成的網路爬蟲,我們可以開箱即用,並且與 Apache 生態系統中的其他工具集成,例如 Apache Hadoop 和 Apache Solr。
2. 設定Nutch
在開始使用 Nutch 之前,我們需要下載最新版本。我們可以在https://nutch.apache.org/download/找到它並下載最新的二進位版本,在撰寫本文時為 1.20。下載後,我們需要將其解壓縮到適當的目錄中。
解壓縮後,我們需要設定 Nutch 造訪其他網站時將使用的使用者代理程式。我們透過編輯conf/nutch-site.xml來做到這一點:
這將配置 Nutch,以便檢索文件的所有 HTTP 請求都使用用戶代理的MyNutchCrawler值。顯然,此處使用的確切值取決於我們正在設定的爬網程式設定。
3. 爬行我們的第一個網站
現在我們已經安裝了 Nutch,我們已經準備好抓取我們的第一個 URL。 Nutch 中的抓取過程由幾個階段組成,這使我們在必要時具有很大的靈活性。
我們使用bin/nutch命令列工具來管理整個過程。該工具允許我們執行 Nutch 套件的各個部分。
3.1.注入種子 URL
在抓取任何 URL 之前,我們首先需要播種一些基本 URL。為此,我們創建一些包含 URL 的文本文件,然後使用inject命令將它們注入到我們的爬網資料庫中:
$ mkdir -p urls
$ echo https://www.baeldung.com > urls/seed.txt
$ bin/nutch inject crawl/crawldb urls
這會將 URL https://www.baeldung.com 注入到我們的爬網資料庫中,該資料庫將為crawl/crawldb 。因為這是我們的第一個 URL,所以這也將從頭開始建立爬網資料庫。
讓我們檢查資料庫中的 URL 以確保:
$ bin/nutch readdb crawl/crawldb -dump crawl/log
$ cat crawl/log/part-r-00000
https://www.baeldung.com/
Version: 7
Status: 1 (db_unfetched)
Fetch time: Sat May 18 09:31:09 BST 2024
Modified time: Thu Jan 01 01:00:00 GMT 1970
Retries since fetch: 0
Retry interval: 2592000 seconds (30 days)
Score: 1.0
Signature: null
Metadata:
在這裡,我們看到我們有一個 URL 並且它從未被獲取過。
3.2.生成爬網段
爬網過程的下一步是產生一個段,我們將在其中建立爬網資料。這是使用generate指令完成的,告訴它我們的爬網資料庫在哪裡以及在哪裡建立段:
$ bin/nutch generate crawl/crawldb crawl/segments
.....
2024-05-18 09:48:00,281 INFO oancGenerator [main] Generator: Partitioning selected urls for politeness.
2024-05-18 09:48:01,288 INFO oancGenerator [main] Generator: segment: crawl/segments/20240518100617
2024-05-18 09:48:02,645 INFO oancGenerator [main] Generator: finished, elapsed: 3890 ms
在本例中,我們剛剛產生了一個位於crawl/segments/20240518100617.段名稱始終是當前時間戳,這意味著它們始終是唯一的且遞增的。
預設情況下,這將為每個準備獲取的 URL 產生分段數據,包括我們從未取得或取得間隔已過期的每個 URL。
如果需要,我們可以使用-topN參數為一組有限的 URL 產生資料。這將限制抓取階段僅獲取那麼多 URL:
$ bin/nutch generate crawl/crawldb crawl/segments -topN 20
此時,讓我們查詢該段,看看它是什麼樣子的:
$ bin/nutch readseg -list crawl/segments/20240518100617
NAME
GENERATED
FETCHER START
FETCHER END
FETCHED
PARSED
20240518100617
1
?
?
?
?
這告訴我們,我們已經獲得了一個 URL,但尚未獲得任何內容。
3.3.取得和解析 URL
產生抓取分段後,我們就可以取得 URL。我們使用fetch命令來執行此操作,將其指向需要獲取的段:
$ bin/nutch fetch crawl/segments/20240518100617
該命令將啟動獲取器,運行多個並發線程來獲取所有未完成的 URL。
讓我們再次查詢該段落以查看發生了什麼變化:
$ bin/nutch readseg -list crawl/segments/20240518100617
NAME
GENERATED
FETCHER START
FETCHER END
FETCHED
PARSED
20240518100617
1
2024-05-18T10:11:16
2024-05-18T10:11:16
1
?
現在,我們可以看到我們實際上已經取得了 URL,但尚未解析它。我們使用parse命令來執行此操作,再次將其指向剛剛獲取的段:
$ bin/nutch parse crawl/segments/20240518100617
完成後,我們將查詢我們的段落並看到 URL 現在已解析:
$ bin/nutch readseg -list crawl/segments/20240518100617
NAME
GENERATED
FETCHER START
FETCHER END
FETCHED
PARSED
20240518100617
1
2024-05-18T10:11:16
2024-05-18T10:11:16
1
1
3.4.更新爬網資料庫
我們的爬網過程的最後一步是更新我們的爬網資料庫。到目前為止,我們已經獲取了 URL 集並對其進行了解析,但尚未對這些資料執行任何操作。
更新我們的爬網資料庫會將我們解析的 URL 合併到我們的資料庫中,包括實際的頁面內容,但它也會注入任何發現的 URL,以便下一輪爬網將使用它們。我們使用updatedb命令來實現這一點,該命令指向我們的爬行資料庫和我們希望從中更新它的段落:
$ bin/nutch updatedb crawl/crawldb crawl/segments/20240518100617
完成此操作後,我們的資料庫將使用所有抓取結果進行更新。
讓我們再檢查一次它的樣子:
$ bin/nutch readdb crawl/crawldb -stats
2024-05-18 10:21:42,675 INFO oancCrawlDbReader [main] CrawlDb statistics start: crawl/crawldb
2024-05-18 10:21:44,344 INFO oancCrawlDbReader [main] Statistics for CrawlDb: crawl/crawldb
2024-05-18 10:21:44,344 INFO oancCrawlDbReader [main] TOTAL urls:
59
.....
2024-05-18 10:21:44,352 INFO oancCrawlDbReader [main] status 1 (db_unfetched):
58
2024-05-18 10:21:44,352 INFO oancCrawlDbReader [main] status 2 (db_fetched):
1
2024-05-18 10:21:44,352 INFO oancCrawlDbReader [main] CrawlDb statistics: done
在這裡,我們看到資料庫中現在有 59 個 URL,我們已取得其中一個,還有 58 個尚未取得。
3.5.產生反向連結資料庫
除了更新爬行資料庫之外,我們還可以維護一個反向連結資料庫。
到目前為止,我們的抓取資料包括我們抓取的所有頁面,以及每個頁面的一組「外鏈」 - 每個頁面都連結到的頁面。
除此之外,我們還可以為每個爬行的頁面產生一個「內連結」資料庫,也就是連結到該頁面的一組頁面。為此,我們使用invertlinks命令,指向我們的連結資料庫和我們希望包含的段落:
$ bin/nutch invertlinks crawl/linkdb crawl/segments/20240518100617
請注意,此“inlinks”資料庫僅包含跨域鏈接,因此它將僅包含來自不同域的從一個頁面到另一個頁面的任何鏈接。
3.6.再次爬行
現在我們已經抓取了一頁並發現了 58 個新 URL,我們可以再次運行整個過程並抓取所有這些新頁面。我們透過重複之前執行的過程來做到這一點,從產生新段開始,一直到用它更新我們的爬網資料庫:
$ bin/nutch generate crawl/crawldb crawl/segments
$ bin/nutch fetch crawl/segments/20240518102556
$ bin/nutch parse crawl/segments/20240518102556
$ bin/nutch updatedb crawl/crawldb crawl/segments/20240518102556
$ bin/nutch invertlinks crawl/linkdb crawl/segments/20240518102556
不出所料,這次獲取過程花了更長的時間。這是因為我們現在取得的 URL 比以前多得多。
如果我們再次查詢爬網資料庫,我們會看到現在取得了更多資料:
$ bin/nutch readdb crawl/crawldb -stats
2024-05-18 10:33:15,671 INFO oancCrawlDbReader [main] CrawlDb statistics start: crawl/crawldb
2024-05-18 10:33:17,344 INFO oancCrawlDbReader [main] Statistics for CrawlDb: crawl/crawldb
2024-05-18 10:33:17,344 INFO oancCrawlDbReader [main] TOTAL urls:
900
.....
2024-05-18 10:33:17,351 INFO oancCrawlDbReader [main] status 1 (db_unfetched):
841
2024-05-18 10:33:17,351 INFO oancCrawlDbReader [main] status 2 (db_fetched):
52
2024-05-18 10:33:17,351 INFO oancCrawlDbReader [main] status 3 (db_gone):
1
2024-05-18 10:33:17,351 INFO oancCrawlDbReader [main] status 4 (db_redir_temp):
1
2024-05-18 10:33:17,351 INFO oancCrawlDbReader [main] status 5 (db_redir_perm):
5
2024-05-18 10:33:17,351 INFO oancCrawlDbReader [main] CrawlDb statistics: done
現在我們總共有 900 個 URL,其中我們取得了 52 個。其中一些是圖像、JSON 檔案或 Nutch 無法立即解析的其他資源。
現在我們可以按照我們希望的節奏重複這個過程。
4. 限制域名
到目前為止,我們的爬蟲程式遇到的一個問題是,它會追蹤任何 URL,無論它們去了哪裡。例如,如果我們從爬網資料庫轉儲 URL 清單(即我們已取得的 URL 或下一輪將要存取的 URL),那麼我們將看到有 60 個不同的主機,包括:
www.baeldung.com
courses.baeldung.com
github.com
www.linkedin.com
根據我們想要的結果,這可能不太好。如果我們想要一個能夠掃描整個網路的通用網路爬蟲,那麼這是理想的選擇。如果我們只想掃描單一站點或一組站點,那麼這是有問題的。
有用的是,Nutch 有一個專門針對這種情況的內建機制。我們可以配置一組正規表示式來包含或排除 URL。這些可以在conf/regex-urlfilter.txt檔案中找到。
該文件中的每個非註解行都是一個正規表示式,前綴為“-”(表示排除)或“+”(表示包含)。如果到達文件末尾沒有匹配項,則該 URL 將被排除。
我們將看到最後一行目前是“ +. 」。這將包括之前任何規則均未排除的每個 URL。
如果我們將此行更改為“ +^https?://www\.baeldung\.com ”,那麼現在將只匹配以 http://www.baeldung.com 或 https:// 開頭的 URL www.baeldung .com。
請注意,我們無法追溯應用這些規則。只有在配置後發生的爬網才會受到影響。但是,如果我們刪除所有爬網資料並使用這些規則重新開始,則經過兩次之後,我們最終會得到:
$ bin/nutch readdb crawl/crawldb -stats
2024-05-18 17:57:34,921 INFO oancCrawlDbReader [main] CrawlDb statistics start: crawl/crawldb
2024-05-18 17:57:36,595 INFO oancCrawlDbReader [main] Statistics for CrawlDb: crawl/crawldb
2024-05-18 17:57:36,596 INFO oancCrawlDbReader [main] TOTAL urls:
670
.....
2024-05-18 17:57:36,607 INFO oancCrawlDbReader [main] status 1 (db_unfetched):
613
2024-05-18 17:57:36,607 INFO oancCrawlDbReader [main] status 2 (db_fetched):
51
2024-05-18 17:57:36,607 INFO oancCrawlDbReader [main] status 4 (db_redir_temp):
1
2024-05-18 17:57:36,607 INFO oancCrawlDbReader [main] status 5 (db_redir_perm):
5
2024-05-18 17:57:36,607 INFO oancCrawlDbReader [main] CrawlDb statistics: done
我們總共獲得了 670 個 URL,而不是 900 個。
5. 使用 Solr 建立索引
一旦我們獲得了抓取數據,我們就需要能夠使用它。顯而易見的方法是使用搜尋引擎進行查詢,Nutch 提供了與 Apache Solr 整合的標準支援。
首先,我們需要一個Solr伺服器來使用。如果我們尚未安裝, Solr 快速入門指南將向我們展示如何安裝。
一旦我們得到了這個,我們需要建立一個新的 Solr 集合來將我們爬行的網站索引到:
# From the Solr install
$ bin/solr create -c nutch
完成此操作後,我們需要配置 Nutch 以了解這一點。我們透過在 Nutch 安裝中向conf/nutch-site.xml檔案添加一些配置來實現此目的:
storage.data.store.class設定配置要使用的儲存機制, solr.server.url設定配置我們要將爬網資料索引到的 Solr 集合的 URL。
此時,我們可以使用index指令對我們的爬取資料進行索引:
# From the Nutch install
bin/nutch index crawl/crawldb/ -linkdb crawl/linkdb/ crawl/segments/20240518100617 -filter -normalize -deleteGone
2024-05-19 11:12:12,502 INFO oanisSolrIndexWriter [pool-5-thread-1] Indexing 1/1 documents
2024-05-19 11:12:12,502 INFO oanisSolrIndexWriter [pool-5-thread-1] Deleting 0 documents
2024-05-19 11:12:13,730 INFO oaniIndexingJob [main] Indexer: number of documents indexed, deleted, or skipped:
2024-05-19 11:12:13,732 INFO oaniIndexingJob [main] Indexer: 1 indexed (add/update)
2024-05-19 11:12:13,732 INFO oaniIndexingJob [main] Indexer: finished, elapsed: 2716 ms
每次進行爬網時,我們都需要在剛剛為該爬網產生的段上執行此命令。
完成此操作後,我們現在可以使用 Solr 查詢索引資料:
在這裡,我們可以看到,在爬行資料中搜尋標題包含「Spring」的任何頁面已返回 19 個文件。
6. 自動化抓取流程
到目前為止,我們已經成功抓取了我們的網站。然而,要實現這一結果需要採取許多步驟。
值得慶幸的是, Nutch 附帶了一個腳本,可以自動為我們完成所有這些工作 – bin/crawl 。我們可以使用它以正確的順序執行所有步驟,每次都獲得正確的段 ID,並根據需要運行該過程任意多輪。這還可以包括在開始時注入種子 URL 並在每輪之後將結果發送到 Solr。
例如,要運行我們剛剛描述的整個過程兩輪,我們可以執行:
$ ./bin/crawl -i -s urls crawl 2
讓我們分解一下命令:
“-i”告訴它在我們配置的搜尋索引中索引爬行的資料。
“-s urls”告訴它在哪裡可以找到我們的種子 URL。
“crawl”告訴它在哪裡儲存我們的爬行資料。
“2”告訴它要運轉的爬行輪數。
如果我們在乾淨的 Nutch 安裝上運行它 – 首先配置了conf/nutch-site.xml和conf/regex-urlfilter.txt檔案 – 那麼最終結果將與我們運行之前的所有步驟完全相同手。
七、結論
我們在這裡看到了 Nutch 的介紹,如何設定它並抓取我們的第一個網站,以及如何將資料索引到 Solr 中以便我們可以搜尋它。然而,這只是我們使用 Nutch 可以實現的目標的表面,所以為什麼不自己探索更多呢?