Đánh giá Apache Nutch: Bốn ranh giới quyết định nó có chạy được không và tìm thấy gì

Cập nhật lần cuối vào August 14, 2026
Đánh giá Apache Nutch: Bốn ranh giới quyết định nó có chạy được không và tìm thấy gì
Tóm tắt bằng AI
Apache Nutch là một trình thu thập dữ liệu của Apache Software Foundation, với quá trình phát triển bắt đầu từ năm 2004. Đây là một hệ thống JVM xây dựng trên Hadoop, hoạt động theo kiểu vòng lặp chứ không phải một lệnh streaming đơn lẻ: các URL hạt giống được inject vào một cơ sở dữ liệu bền vững, sau đó là các vòng generate → fetch → parse → updatedb, với plugin cho protocol, parser, bộ lọc URL và scoring. Đầu ra thông thường được đẩy vào search index như Solr hoặc Elasticsearch thay vì CSV. Tôi đã chạy Nutch 1.22 trên một site test nội bộ có kiểm soát — nơi ghi lại mọi request ở phía server, nên kết quả được đánh giá dựa trên những gì server thực sự nhìn thấy chứ không phải những gì crawler tự báo cáo.

Keywords

đánh giá apache nutch, web scraping, mã nguồn mở, benchmark

Content

Apache Nutch là một công cụ thu thập dữ liệu của Apache Software Foundation, với quá trình phát triển bắt đầu từ năm 2004. Đây là một hệ thống chạy trên JVM, xây dựng trên Hadoop và vận hành theo kiểu vòng lặp chứ không phải một lệnh streaming đơn lẻ: các URL hạt giống được inject vào một cơ sở dữ liệu bền vững, sau đó là các vòng generate → fetch → parse → updatedb, kèm theo các “slot” plugin cho protocol, parser, bộ lọc URL và scoring. Đầu ra thông thường sẽ đẩy vào một search index như Solr hoặc Elasticsearch thay vì xuất ra CSV.

Tôi đã chạy Nutch 1.22 trên một site test nội bộ có kiểm soát — nơi ghi lại mọi request ở phía server, nên kết quả được đánh giá dựa trên những gì server thực sự nhìn thấy chứ không phải những gì crawler tự báo cáo. Có bốn ranh giới quyết định toàn bộ quá trình: phiên bản JDK, http.agent.name, phạm vi crawl, và việc parse-js có xuất hiện trong plugin.includes hay không. Toàn bộ chu kỳ được chạy lặp lại nhiều lần với cấu hình đã kiểm thử; chỉ cần đổi JDK hoặc để trống danh tính agent là nó dừng lại trước khi fetch được các trang hữu ích.

Ranh giới JDK xuất hiện trước cả khi crawl bắt đầu. Nutch 1.22 không khởi động được trên JDK 26.0.1 trong môi trường này: job Hadoop đầu tiên chết ở Subject.getSubject() sau khi Java gỡ bỏ đường đi SecurityManager. Nutch đi kèm Hadoop 3.4.2, trong khi bản sửa lỗi chỉ xuất hiện ở Hadoop 3.4.3, bảy ngày sau khi Nutch 1.22 phát hành. Ngoài ra, parse-js đã cải thiện khả năng khôi phục hai literal trong file JavaScript từ 0/2 lên 2/2 mà không cần chạy trình duyệt.

Nutch dùng để làm gì, và không dùng để làm gì

Nutch không phải là scraper. Việc trích xuất trường dữ liệu có cấu trúc không phải nhiệm vụ của nó: nó phát hiện và fetch URL ở quy mô lớn, duy trì một cơ sở dữ liệu bền vững về các URL và trạng thái của chúng (crawldb), rồi giao cho bạn các segment để một công cụ khác biến thành index. Nếu bạn đưa nó một catalog và mong nhận lại bảng tên và giá, thứ bạn nhận được sẽ là crawldb.

Kiến trúc đó giải thích phần lớn những gì diễn ra sau đây. Nutch ra đời trước thời crawler “một binary” phổ biến khoảng hai thập kỷ, và nó được xây cho đúng bài toán mà Hadoop sinh ra để giải quyết: crawl nhiều trang hơn mức một máy có thể chứa. Chạy nó trên laptop để làm một bộ fixture 12 trang cũng giống như thuê tàu chở hàng để chuyển một cái giá sách — rất có ích để hiểu về con tàu, nhưng thật bất công nếu đòi nó có cảm giác “như xe đạp”.

Bản phát hành hiện tại là 1.22, công bố ngày 17/02/2026. Dự án dùng Apache-2.0, repo có 3.272 stars8 open issues tại thời điểm tôi kiểm tra ngày 27/07/2026, và nhánh master được đẩy lên chỉ bốn ngày trước đó. Đây là một dự án vẫn được duy trì, không phải bị bỏ hoang — và đó là góc nhìn đúng cho vấn đề JDK: một cửa sổ đóng gói hơi sớm một tuần, chứ không phải sự lơ là.

Ma trận phiên bản: JDK 24+, Hadoop 3.4.2 và một bản sửa hai dòng

Vướng mắc này là sự tương tác giữa ba phiên bản, và phần duy nhất bạn kiểm soát được là Nutch chạy trên JDK nào. Job Hadoop đầu tiên, trên JDK mặc định của máy chủ, đã chết ngay khi khởi tạo:

java.lang.UnsupportedOperationException: getSubject is not supported
    at java.base/javax.security.auth.Subject.getSubject(Subject.java:277)
    at org.apache.hadoop.security.UserGroupInformation.getCurrentUser(UserGroupInformation.java:588)
    at org.apache.nutch.crawl.Injector.inject(Injector.java:473)

Mã thoát 255. Không fetch được trang nào. bin/nutch inject thậm chí chưa chạm tới mạng — nó khởi tạo một Hadoop LocalJobRunner, Job này hỏi ai là user hiện tại, rồi gọi Subject.getSubject(), mà JEP 486 đã biến thành ngoại lệ bắt buộc khi JDK 24 xóa bỏ hoàn toàn SecurityManager. JDK trên máy của tôi là OpenJDK 26.0.1, đã vượt xa ranh giới đó.

Cách “thoát” truyền thống cũng không còn tác dụng. Thêm -Djava.security.manager=allow, flag từng dùng để kích hoạt lại hành vi cũ, sẽ bị VM từ chối ngay trước khi code của Nutch kịp nạp:

Error occurred during initialization of VM
java.lang.Error: A command line option has attempted to allow or enable the Security
Manager. Enabling a Security Manager is not supported.

Đó là mã thoát 1, và về bản chất thì đây là ngõ cụt — flag đó đã bị gỡ cùng với tính năng.

Nguyên nhân gốc nằm ở phiên bản Hadoop đi kèm Nutch 1.22. Vấn đề getSubject được theo dõi tại HADOOP-19212 và đã được sửa trong Hadoop 3.4.3 và 3.5.0; trong khi đó Nutch 1.22 đi kèm hadoop-common-3.4.2. Nutch 1.22 phát hành ngày 17/02/2026, và Hadoop 3.4.3 ra đời khoảng một tuần sau đó.

Đây cũng không phải là lỗi do thiếu Solr hay Hadoop cluster. Có một giả định khá phổ biến rằng Nutch cần một Hadoop cluster và Solr đang chạy thì mới làm được gì. Thực ra không phải. Chế độ local dùng LocalJobRunner của Hadoop ngay trong tiến trình — không cần HDFS daemon, không cần YARN, không cần cluster. Toàn bộ chu kỳ inject → generate → fetch → parse → updatedb chạy trên một máy duy nhất, không cần cài thêm gì khác. Bức tường JDK hoàn toàn là vấn đề tương thích thư viện đi kèm, và nó chặn bạn trước khi câu hỏi về hạ tầng còn kịp xuất hiện.

Ma trận phiên bản thực tế, với cả ba dòng được đo:

JDK sử dụngLệnhKết quả
OpenJDK 26.0.1bin/nutch injectThất bại, rc=255 — UnsupportedOperationException: getSubject is not supported
OpenJDK 26.0.1bin/nutch inject + -Djava.security.manager=allowThất bại, rc=1 — VM từ chối khởi động
OpenJDK 17.0.20 (LTS)bin/nutch injectHoạt động, rc=0 — Total new urls injected: 1

Cách khắc phục chỉ cần hai lệnh. Cài một JDK LTS và trỏ Nutch về nó:

brew install openjdk@17
export NUTCH_JAVA_HOME=/opt/homebrew/opt/openjdk@17

Đây là bản keg-only nên không đụng tới JDK mặc định của hệ thống. CI của chính Nutch cũng nhắm vào Java 17, và dự án đã công bố rằng 1.22 là bản cuối cùng chạy được trên Java 11 và 1.23 sẽ yêu cầu Java 17. Vì vậy, JDK LTS không phải mẹo chữa cháy — đó chính là cấu hình được hỗ trợ. Sự lệch pha nằm giữa những gì Nutch hỗ trợ và những gì brew install openjdk đưa cho bạn vào năm 2026, và đây là hai câu chuyện khác nhau nhưng va vào nhau ngay ở lệnh đầu tiên.

Từ đây trở đi, mọi thứ đều chạy trên OpenJDK 17.0.20, và toàn bộ chu kỳ sạch sẽ.

Thiết lập, đo đạc: 396 MB và một property chặn mọi thứ

“Cồng kềnh” là từ ai cũng dùng, nhưng nếu không có con số thì nó vô nghĩa. Đây là thứ thực sự nằm trong bản binary Nutch 1.22 sau khi giải nén:

Hạng mụcBản phân phối binary Nutch 1.22
Kích thước sau khi giải nén≈396 MB
Số jar trong lib/188 (≈113 MB)
— trong đó là stack Hadoop đi kèm13
Thư mục plugin78
Số jar trong các thư mục plugin533
File cấu hình35
Script trong bin/2 — crawlnutch

Để so sánh, một crawler Go hiện đại như katana chỉ là một binary khoảng 50 MB, không cần JVM và không cần jar ngoài.

Rồi đến “cửa chặn” mà không ai cảnh báo trước. File nutch-site.xml đi kèm để trống, và http.agent.name mặc định là chuỗi rỗng. Khi để nguyên, lần crawl đầu tiên của tôi không fetch được bất kỳ path nào và log báo:

ERROR Fetcher: No agents listed in 'http.agent.name' property.

Chỉ cần đặt một property đó thôi — không gì khác — là nó bắt đầu fetch bình thường. Khi property để trống, lệnh vẫn hoàn tất nhưng không fetch được trang nào, và log hiện lỗi agent-name ở trên; tức là nó không hề im lặng.

Bộ cấu hình tối thiểu thực tế hóa ra gồm ba thứ: conf/nutch-site.xml (agent name, bộ plugin, scope), conf/regex-urlfilter.txt (giới hạn theo host), và một file URL hạt giống. Con số đó không tệ. Chỉ là nhiều hơn crawler run <url> đúng ba file.

Nó tìm thấy gì: công tắc plugin quan trọng nhất

System diagram: What it found: the plugin toggle that matters

Site test có ba nhóm endpoint được thiết kế khác nhau, và hành vi của Nutch tách rất rõ theo từng nhóm:

  • Nhóm A — các link HTML thông thường (4 trang, cộng thêm một chuỗi sâu 3 link)
  • Nhóm B — các endpoint chỉ tồn tại như literal chuỗi bên trong một file JavaScript được link tới: một cái là đối số của hàm, fetch('/api/js-endpoint-7'), một cái là gán biến, const other = "/api/js-endpoint-8"
  • Nhóm C — một endpoint chỉ xuất hiện sau khi JavaScript chạy và chèn nó vào DOM

Kết quả, dựa trên log hit phía server, lặp lại ba lần:

Cấu hình pluginNhóm A (link HTML)Nhóm B (literal trong file JS)Nhóm C (runtime DOM)
Mặc định đi kèm — parse-(html|tika)4/4 (recall 1.0)0/2 (recall 0.0)chưa chạm tới
Bật parse-jsparse-(html|tika|js)4/4 (recall 1.0)2/2 (recall 1.0)chưa chạm tới

Giống hệt nhau trong cả ba lần lặp. Có tính quyết định.

Điểm tăng ở nhóm B là phần dễ bị đánh giá thấp. Nutch tìm ra cả hai endpoint nhúng trong JavaScript mà không cần chạy browser, nhờ plugin parse-js quét nội dung JavaScript bằng regex. File app.js vẫn được fetch ở cả hai cấu hình — Nutch coi <script src> như một outlink bất kể gì — nên khác biệt hoàn toàn nằm ở việc có đọc nội dung file để tìm các chuỗi trông giống URL hay không. Bật plugin lên, nó bắt được cả hai dạng literal.

Trên fixture này, chế độ mặc định của Nutch và chế độ standard của katana đều chạm được cùng bộ nhóm A, còn Nutch với parse-js và katana với -jc đều chạm được nhóm A và B mà không cần browser. Phiên bản katana và lệnh đầy đủ không được ghi trong bài này, nên kết quả đó chỉ mang tính bối cảnh chứ không phải benchmark sản phẩm nghiêm ngặt.

Nhóm C là trần giới hạn thành thật. Không có cấu hình tĩnh nào chạm tới nó, và điều đó là dễ hiểu: muốn khôi phục một endpoint chỉ tồn tại sau khi script chạy thì bắt buộc phải thực thi script. Tôi có thử thay protocol-http bằng protocol-htmlunit, tức protocol chạy JavaScript bằng Java thuần của Nutch. Nó nạp và chạy mà không bị crash, nhưng trong cùng bộ harness bốn vòng nó chỉ hoàn tất một vòng, chỉ fetch được trang seed và app.js, không chạm được A/B/C, và vòng hai báo 0 records selected for fetching. Đó là một probe bị cấu hình thiếu, không phải phán quyết về năng lực của HtmlUnit. Điều nó chứng minh chỉ hẹp hơn thế: thay một protocol chạy JS vào không phải là thay thế “cắm vào là chạy”, và nhóm C vẫn không chạm tới ở mọi cấu hình tôi thử.

Điều khiển crawl và hành vi khi lỗi

Độ sâu không phải là một flag. Nutch không có --depth 3; độ sâu chính là số vòng generate → fetch → parse → updatedb bạn chạy, vì vòng R sẽ fetch frontier được phát hiện ở vòng R-1. Chuỗi độ sâu của tôi xác nhận điều đó rất rõ:

Số vòng chạyĐường dẫn sâu nhất đạt tới
2/depth/1
3/depth/2
4/depth/3

Rõ ràng và cơ học, nhưng đồng nghĩa độ sâu là số vòng bạn tự quản lý trong script, chứ không phải một tham số.

Giờ đến cái bẫy. Mặc định đi kèm của Nutch là db.ignore.external.links=false, ghép với URL filter thoáng +. — nghĩa là một lần crawl mặc định của Nutch sẽ đi theo link ra ngoài host gốc. Tôi seed một trang có một path nằm trong scope và một link sang hostname khác, và crawl đã fetch host ngoài phạm vi. Hai tín hiệu độc lập xác nhận nhau: crawldb của Nutch ghi trạng thái db_fetched, và bộ đếm request của host kia cũng ghi nhận hit.

Muốn giữ trong phạm vi thì phải bật chủ đích, và cả hai cách đều hoạt động kiểm chứng được:

Cấu hìnhHost ngoài phạm vi trong crawldbHit ở server của host ngoàiCó bị cô lập?
db.ignore.external.links=false (mặc định đi kèm)db_fetched+1Không
db.ignore.external.links=truekhông có0
Rule host trong regex-urlfilter.txt (+^http://127.0.0.1: rồi -.)không có0

Nếu bạn chỉ crawl một site, hãy đặt một trong hai cách này trước lần chạy thật đầu tiên. Một lưu ý về phương pháp: test cụ thể này khá nhạy với tải trên server local, nên ba dòng ở trên đến từ một lần chạy khi không có gì khác chạm vào fixture. Hành vi bản thân nó rất rõ ràng về mặt cơ học và được xác nhận bởi hai tín hiệu độc lập; các giá trị cụ thể ở từng dòng là từ một lần chạy sạch, không phải trung bình của nhiều lần.

Sitemap là một bước riêng. Mức độ “lịch sự” đã bật sẵn — một crawl bình thường đã fetch /robots.txt — nhưng sitemap thì cần lệnh riêng:

Cách tiếp cậnCó request /sitemap.xml không?Endpoint chỉ tồn tại trong sitemap
Một crawl bình thườngchưa bao giờ được request0/2
bin/nutch sitemap, chạy riêng trên crawldbđã được fetch2/2 entry được inject, recall đầy đủ
Chế độ -kf inline của katana, cùng fixture, trên host IPkhông ghi nhận0/2

Đây là mô hình khác với các crawler kéo known files inline, và nó tốn thêm một lệnh, nhưng làm đúng việc đến cùng.

Hai hành vi nhỏ hơn cũng vận hành tốt.

Xử lý lỗi: một lần crawl qua trang có liên kết tới 500 và 404 vẫn hoàn tất đủ các vòng, vẫn fetch đủ bốn trang nhóm A, và ghi nhận từng lỗi riêng biệt:

Response lỗi được liên kết từ trangtrạng thái ghi trong crawldb
500db_unfetched (đủ điều kiện retry)
404db_gone

Không có gì làm nó chệch hướng.

Politeness: với một thread cho mỗi queue, khoảng cách giữa các lần fetch cùng host đi theo đúng cấu hình:

fetcher.server.delayKhoảng cách trung vị giữa các lần fetch cùng host
1.0 second1.009 s (tối thiểu 1.006 s)
0.00.002 s

Nút chỉnh làm đúng như những gì nó nói. Mặc định đi kèm là 5.0 giây, khá thận trọng và, một lần nữa, có lẽ là đúng với một công cụ được thiết kế để crawl các server của người khác.

Cái giá của chế độ batch, tính bằng giây

Mỗi lệnh Nutch là một JVM mới. Chỉ riêng điều này đã chi phối profile thời gian nhiều hơn hầu hết mọi yếu tố khác về việc fetch.

Giai đoạn (mỗi vòng)Trung vị số giây
inject (một lần)1.81
generate3.93
fetch2.82
parse1.78
updatedb1.81
Một vòng hoàn chỉnh12.14

Mức sàn hiệu dụng cho mỗi job — JVM startup cộng khởi tạo Hadoop, đo như phase nhẹ nhất làm việc rất ít — vào khoảng 1.77 giây. Nhân con số đó với bốn lệnh mỗi vòng, cộng thêm inject ban đầu, và bức tranh toàn crawl sẽ như sau:

Công cụCrawl độ sâu 4 của fixture 12 trangTiến trình
Nutchkhoảng 45 giây (tôi đo được 45.8 s và 45.0 s ở hai cấu hình)khoảng 17 lần khởi chạy JVM, hầu như không cái nào thực sự làm việc mạng
katana chế độ standard, cùng fixturekhoảng 13 giâymột tiến trình

Khoảng cách đó không nằm ở tốc độ fetch; cả hai công cụ đều request cùng số ít trang. Nó là vấn đề kiến trúc. Nutch trả một chi phí tiến trình cố định cho mỗi phase vì các phase đó được thiết kế như MapReduce job. Trên một crawl local nhỏ, chi phí thiết lập chiếm ưu thế. Chi phí cố định này có thể trở thành tỷ trọng nhỏ hơn trong job dài hơn, nhưng bài test này không đo đến quy mô mà Nutch và katana giao nhau, cũng không xác định liệu tỷ lệ của chúng có đảo ngược hay không.

Ưu và nhược điểm

Ưu điểm

  • Phát hiện tĩnh mang tính quyết định: nhóm HTML 4/4, chuỗi độ sâu 3/3, giống hệt qua ba lần chạy lặp lại.
  • parse-js khôi phục các endpoint literal trong file JavaScript (2/2) mà không cần browser, bắt được cả dạng đối số hàm lẫn dạng gán biến.
  • Có hai cách kiểm soát phạm vi đã được xác minh và cô lập hoàn toàn crawl (db.ignore.external.links và host rule trong regex-urlfilter).
  • Ingest sitemap bằng bin/nutch sitemap đạt recall đầy đủ 2/2 với các endpoint mà crawl bình thường bỏ sót hoàn toàn.
  • Chịu lỗi tốt: cả 500 và 404 đều được xử lý bằng trạng thái crawldb riêng, crawl vẫn tiếp tục.
  • Trong lần chạy local này, khoảng cách giữa các request cùng host khớp với delay đã cấu hình 1.0 giây; mặc định đi kèm là 5.0 giây.
  • Apache-2.0, vẫn được duy trì, 78 plugin, và crawldb bền vững theo dõi trạng thái từng URL qua các vòng.
  • Chạy được ở local mode mà không cần cluster, không cần HDFS, không cần Solr.

Nhược điểm

  • Không chạy trên JDK 24 trở lên, nơi việc gỡ SecurityManager gây lỗi (tôi đo được thất bại trên 26.0.1) — Hadoop 3.4.2 đi kèm còn trước bản sửa upstream và flag thoát đã không còn, nên pin LTS JDK là điều bắt buộc chứ không phải sở thích.
  • Kích thước sau khi giải nén ≈396 MB, 188 jar thư viện, 78 thư mục plugin, 35 file cấu hình.
  • Mỗi lệnh lại khởi tạo JVM mới nên có ~1.77 s overhead cố định mỗi phase; crawl độ sâu 4 với 12 trang mất ~45 s so với ~13 s của một crawler single-binary trên cùng dữ liệu.
  • Mặc định đi theo link sang host ngoài; muốn giới hạn một site phải bật chủ đích.
  • http.agent.name đi kèm dưới dạng rỗng và fetcher sẽ từ chối chạy cho đến khi bạn đặt giá trị.
  • Không có depth flag — độ sâu là số vòng bạn tự quản lý.
  • Các endpoint chỉ xuất hiện ở runtime DOM không chạm tới được trong mọi cấu hình đã thử, và thay protocol chạy JS vào không phải kiểu cắm là chạy.
  • Tôi chỉ test local mode trên một host với fixture nhỏ. Distributed/HDFS mode, Solr indexing, hostdb, resume, và lịch crawl lại tăng dần nằm ngoài lần kiểm thử này — hãy xem chúng là chưa được kiểm chứng ở đây, không phải được xác nhận.

Ai nên dùng, và ai nên rời đi

Nutch đáng giá khi chính việc crawl mới là phần khó. Nếu bạn đang xây search index, chạy crawl rộng nhiều domain, cần một cơ sở dữ liệu URL bền vững với trạng thái từng URL và logic retry, hoặc dự tính sẽ phân tán công việc sang nhiều máy, đây là hạ tầng đã làm đúng nhiệm vụ đó từ trước khi phần lớn lựa chọn thay thế xuất hiện. Hệ thống plugin cho phép bạn thay đổi hành vi protocol, parser, filter và scoring mà không cần fork. Mặc định politeness khá thận trọng, cho thấy người duy trì đã suy nghĩ rất kỹ về việc làm một “công dân tốt” trên web.

Hãy rời đi nếu bạn muốn dữ liệu có cấu trúc từ chỉ vài trang. Nutch sẽ fetch và parse chúng, rồi trả về crawldb và các segment và mong bạn tự mang theo indexer. Hãy rời đi nếu mục tiêu của bạn là các ứng dụng single-page render phía client — nhóm C không chạm tới trong mọi lần tôi chạy. Hãy rời đi nếu đội của bạn không vận hành JVM, vì bạn sẽ phải thêm Java toolchain, pin một JDK LTS, và 396 MB jar vào một stack hiện giờ không có gì trong số đó. Và nếu workload chỉ là “crawl một site, sâu bốn tầng, mỗi tuần một lần,” bạn sẽ dành nhiều thời gian cho vòng lặp và file cấu hình hơn là chính việc crawl.

Với đa số người đang tìm một scraper, trường hợp cuối cùng mới là trường hợp thực tế. Đó không phải là lời chê Nutch — mà là sự lệch pha giữa công cụ và công việc. Nếu bạn muốn có cái nhìn rộng hơn về thị trường, bài tổng hợp open-source scraperscác dự án GitHub web scraping tốt nhất của chúng tôi sẽ bao phủ kỹ hơn phần “nhẹ” của phổ này.

Các lựa chọn thay thế, bao gồm chỗ đứng của stack của chúng tôi

Trước hết là cách nhìn công bằng: Nutch miễn phí, dùng giấy phép Apache, tự host, và bạn có thể chạy mãi mà không tốn phí theo request. Đó là lợi thế rất thật, và không có gì dưới đây xóa đi điều đó.

Bài đánh giá liên quan: Đánh giá Browsertrix Crawler.

Trong thế giới open-source, so sánh phụ thuộc vào mục tiêu bạn tối ưu. Nếu bạn muốn một framework Python có điều khiển crawl và ưu tiên request-first, Scrapy là một đối sánh gần hơn cho nhiều dự án; bài viết này không đo footprint cài đặt của nó trên cùng tiêu chí. Nếu bạn muốn một crawler Go gọn nhẹ, không cần browser, Colly là một hình thái khác để cân nhắc. Nếu vấn đề của bạn là biến trang thành nội dung sẵn sàng cho LLM thay vì tìm URL, Crawl4AI nhắm tới một tầng khác.

Một dịch vụ quản lý như Thunderbit đưa fetching, rendering và extraction ra sau một API, còn Nutch giữ trạng thái crawl và hạ tầng trong tay bạn. Thunderbit không được chạy trên fixture này, nên đây là so sánh về mô hình sở hữu chứ không phải tuyên bố rằng recall hay hiệu năng trang động là ngang nhau.

Cái được và cái mất nằm ở quyền kiểm soát so với gánh nặng vận hành, và điều đó khá rõ ràng. Nutch cho bạn toàn quyền kiểm soát, crawldb bền vững, khả năng mở rộng theo cụm từ thiết kế, và chi phí biên bằng 0 — đổi lại là một JVM, một pin JDK LTS, 396 MB jar, một vòng lặp theo phase, và lớp indexing của riêng bạn. Một API quản lý cho bạn đầu ra có cấu trúc ngay từ lần gọi đầu và không cần hạ tầng — đổi lại là giá theo lần gọi và ít quyền kiểm soát hơn với frontier crawl. Nếu công việc của bạn là “index 50 triệu trang,” mô hình của Nutch là đúng còn API sẽ vô lý. Nếu công việc của bạn là “lấy record có cấu trúc từ 200 trang sản phẩm trước thứ Năm,” thì ngược lại.

Dùng thử Thunderbit để trích xuất dữ liệu web

Kết luận

Apache Nutch rất đáng đánh giá nếu bạn đang vận hành một crawl liên tục, đa domain và đã có sẵn hạ tầng JVM. Trên fixture này, khả năng phát hiện tĩnh của nó là quyết định qua các lần lặp, parse-js tìm ra cả hai endpoint JavaScript literal, các lỗi vẫn được thể hiện trong crawldb, và khoảng cách request quan sát được khớp với delay đã cấu hình.

Hãy tính đúng chi phí đầu vào. Nutch 1.22 đã thất bại ở đây trên JDK 26.0.1; OpenJDK 17.0.20 là cấu hình LTS đã được xác nhận trong bài đánh giá này, còn Java 21 chưa được thử. Sau đó đặt http.agent.name, xác định rõ phạm vi, và tính tới mức sàn cố định khoảng ~1.77 giây mỗi phase trong lần chạy local nhỏ này. Việc đánh đổi đó có hợp lý hay không phụ thuộc vào thời lượng crawl, độ rộng, và nhu cầu lưu trạng thái bền vững.

Dùng thử Thunderbit để trích xuất dữ liệu web Get Started Free

Câu hỏi thường gặp

Vì sao Apache Nutch báo lỗi "getSubject is not supported"? Trên JDK 24 trở lên, JEP 486 khiến Subject.getSubject() luôn ném lỗi, trong khi Hadoop 3.4.2 đi kèm vẫn còn gọi nó. Vì vậy job Hadoop đầu tiên chết trước khi fetch được bất kỳ trang nào, và đường thoát cũ -Djava.security.manager=allow cũng không còn làm VM khởi động. Hãy dùng cấu hình Java 17 đã được kiểm chứng và đặt NUTCH_JAVA_HOME; Java 21 có thể vẫn được hỗ trợ, nhưng bài đánh giá này không chạy full cycle trên nó.

Tôi nên chạy Nutch 1.22 trên phiên bản Java nào? Java 17 là lựa chọn an toàn nhất — CI của Nutch nhắm vào nó, và nó chạy sạch trong thử nghiệm của tôi trên OpenJDK 17.0.20. Java 11 cũng vẫn được hỗ trợ cho 1.22, dù dự án đã thông báo rằng 1.23 sẽ yêu cầu Java 17. Bất kỳ JDK nào từ 24 trở lên đều sẽ không chạy. Một bản cài Homebrew keg-only (brew install openjdk@17) cùng NUTCH_JAVA_HOME sẽ giữ nguyên JDK mặc định của hệ thống.

Nutch có crawl được site nhiều JavaScript không? Có một phần, và sự khác biệt này rất quan trọng. Khi bật plugin parse-js, Nutch tìm được cả hai endpoint chỉ tồn tại như literal chuỗi trong file JavaScript được link tới — 2/2, không cần browser. Ở bộ plugin mặc định, nó không tìm được endpoint nào trong số đó. Nhưng một endpoint chỉ xuất hiện sau khi JavaScript chạy và sửa DOM thì vẫn không thể chạm tới trong mọi cấu hình tĩnh tôi thử, và việc thay protocol HtmlUnit vào không phải kiểu cắm vào là dùng ngay trong lần chạy của tôi. Với app render phía client, hãy chuẩn bị cho một protocol thực thi JS kèm cấu hình thực sự, hoặc dùng công cụ khác.

Nutch có cần cài Hadoop và Solr không? Không. Chế độ local chạy LocalJobRunner trong tiến trình của Hadoop — không cluster, không HDFS daemon, không YARN — và toàn bộ chu kỳ inject → generate → fetch → parse → updatedb hoạt động trên một máy mà không cần cài thêm gì. Solr là đích index thường gặp, nhưng chính crawl thì không bắt buộc phải có. Tuy nhiên, Hadoop jar được đi kèm (13 jar, phiên bản 3.4.2), và đó chính là lý do vì sao vấn đề tương thích JDK lại tồn tại.

Làm sao để Nutch không crawl sang website khác? Hãy đặt rõ ràng, vì mặc định đi kèm không làm điều đó. Nutch 1.22 ship với db.ignore.external.links=false và URL filter thoáng, và trong test của tôi crawl mặc định đã đi theo link sang host khác rồi fetch nó. Bạn có thể đặt db.ignore.external.links=true trong nutch-site.xml, hoặc thêm rule host vào conf/regex-urlfilter.txt (ví dụ +^https://example\.com/ rồi -.). Cả hai cách đều cô lập crawl hoàn toàn trong thử nghiệm, được xác nhận từ crawldb của Nutch và log request của server còn lại.

Ke
Ke
CTO tại Thunderbit | Chuyên gia Khoa học Dữ liệu cấp cao & ML Với gần một thập kỷ kinh nghiệm trong học máy và khoa học dữ liệu, Ke Shen là cựu sinh viên Đại học Columbia và từng là Chuyên gia Khoa học Dữ liệu cấp cao tại Walmart Labs. Sở hữu chuyên môn sâu về Python, R, Java và Thống kê, được đồng nghiệp công nhận, anh chia sẻ những góc nhìn thực chiến về cách đưa các thuật toán AI phức tạp từ lý thuyết vào kiến trúc sẵn sàng cho môi trường sản xuất.
Mục lục
Thunderbit · Tác nhân dữ liệu web AI

Trích xuất dữ liệu từ bất kỳ trang nào trong 1 lần nhấp

Được hơn 250.000+ người dùng tin tưởng
có gói miễn phí
Từ trang web đến bảng tính
Mô tả điều bạn cần — AI Agent của Thunderbit sẽ cào dữ liệu và xuất ra Excel, Google Sheets, Airtable hoặc Notion. Bắt đầu miễn phí.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week