Apache Nutch は、Apache Software Foundation が開発するクローラーで、開発は 2004 年に始まりました。Hadoop 上で動く JVM ベースのシステムで、単発のストリーミングコマンドではなくループ型の構成になっています。まず seed URL を永続データベースに inject し、その後 generate → fetch → parse → updatedb を何度も回します。さらに、protocol、parser、URL filter、scoring にはプラグインの差し込み口があります。最終的な出力は CSV ではなく、Solr や Elasticsearch のような検索インデックスに流し込むのが一般的です。
私は Nutch 1.22 を、リクエストをサーバー側で全件記録する制御済みのローカルテストサイトに対して実行しました。つまり、結果はクローラーの申告ではなく、サーバーが実際に受け取った内容を基準に判定しています。実行結果を左右した境界は 4 つありました。JDK のバージョン、http.agent.name、クロール範囲、そして plugin.includes に parse-js が含まれているかどうかです。検証した構成では一連のサイクルを繰り返し実行しましたが、JDK を変えるか、agent の識別名を未設定にすると、有用なページを取得する前に止まります。
JDK の境界は、クロール開始前に立ちはだかります。Nutch 1.22 は JDK 26.0.1 では起動しませんでした。最初の Hadoop ジョブが Subject.getSubject() の内部で落ちるのです。Java で SecurityManager の経路が削除されたためです。Nutch に同梱されているのは Hadoop 3.4.2 で、この問題への修正は Nutch 1.22 のリリースから 7 日後に出た Hadoop 3.4.3 に入っています。なお、parse-js はブラウザを実行せずに、JavaScript ファイル内の 2 つの文字列リテラルを 0/2 から 2/2 へ復元できました。
Nutch は何のためのものか、そして何ではないのか
Nutch はスクレイパーではありません。構造化フィールドを抜き出す用途は本職ではなく、URL を大量に発見・取得し、それらの URL と状態を永続的に管理し(crawldb)、その後のインデックス化は別の仕組みに渡します。名前や価格の一覧表を期待してカタログを与えると、返ってくるのは表ではなく crawldb です。
この設計が、以降の話のほとんどを説明しています。Nutch は、単体バイナリ型のクローラーが主流になるより約 20 年前に登場し、Hadoop が得意とする問題、つまり 1 台のマシンに収まらない規模のページをクロールするために作られました。12 ページのテストデータに対してノート PC 上で動かすのは、書棚を動かすのに貨物列車を借りるようなものです。列車の挙動はよく分かりますが、自転車の機動性を期待するのは筋違いです。
現在のリリースは 1.22 で、2026 年 2 月 17 日に公開されました。ライセンスは Apache-2.0。私が 2026 年 7 月 27 日に確認した時点では、リポジトリの星は 3,272、未解決 issue は 8 件で、master にはその 4 日前までに push がありました。これは放置されたプロジェクトではなく、継続的に保守されているものです。だからこそ、JDK 問題は「放置」ではなく、「パッケージングのタイミングが 1 週間早すぎた」と捉えるのが正確です。
バージョン関係の実態:JDK 24+、Hadoop 3.4.2、そして 2 行の修正
この障害は 3 つのバージョンが絡む問題で、ユーザー側で制御できるのは Nutch がどの JDK で動くかだけです。ホストのデフォルト JDK では、最初の Hadoop ジョブが初期化時に落ちました。
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)
終了コードは 255。取得ページ数は 0。bin/nutch inject はネットワークにすら到達しません。内部では Hadoop の LocalJobRunner が立ち上がり、現在のユーザーは誰かを確認します。その過程で Subject.getSubject() を呼びますが、JEP 486 により、JDK 24 で SecurityManager が完全削除された際、この呼び出しは無条件の例外になりました。私のホスト JDK は OpenJDK 26.0.1 で、その変更点のずっと先にあります。
昔の回避策も使えません。旧挙動を再有効化するための -Djava.security.manager=allow を付けても、Nutch のコードが読み込まれる前に VM 側で拒否されます。
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.
これは終了コード 1 で、設計上の行き止まりです。機能の削除に伴い、このフラグもなくなりました。
根本原因は、Nutch 1.22 に同梱されている Hadoop のバージョンにあります。getSubject 問題は HADOOP-19212 として追跡されており、Hadoop 3.4.3 と 3.5.0 で修正済みです。一方、Nutch 1.22 が同梱しているのは hadoop-common-3.4.2 です。Nutch 1.22 の公開は 2026 年 2 月 17 日、その約 1 週間後に Hadoop 3.4.3 が続きました。
これは Solr や Hadoop クラスタ依存の問題でもありません。 Nutch には Hadoop クラスタと稼働中の Solr が必須だと思われがちですが、実際は違います。ローカルモードでは Hadoop のプロセス内 LocalJobRunner が動くだけで、HDFS デーモンも YARN もクラスタも不要です。inject → generate → fetch → parse → updatedb の一連の流れは、他に何も入っていない 1 台のマシンで完結します。JDK の壁は純粋に同梱ライブラリのバージョン問題であり、その手前で止まるため、インフラの議論にすら進めません。
実際のバージョン関係を、3 パターンすべて計測しました。
| 使用 JDK | コマンド | 結果 |
|---|---|---|
| OpenJDK 26.0.1 | bin/nutch inject | 失敗、rc=255 — UnsupportedOperationException: getSubject is not supported |
| OpenJDK 26.0.1 | bin/nutch inject + -Djava.security.manager=allow | 失敗、rc=1 — VM 起動拒否 |
| OpenJDK 17.0.20 (LTS) | bin/nutch inject | 成功、rc=0 — Total new urls injected: 1 |
修正は 2 行のコマンドで済みます。LTS の JDK を入れて、Nutch にそれを向けます。
brew install openjdk@17
export NUTCH_JAVA_HOME=/opt/homebrew/opt/openjdk@17
これは keg-only なので、システムのデフォルトには影響しません。Nutch 自身の CI も Java 17 を対象にしており、プロジェクトは 公開の場で 1.22 が Java 11 で動く最後のリリースで、1.23 からは Java 17 が必要になると案内しています。したがって、LTS JDK は回避策ではなく、正式な構成です。食い違っているのは、Nutch がサポートする環境と、2026 年に brew install openjdk で入るものが違う、という点です。そしてその 2 つが最初のコマンドでぶつかっています。
以降はすべて OpenJDK 17.0.20 で実行しており、サイクル全体は問題なく進みました。
セットアップを数値で見る:396 MB と、すべてを止める 1 つの設定項目
「重い」は誰もが使う形容詞ですが、実測なしでは意味がありません。Nutch 1.22 のバイナリ配布を展開すると、実際には以下の内容になります。
| 項目 | Nutch 1.22 バイナリ配布 |
|---|---|
| 展開後サイズ | 約 396 MB |
lib/ 内の jar | 188 個(約 113 MB) |
| — そのうち同梱 Hadoop スタック | 13 個 |
| プラグインディレクトリ | 78 |
| その中の jar | 533 個 |
| 設定ファイル | 35 |
bin/ 内のスクリプト | 2 個 — crawl と nutch |
規模感の比較として、現代的な Go 製クローラー katana は、JVM も外部 jar もない約 50 MB の単一バイナリで配布されます。
さらに、誰も事前に強調しないゲートがあります。配布版の nutch-site.xml は空で、http.agent.name のデフォルトも空文字です。これを設定しないと、最初のクロールは 0 パス で終わり、ログには次が出ます。
ERROR Fetcher: No agents listed in 'http.agent.name' property.
この 1 項目だけを設定すれば、他はそのままで取得が動きます。空のままだと、コマンドはページを取得せずに終了し、上記の agent 名エラーがログに記録されます。静かに失敗するわけではありません。
最低限必要だった構成要素は 3 つでした。conf/nutch-site.xml(agent 名、プラグインセット、scope)、conf/regex-urlfilter.txt(ホストの範囲指定)、そして seed URL ファイルです。悪い数ではありませんが、crawler run <url> より 3 ファイル多いのは確かです。
何を見つけたか:重要なのはプラグインの切り替え

テストサイトには、意図的に異なる 3 種類のエンドポイントがあり、Nutch の挙動はそれらに対してきれいに分かれました。
- Class A — 通常の HTML リンク(4 ページ、さらに 3 段の深さを持つチェーン)
- Class B — リンクされた JavaScript ファイル内にだけ文字列として存在するエンドポイント。1 つは関数呼び出しの引数
fetch('/api/js-endpoint-7')、もう 1 つは代入const other = "/api/js-endpoint-8" - Class C — JavaScript 実行後に DOM へ差し込まれて初めて存在するエンドポイント
サーバー側のヒットログを基準にした結果は、3 回の反復すべてで同じでした。
| プラグイン構成 | Class A(HTML リンク) | Class B(JS ファイル内リテラル) | Class C(実行時 DOM) |
|---|---|---|---|
配布時デフォルト — parse-(html|tika) | 4/4(再現率 1.0) | 0/2(再現率 0.0) | 未到達 |
parse-js あり — parse-(html|tika|js) | 4/4(再現率 1.0) | 2/2(再現率 1.0) | 未到達 |
3 回とも完全一致でした。決定的です。
見落とされがちなのは Class B の変化です。Nutch は、ブラウザを動かさずに、parse-js プラグインが JavaScript 内容を正規表現で走査することで、JS 内に埋め込まれた 2 つのエンドポイントの両方を見つけました。app.js 自体はどちらの構成でも取得されています。Nutch は <script src> を outlink として扱うためです。したがって差分は、そのファイルの中身を URL らしい文字列の探索対象にするかどうかだけです。プラグインを有効にすると、両方のリテラル形式を拾えます。
このテストでは、Nutch のデフォルト構成と katana の標準モードが同じ Class A に到達し、Nutch の parse-js と katana の -jc はブラウザなしで Class A と B に到達しました。なお、katana のバージョンと完全なコマンドはこの記事では記録していないため、その結果は厳密な製品ベンチマークではなく、文脈としての比較です。
Class C は、静的なプラグイン構成では到達不能でした。これは自然な結果です。スクリプト実行後にだけ現れるエンドポイントを回収するには、実際にスクリプトを実行する必要があるからです。私は protocol-http を Nutch の純 Java JS 実行型プロトコルである protocol-htmlunit に差し替えることも試しました。読み込みと実行はしましたが、同じ 4 ラウンドの枠組みでは 1 ラウンドしか完了せず、取得したのは seed ページと app.js のみ、A/B/C のどれにも到達せず、2 ラウンド目には 0 records selected for fetching と表示されました。これは HtmlUnit の能力を評価するには設定が足りていない試行であって、HtmlUnit そのものへの結論ではありません。ここで分かるのはより限定的で、JS 実行型プロトコルへの差し替えは単純な置換ではない、という点です。そして私が試したすべての構成で、Class C は最後まで未到達でした。
クロール制御と失敗時の挙動
深さはフラグではありません。Nutch に --depth 3 のような指定はなく、深さは実行する generate → fetch → parse → updatedb のラウンド数そのものです。ラウンド R が、ラウンド R-1 で見つけたフロンティアを取得するからです。深さチェーンの検証でも、それがそのまま確認できました。
| 実行ラウンド数 | 到達した最深パス |
|---|---|
| 2 | /depth/1 |
| 3 | /depth/2 |
| 4 | /depth/3 |
挙動はきれいで機械的ですが、深さはパラメータではなく、スクリプト内で管理するループ回数だということになります。
次に落とし穴です。Nutch の配布時デフォルトは db.ignore.external.links=false で、しかも寛容な +. の URL フィルターが付いています。つまり、デフォルトの Nutch クロールは seed ホストの外側へもリンクをたどります。私は 1 つのインスコープのパスと、別ホストへのリンクを含むページを seed にしましたが、クロールは外部ホストも取得しました。2 つの独立した証拠が一致しています。Nutch 自身の crawldb では db_fetched、もう一方のホストのサーバー側カウンタではヒットが記録されました。
スコープ内に収めるには明示的な設定が必要で、次の 2 つの対策はいずれも実際に効きました。
| 構成 | crawldb 内の外部ホスト | 外部ホスト側のヒット数 | 範囲内に収まったか |
|---|---|---|---|
db.ignore.external.links=false (配布時デフォルト) | db_fetched | +1 | いいえ |
db.ignore.external.links=true | なし | 0 | はい |
regex-urlfilter.txt のホストルール(+^http://127.0.0.1: の後に -.) | なし | 0 | はい |
1 つのサイトだけをクロールするなら、最初の本番実行の前にどちらかを設定してください。なお、このテストはローカルサーバーへの負荷に敏感です。そのため、この 3 行はテストデータに他のアクセスが一切ない状態での結果です。挙動自体は機械的に明瞭で、2 つの独立したシグナルでも裏付けられていますが、各行の値は多数回の平均ではなく、きれいな 1 回の実行結果です。
サイトマップは別手順です。politeness は有効で、通常のクロールでも /robots.txt は取得しましたが、サイトマップ自体は専用コマンドが必要です。
| 方法 | /sitemap.xml を要求したか | サイトマップにしか存在しないエンドポイント |
|---|---|---|
| 通常のクロール | 要求されない | 0/2 |
crawldb に対して明示的に実行した bin/nutch sitemap | 取得された | 2/2 エントリが注入され、完全再現 |
katana のインライン -kf known-files モード、同じテストデータ、IP ホスト上 | 記録なし | 0/2 |
known-files をクロール中に取り込むタイプのクローラーとはモデルが違い、コマンドは 1 つ増えますが、やるべきことは完全にこなします。
小さめの挙動も 2 つ確認できました。
エラー処理: ページから 500 と 404 をリンクしたクロールは、全ラウンドを問題なく終え、Class A の 4 ページもすべて取得し、それぞれの失敗を別々に記録しました。
| ページからリンクされた失敗レスポンス | crawldb に記録された状態 |
|---|---|
| 500 | db_unfetched(再試行対象) |
| 404 | db_gone |
途中で崩れることはありませんでした。
politeness: queue あたり 1 スレッドにすると、同一ホスト間の取得間隔は設定値に沿いました。
fetcher.server.delay | 同一ホスト取得間の中央値 |
|---|---|
| 1.0 秒 | 1.009 s(最小 1.006 s) |
| 0.0 | 0.002 s |
設定どおりに動きます。配布時デフォルトは 5.0 秒で、かなり保守的です。見知らぬサーバーをクロールするためのツールとしては、むしろ妥当でしょう。
バッチ処理のコストは何秒か
Nutch の各コマンドは毎回新しい JVM です。この 1 つの事実が、取得処理そのもの以上に時間プロファイルを支配します。
| フェーズ(1 ラウンドあたり) | 中央値(秒) |
|---|---|
inject(1 回のみ) | 1.81 |
generate | 3.93 |
fetch | 2.82 |
parse | 1.78 |
updatedb | 1.81 |
| 1 ラウンド合計 | 12.14 |
実質的な 1 ジョブあたりの下限、つまり JVM 起動と Hadoop 初期化を含む最安の単純処理フェーズは、およそ 1.77 秒 です。これが 1 ラウンド 4 コマンドに掛かり、さらに最初の inject を加えると、全体像はこうなります。
| ツール | 12 ページのテストデータを深さ 4 でクロール | プロセス数 |
|---|---|---|
| Nutch | およそ 45 秒(2 つの構成で 45.8 秒と 45.0 秒を計測) | 約 17 回の JVM 起動で、そのほとんどはネットワーク処理をしていない |
katana standard モード、同じテストデータ | 約 13 秒 | 1 プロセス |
この差は取得スループットの差ではありません。両者とも同じ少数のページを要求しています。違いはアーキテクチャです。Nutch は各フェーズを MapReduce ジョブとして設計しているため、フェーズごとに固定のプロセスコストを払います。小さなローカルクロールでは、そのセットアップコストが支配的になります。ジョブが長くなれば固定コストの比率は下がるはずですが、このテストでは Nutch と katana がどの規模で逆転するのか、あるいは比率が反転するのかまでは測っていません。
長所と短所
長所
- 静的発見が決定的:HTML 系は 4/4、深さチェーンは 3/3、3 回の反復で完全一致。
parse-jsにより、JavaScript ファイル内のリテラル URL をブラウザなしで 2/2 回収。引数形式と代入形式の両方に対応。- クロールを完全に囲い込めることが実証された 2 つの範囲制御(
db.ignore.external.linksとホストルールのregex-urlfilter)。 bin/nutch sitemapにより、通常クロールで取りこぼしたエンドポイントを 2/2 で完全回収。- 障害に強い:500 と 404 を別々の crawldb 状態で扱い、クロールは継続。
- このローカル実行では、同一ホスト間の実測間隔は 1.0 秒設定と整合し、配布時デフォルトは 5.0 秒。
- Apache-2.0、継続保守中、78 プラグイン、ラウンドをまたいで URL 状態を追跡する永続 crawldb。
- クラスタ不要、HDFS 不要、Solr 不要でローカルモード実行が可能。
短所
- JDK 24 以降では SecurityManager 削除の影響で動作しない(26.0.1 で失敗を確認)。同梱 Hadoop 3.4.2 は上流修正より前の版で、回避フラグも消えているため、LTS JDK の固定は好みではなく必須条件。
- 展開後約 396 MB、ライブラリ jar 188 個、プラグインディレクトリ 78、設定ファイル 35。
- コマンドごとに新しい JVM を起動するため、各フェーズで約 1.77 秒の固定オーバーヘッド。12 ページの深さ 4 クロールで約 45 秒、同条件の単一バイナリ型クローラーでは約 13 秒。
- 配布時デフォルトは外部ホストへもリンクをたどるため、1 サイトに閉じるには明示設定が必要。
http.agent.nameは空のまま出荷され、設定するまで fetcher は動かない。- 深さフラグがないので、深さは自分でループ回数として管理する必要がある。
- 実行時 DOM のエンドポイントは、試した全構成で到達できず、JS 実行型プロトコルへの差し替えも単純ではなかった。
- ローカルの単一ホスト、小さなテストデータでのみ検証した。分散/HDFS モード、Solr インデックス、hostdb、resume、増分再クロールのスケジューリングは今回の対象外であり、未検証として扱うべきです。
どんな人に向いていて、どんな人は離れるべきか
Nutch が真価を発揮するのは、クロールそのものが難しい場合です。検索インデックスを作りたい、複数ドメインにまたがる大規模クロールをしたい、URL ごとの状態や再試行の挙動を持つ永続的な URL データベースが欲しい、あるいは将来的に作業を複数マシンへ分散したい。そういう場合には、Nutch はそれ以前の多くの代替案が存在する前から、その仕事をしてきた基盤です。プラグインシステムにより、protocol、parser、filter、scoring の挙動を fork なしで変更できます。politeness のデフォルトは保守的で、開発者が相手のサーバーに配慮していることが伝わります。
数ページから構造化データだけ欲しいなら、Nutch から離れてください。Nutch は取得して解析した後、crawldb と segments を返し、indexer は自分で用意する前提です。対象がクライアントレンダリングの SPA なら、やはり離れるべきです。Class C は、私が試したすべてで到達できませんでした。チームに JVM がないなら離れるべきです。Java ツールチェーン、LTS JDK の固定、396 MB の jar を新たに積み増すことになるからです。そして仕事が「1 サイトを週 1 回、4 階層だけクロールする」なら、ラウンドループと設定ファイルの手間の方が、対象の規模に対して大きすぎます。
スクレイパーを探している人にとっては、多くの場合まさに最後のケースが本当の用途です。これは Nutch への批判ではなく、ツールと用件の不一致です。周辺領域を俯瞰したいなら、オープンソーススクレイパーの総覧 と おすすめの Web スクレイピング GitHub プロジェクト で、より軽量な選択肢を詳しく紹介しています。
代替案と、私たちのスタックが入る位置
まず公平に言うと、Nutch は無料で、Apache ライセンスで、セルフホスト可能で、将来にわたってリクエストごとの課金なしで運用できます。これは本当に大きな利点で、以下の比較で失われるものではありません。
関連レビュー: Browsertrix Crawler レビュー。
オープンソースの世界で何と比べるべきかは、何を最適化したいかで変わります。Python ベースでクロール制御と request-first の思想を求めるなら、Scrapy の方が多くの案件で近い位置づけです。ただし本記事では、同条件での導入サイズは測っていません。軽量な Go 製クローラーで、ブラウザなしのものを探すなら、Colly も検討候補です。問題が URL 発見ではなく、ページを LLM 向けコンテンツに変換することなら、Crawl4AI は別の層を狙っています。
Thunderbit のようなマネージドサービスは、fetching、rendering、extraction を API の裏に隠します。一方、Nutch はクロール状態とインフラを自分で握れます。Thunderbit はこのテストデータでは実行していないため、ここでの比較は回収率や動的ページ性能の比較ではなく、所有モデルの比較です。
このトレードオフは、所有かオーバーヘッドか、という話であり、かなり明確です。Nutch は完全な制御、永続 crawldb、設計上のクラスタ拡張性、そして追加コスト 0 を与えてくれます。その代わりに必要なのは、JVM、LTS JDK の固定、396 MB の jar、ラウンドループ、そして自前のインデックス層です。マネージド API は、最初の呼び出しで構造化出力を返し、インフラも不要です。その代わり、従量課金 と、クロール前線に対する制御の少なさが付きまといます。仕事が「5,000 万ページをインデックス化する」なら、Nutch のモデルが正しく、API は不合理です。仕事が「木曜までに 200 の商品ページから構造化レコードを取る」なら、逆です。
総評
Apache Nutch は、継続的で複数ドメインにまたがるクロールを行い、すでに JVM インフラを運用しているなら、検討する価値があります。このテストデータでは、静的発見は反復ごとに決定的で、parse-js は 2 つのリテラル JavaScript エンドポイントを見つけ、失敗も crawldb に適切に残り、実際のリクエスト間隔は設定した delay と一致しました。
ただし、導入コストは正直に見積もるべきです。Nutch 1.22 はここでは JDK 26.0.1 で失敗し、今回のレビューで実際に検証できた LTS 構成は OpenJDK 17.0.20 でした。Java 21 は未検証です。そのうえで http.agent.name を設定し、スコープを明示し、この小規模なローカル実行で観測されたフェーズごとの約 1.77 秒の固定下限を織り込む必要があります。そのトレードオフが意味を持つかは、クロールの期間、広がり、そして永続状態の必要性次第です。
Web データ抽出に Thunderbit を試す Get Started Free
よくある質問
Apache Nutch が "getSubject is not supported" で失敗するのはなぜですか?
JDK 24 以降では、JEP 486 により Subject.getSubject() が無条件で例外を投げるようになりました。一方で、同梱の Hadoop 3.4.2 はなおもそれを呼び出していました。そのため最初の Hadoop ジョブは、ページを 1 枚も取得する前に落ちます。昔の -Djava.security.manager=allow も、もはや VM を起動させることはできません。検証済みの Java 17 構成を使い、NUTCH_JAVA_HOME を設定してください。Java 21 もサポート対象の可能性はありますが、このレビューではフルサイクルを実行していません。
Nutch 1.22 はどの Java バージョンで動かすべきですか?
もっとも安全なのは Java 17 です。Nutch の CI もこれを対象にしており、私の OpenJDK 17.0.20 での検証でも問題なく動きました。Java 11 も 1.22 では引き続きサポートされていますが、プロジェクトは 1.23 から Java 17 が必要になる と明言しています。JDK 24 以上では動きません。Homebrew で keg-only の brew install openjdk@17 を使い、NUTCH_JAVA_HOME を設定すれば、システム既定の JDK はそのまま残せます。
Nutch は JavaScript が多いサイトもクロールできますか?
部分的にはできますが、その違いは重要です。parse-js プラグインを有効にすると、リンク先の JavaScript ファイルの中に文字列リテラルとしてだけ存在した 2 つのエンドポイントを、ブラウザなしで 2/2 取得できました。デフォルトのプラグインセットではどちらも見つかりませんでした。ただし、JavaScript 実行後に DOM が変化して初めて現れるエンドポイントは、静的構成ではどれも到達できませんでした。さらに、HtmlUnit プロトコルへの差し替えも、私の実行では単純な置換ではありませんでした。クライアントレンダリングのアプリを対象にするなら、JS 実行型プロトコルと本格的な設定作業を前提にするか、別のツールを選ぶべきです。
Nutch には Hadoop と Solr のインストールが必要ですか?
いいえ。ローカルモードでは Hadoop の LocalJobRunner がプロセス内で動くだけで、クラスタも HDFS デーモンも YARN も不要です。inject → generate → fetch → parse → updatedb の一連の流れは、他に何も入っていない 1 台のマシンで動きます。Solr は一般的なインデックス先ですが、クロール自体には必須ではありません。ただし、Hadoop の jar は 13 個同梱されており(バージョン 3.4.2)、だからこそ JDK 互換性の問題が起きるわけです。
Nutch が他のサイトまでクロールしないようにするにはどうすればいいですか?
配布時デフォルトはそうなっていないので、明示的に設定してください。Nutch 1.22 は db.ignore.external.links=false と寛容な URL フィルターで出荷されており、私のテストではデフォルトクロールが別ホストへのリンクをたどって取得しました。nutch-site.xml で db.ignore.external.links=true を設定するか、conf/regex-urlfilter.txt にホストルールを追加してください(たとえば +^https://example\.com/ の後に -.)。どちらもテストではクロールを完全に閉じ込められ、Nutch の crawldb と相手サーバーのリクエストログの両方で確認できました。


