Apache Nutch es un rastreador de la Apache Software Foundation cuyo desarrollo empezó en 2004. Es un sistema sobre JVM construido en Hadoop, organizado como un ciclo y no como un único comando de streaming: las URL semilla se injectan en una base de datos persistente y luego pasan por rondas de generate → fetch → parse → updatedb, con espacio para plugins de protocolo, parser, filtro de URL y scoring. El resultado habitual alimenta un índice de búsqueda como Solr o Elasticsearch, en lugar de generar un CSV.
Ejecuté Nutch 1.22 contra un sitio local de prueba controlado, que registra cada solicitud en el servidor; así, los resultados se juzgan por lo que el servidor realmente recibió, no por lo que el crawler dijo haber hecho. Cuatro límites marcaron la ejecución: la versión del JDK, http.agent.name, el alcance del rastreo y si parse-js aparece en plugin.includes. El ciclo completo se repitió varias veces con la configuración probada; si cambias el JDK o dejas sin definir la identidad del agente, el proceso se detiene antes de llegar a páginas útiles.
El límite del JDK aparece antes de que empiece cualquier rastreo. Nutch 1.22 no arrancó aquí con JDK 26.0.1: el primer job de Hadoop murió dentro de Subject.getSubject() después de que Java eliminara la ruta de SecurityManager. Nutch incorpora Hadoop 3.4.2, mientras que la corrección llegó en Hadoop 3.4.3 siete días después del lanzamiento de Nutch 1.22. Por otra parte, parse-js hizo que la recuperación de dos literales en archivos JavaScript pasara de 0/2 a 2/2 sin ejecutar un navegador.
Para qué sirve Nutch y para qué no
Nutch no es un scraper. La extracción estructurada de campos no es su objetivo: descubre y descarga URL a gran escala, mantiene una base de datos persistente de esas URL y sus estados (la crawldb), y te entrega segmentos que otra herramienta convierte en un índice. Si lo apuntas a un catálogo esperando una tabla de nombres y precios, obtendrás una crawldb.
Esa arquitectura explica casi todo lo que sigue. Nutch nació unas dos décadas antes de la era del crawler de binario único, y está pensado para el problema para el que Hadoop fue creado: rastrear más páginas de las que caben en una sola máquina. Ejecutarlo en un portátil contra un fixture de 12 páginas es como alquilar un tren de carga para mover una estantería: sirve para entender el tren, pero sería injusto pedirle la ergonomía de una bicicleta.
La versión actual es 1.22, anunciada el 17 de febrero de 2026. Tiene licencia Apache-2.0, el repositorio tenía 3.272 estrellas y 8 incidencias abiertas cuando lo revisé el 27 de julio de 2026, y master había recibido cambios cuatro días antes. Se trata de un proyecto mantenido, no abandonado, y eso es importante para interpretar el problema del JDK: una ventana de empaquetado que se cerró una semana demasiado pronto, no desinterés.
La matriz de versiones: JDK 24+, Hadoop 3.4.2 y una corrección de dos líneas
El bloqueo es una interacción entre tres versiones, y la única parte que puedes controlar directamente es en qué JDK se ejecuta Nutch. El primer job de Hadoop, con el JDK por defecto del host, falló en la inicialización:
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)
Código de salida 255. Cero páginas descargadas. bin/nutch inject ni siquiera llega a la red: inicializa un LocalJobRunner de Hadoop, que pregunta quién es el usuario actual, lo que llama a Subject.getSubject(), que JEP 486 convirtió en una excepción obligatoria cuando JDK 24 retiró de forma definitiva SecurityManager. Mi JDK del host era OpenJDK 26.0.1, muy por encima de ese umbral.
Tampoco funciona la vía de escape tradicional. Añadir -Djava.security.manager=allow, la bandera que antes reactivaba el comportamiento antiguo, es rechazado por la máquina virtual antes de que se cargue el código de Nutch:
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.
Eso devuelve código 1 y es un callejón sin salida por diseño: la bandera desapareció junto con la función.
La causa raíz está en la versión de Hadoop que incluye Nutch 1.22. El problema de getSubject está registrado como HADOOP-19212 y se corrigió en Hadoop 3.4.3 y 3.5.0; Nutch 1.22 incorpora hadoop-common-3.4.2. Nutch 1.22 se lanzó el 17 de febrero de 2026, y Hadoop 3.4.3 llegó aproximadamente una semana después.
Tampoco es un problema de dependencia de Solr o de un clúster Hadoop. Es una suposición común pensar que Nutch necesita un clúster Hadoop y un Solr en ejecución para hacer algo. No es así. El modo local ejecuta LocalJobRunner de Hadoop dentro del proceso, sin demonio HDFS, sin YARN y sin clúster. Todo el ciclo inject → generate → fetch → parse → updatedb corre en una sola máquina sin instalar nada más. El bloqueo del JDK es únicamente un problema de versión de librerías empaquetadas y te detiene antes de que entre en juego cualquier cuestión de infraestructura.
La matriz práctica de versiones, con los tres casos medidos:
| JDK usado | Comando | Resultado |
|---|---|---|
| OpenJDK 26.0.1 | bin/nutch inject | Falla, rc=255 — UnsupportedOperationException: getSubject is not supported |
| OpenJDK 26.0.1 | bin/nutch inject + -Djava.security.manager=allow | Falla, rc=1 — la VM rechaza el arranque |
| OpenJDK 17.0.20 (LTS) | bin/nutch inject | Funciona, rc=0 — Total new urls injected: 1 |
La solución son dos comandos. Instala un JDK LTS y apunta Nutch hacia él:
brew install openjdk@17
export NUTCH_JAVA_HOME=/opt/homebrew/opt/openjdk@17
Es un paquete keg-only, así que no toca el JDK predeterminado del sistema. La propia CI de Nutch apunta a Java 17, y el proyecto ha anunciado públicamente que 1.22 será la última versión compatible con Java 11 y que 1.23 requerirá Java 17. Así que un JDK LTS no es un apaño: es la configuración soportada. La incompatibilidad está entre lo que Nutch admite y lo que brew install openjdk te entrega en 2026, y son dos cosas distintas que aquí chocan en el primer comando.
A partir de aquí, todo se ejecutó en OpenJDK 17.0.20, donde el ciclo completo funciona sin problemas.
La instalación, medida: 396 MB y una propiedad que lo bloquea todo
“Pesado” es el adjetivo que todo el mundo usa, pero no sirve sin cifras. Esto es lo que realmente ocupa la distribución binaria descomprimida de Nutch 1.22:
| Elemento | Distribución binaria de Nutch 1.22 |
|---|---|
| Tamaño descomprimido | ≈396 MB |
Jars en lib/ | 188 (≈113 MB) |
| — de los cuales la pila Hadoop incluida | 13 |
| Directorios de plugins | 78 |
| Jars dentro de esos directorios | 533 |
| Archivos de configuración | 35 |
Scripts en bin/ | 2 — crawl y nutch |
A modo de referencia, un crawler moderno en Go como katana se distribuye como un binario de unos 50 MB, sin JVM ni jars externos.
Luego está la puerta que nadie te avisa que existe. El nutch-site.xml incluido viene vacío, y http.agent.name tiene por defecto una cadena vacía. Si no se define, mi primer rastreo no descargó ninguna ruta y registró:
ERROR Fetcher: No agents listed in 'http.agent.name' property.
Bastó con establecer esa propiedad, sin tocar nada más, para que el rastreo empezara a funcionar. Con la propiedad vacía, el comando terminó sin descargar páginas y el log mostró el error anterior; no fue un fallo silencioso.
La configuración mínima viable resultó ser tres piezas: conf/nutch-site.xml (nombre del agente, conjunto de plugins, alcance), conf/regex-urlfilter.txt (alcance por host) y un archivo con URL semilla. No es demasiado. Solo son tres archivos más que crawler run <url>.
Qué encontró: el interruptor de plugins que realmente importa

El sitio de prueba tenía tres clases de endpoint intencionadamente distintas, y el comportamiento de Nutch se separó claramente entre ellas:
- Clase A — enlaces HTML normales (4 páginas, más una cadena de 3 niveles de profundidad)
- Clase B — endpoints que existen solo como literales de cadena dentro de un archivo JavaScript enlazado: uno como argumento de una llamada,
fetch('/api/js-endpoint-7'), y otro como asignación,const other = "/api/js-endpoint-8" - Clase C — un endpoint que solo existe después de que JavaScript se ejecuta y lo inserta en el DOM
Resultados, según los registros del servidor, repetidos tres veces:
| Configuración de plugins | Clase A (enlaces HTML) | Clase B (literales en JS) | Clase C (DOM en tiempo de ejecución) |
|---|---|---|---|
Valor por defecto incluido — parse-(html|tika) | 4/4 (recall 1.0) | 0/2 (recall 0.0) | no alcanzado |
Con parse-js — parse-(html|tika|js) | 4/4 (recall 1.0) | 2/2 (recall 1.0) | no alcanzado |
Idéntico en las tres repeticiones. Determinista.
El salto de la clase B es el que suele subestimarse. Nutch encontró ambos endpoints incrustados en JavaScript sin ejecutar un navegador, usando el análisis basado en expresiones regulares del plugin parse-js sobre el contenido del JavaScript. El archivo app.js se descargó en ambas configuraciones —Nutch trata <script src> como un enlace saliente de todos modos—, así que la diferencia completa está en si alguien lee el contenido del archivo buscando cadenas con forma de URL. Al activar el plugin, detecta ambas formas literales.
En este fixture, Nutch en su configuración por defecto y katana en modo estándar alcanzaron el mismo conjunto de la clase A, mientras que Nutch con parse-js y katana con -jc alcanzaron las clases A y B sin navegador. La versión exacta de Katana y el comando completo no aparecen en este artículo, así que ese resultado se presenta como contexto, no como un benchmark estricto entre productos.
La clase C es el límite realista. Ninguna configuración estática llegó hasta allí, y es lo esperable: recuperar un endpoint que solo existe después de ejecutar scripts exige ejecutar realmente el JavaScript. Probé también a sustituir protocol-http por protocol-htmlunit, el protocolo de Nutch que ejecuta JavaScript en Java. Cargó y corrió sin fallar, pero en el mismo marco de cuatro rondas solo completó una, descargó únicamente la página semilla y app.js, no alcanzó ninguna de A/B/C, y la segunda ronda informó 0 records selected for fetching. Eso refleja una prueba mal ajustada, no un veredicto sobre la capacidad de HtmlUnit. Lo que sí deja claro es algo más acotado: sustituir el protocolo por uno que ejecute JavaScript no es un cambio directo de enchufar y usar, y la clase C siguió sin alcanzarse en todas las configuraciones que probé.
Control del rastreo y comportamiento ante fallos
La profundidad no es un flag. En Nutch no existe --depth 3; la profundidad es simplemente la cantidad de rondas generate → fetch → parse → updatedb que ejecutes, porque la ronda R descarga la frontera descubierta en la ronda R-1. Mi cadena de profundidad lo confirmó con precisión:
| Rondas ejecutadas | Ruta más profunda alcanzada |
|---|---|
| 2 | /depth/1 |
| 3 | /depth/2 |
| 4 | /depth/3 |
Es limpio y mecánico, pero significa que la profundidad es un contador de bucle en tu script, no un parámetro.
Ahora, la trampa. El valor por defecto incluido de Nutch es db.ignore.external.links=false, combinado con un filtro de URL permisivo +. —lo que significa que un rastreo por defecto seguirá enlaces fuera del host semilla. Sembré una página que enlazaba una ruta dentro de alcance y otra a un hostname distinto, y el rastreo descargó el host externo. Dos señales independientes coincidieron: la propia crawldb de Nutch lo marcó como db_fetched y el contador del servidor del otro host registró la visita.
Mantenerse dentro del alcance es opt-in, y ambas soluciones funcionan de forma verificable:
| Configuración | Host externo en la crawldb | Visita registrada en el servidor externo | ¿Quedó contenido? |
|---|---|---|---|
db.ignore.external.links=false (valor por defecto incluido) | db_fetched | +1 | No |
db.ignore.external.links=true | ausente | 0 | Sí |
Regla de host en regex-urlfilter.txt (+^http://127.0.0.1: y luego -.) | ausente | 0 | Sí |
Si vas a rastrear un solo sitio, define una de esas dos opciones antes de tu primera ejecución real. Una advertencia metodológica: esta prueba es sensible a la carga del servidor local, así que esas tres filas proceden de una ejecución sin nada más tocando el fixture. El comportamiento en sí es claro y está respaldado por dos señales independientes; los valores concretos de la tabla corresponden a una ejecución limpia, no a un promedio de muchas.
Los sitemaps son un paso aparte. La cortesía está activada —un rastreo normal descargó /robots.txt—, pero el sitemap necesita su propio comando:
| Enfoque | ¿Se solicitó /sitemap.xml? | Endpoints que solo existían en el sitemap |
|---|---|---|
| Un rastreo normal | nunca solicitado | 0/2 |
bin/nutch sitemap, ejecutado explícitamente contra la crawldb | descargado | 2/2 entradas inyectadas, recall completo |
modo de archivos conocidos en línea de katana con -kf, mismo fixture, en un host con IP | no registrado | 0/2 |
Es un modelo distinto al de los crawlers que tiran de los archivos conocidos en línea, y te cuesta un comando extra, pero hace el trabajo por completo.
Dos comportamientos menores también respondieron bien.
Gestión de errores: un rastreo sobre una página que enlazaba una 500 y una 404 completó todas las rondas correctamente, siguió descargando las cuatro páginas de la clase A y registró cada fallo por separado:
| Respuesta fallida enlazada desde la página | estado registrado en crawldb |
|---|---|
| 500 | db_unfetched (elegible para reintento) |
| 404 | db_gone |
Nada se rompió.
Cortesía: con un hilo por cola, la distancia entre descargas del mismo host siguió el valor configurado:
fetcher.server.delay | Intervalo mediano entre descargas del mismo host |
|---|---|
| 1.0 segundo | 1.009 s (mínimo 1.006 s) |
| 0.0 | 0.002 s |
La perilla hace exactamente lo que promete. El valor por defecto incluido es 5.0 segundos, que es conservador y, de nuevo, probablemente correcto para una herramienta pensada para rastrear servidores ajenos.
El coste del batch, en segundos
Cada comando de Nutch arranca una JVM nueva. Ese único hecho domina el perfil de tiempo más que cualquier aspecto del fetching.
| Fase (por ronda) | Segundos medianos |
|---|---|
inject (una vez) | 1.81 |
generate | 3.93 |
fetch | 2.82 |
parse | 1.78 |
updatedb | 1.81 |
| Una ronda completa | 12.14 |
El suelo efectivo por job —arranque de JVM más inicialización de Hadoop, medido como la fase más barata de trabajo trivial— es de unos 1.77 segundos. Multiplica eso por cuatro comandos por ronda, añade el inject inicial y el panorama de un rastreo completo queda así:
| Herramienta | Rastreo de profundidad 4 del fixture de 12 páginas | Procesos |
|---|---|---|
| Nutch | aproximadamente 45 segundos (medí 45.8 s y 45.0 s en dos configuraciones) | alrededor de 17 arranques de JVM, casi ninguno haciendo trabajo de red |
katana en modo standard, mismo fixture | unos 13 segundos | un solo proceso |
La diferencia no tiene que ver con el rendimiento de descarga; ambas herramientas solicitan el mismo puñado de páginas. Es una cuestión arquitectónica. Nutch paga un coste fijo de proceso por fase porque esas fases están diseñadas como jobs MapReduce. En un rastreo local pequeño, la preparación domina. Ese coste fijo debería representar una fracción menor en trabajos más largos, pero esta prueba no midió el punto en el que Nutch y katana se cruzan, ni si su proporción se invierte.
Pros y contras
Pros
- Descubrimiento estático determinista: clase HTML 4/4, cadena de profundidad 3/3, idéntico en tres ejecuciones repetidas.
parse-jsrecupera endpoints de literales en archivos JavaScript (2/2) sin navegador, capturando tanto formas de argumento como de asignación.- Dos controles de alcance verificados que contienen por completo un rastreo (
db.ignore.external.linksy la regla de host enregex-urlfilter). - La ingesta de sitemap mediante
bin/nutch sitemaplogró un recall completo de 2/2 en endpoints que un rastreo normal no encontró. - Robusto ante fallos: tanto 500 como 404 se manejan con estados distintos en crawldb y el rastreo continúa.
- En esta ejecución local, el intervalo observado dentro del mismo host fue coherente con el retardo configurado de 1.0 segundo; el valor por defecto incluido es 5.0 segundos.
- Apache-2.0, mantenido activamente, 78 plugins y una crawldb persistente que conserva el estado por URL entre rondas.
- Funciona en modo local sin clúster, sin HDFS y sin necesidad de Solr.
Contras
- No ejecuta en JDK 24 o superior, donde la eliminación de SecurityManager rompe el arranque (medí el fallo en 26.0.1) — Hadoop 3.4.2, el que viene incluido, es anterior a la corrección upstream y la bandera de escape ya no existe, así que fijar un JDK LTS no es una preferencia sino un requisito.
- ≈396 MB descomprimidos, 188 jars de librerías, 78 directorios de plugins y 35 archivos de configuración.
- Un JVM nuevo por comando implica ~1.77 s de sobrecoste fijo por fase; ~45 s para un rastreo de profundidad 4 sobre 12 páginas frente a ~13 s para un crawler de binario único sobre el mismo terreno.
- El valor por defecto incluido sigue enlaces hacia hosts externos; permanecer en un solo sitio es opt-in.
http.agent.nameviene vacío y el fetcher no ejecuta nada hasta que lo configuras.- No hay flag de profundidad: la profundidad es un contador de bucle que debes gestionar tú mismo.
- Los endpoints renderizados en tiempo de ejecución no fueron alcanzables en ninguna configuración probada, y cambiar al protocolo que ejecuta JavaScript no fue un reemplazo directo.
- Probé el modo local en un solo host con un fixture pequeño. El modo distribuido/HDFS, la indexación con Solr, hostdb, resume y la programación de re-rastreo incremental quedaron fuera de esta prueba; consúltalos aquí como no probados, no como avalados.
Quién debería usarlo y quién debería irse
Nutch vale la pena cuando el rastreo en sí es lo difícil. Si estás construyendo un índice de búsqueda, ejecutando un rastreo amplio entre múltiples dominios, necesitas una base de datos persistente de URL con estado y reintentos por URL, o esperas distribuir el trabajo entre varias máquinas, esta es una infraestructura que lleva haciendo exactamente ese trabajo desde antes de que existieran la mayoría de las alternativas. El sistema de plugins te permite cambiar el comportamiento de protocolo, parser, filtro y scoring sin bifurcar nada. Los valores de cortesía por defecto son conservadores de una forma que sugiere que sus mantenedores han pensado mucho en ser buenos ciudadanos en la red.
Aléjate si quieres datos estructurados de unas pocas páginas. Nutch las descargará y analizará, pero te devolverá una crawldb y segmentos, y esperará que tú aportes un indexador. Aléjate si tus objetivos son aplicaciones de una sola página renderizadas del lado del cliente: la clase C quedó fuera de alcance en todo lo que ejecuté. Aléjate si tu equipo no usa JVM, porque estarías añadiendo una toolchain Java, una fijación de JDK LTS y 396 MB de jars a una pila que hoy no tiene nada de eso. Y si la tarea es “rastrear un sitio, cuatro niveles de profundidad, una vez por semana”, pasarás más tiempo en la lógica de rondas y en archivos de configuración del que el rastreo merece.
Para la mayoría de las personas que buscan un scraper, ese último caso es el caso real. Y no es una crítica a Nutch: es una desalineación entre la herramienta y la tarea. Si quieres una visión del panorama más amplio, nuestro resumen de scrapers open source y los mejores proyectos de web scraping en GitHub cubren con más detalle la parte más ligera del espectro.
Alternativas, incluido dónde encaja nuestra propia pila
Primero, el encuadre justo: Nutch es gratis, tiene licencia Apache, se autoalberga y lo puedes usar indefinidamente sin coste por solicitud. Esa es una ventaja real, y nada de lo siguiente la borra.
Reseña relacionada: Reseña de Browsertrix Crawler.
Dentro del mundo open source, la comparación depende de qué estés optimizando. Si buscas un framework en Python con control de rastreo y una filosofía centrada en requests, Scrapy se parece más a Nutch para muchos proyectos; este artículo no midió su peso de instalación bajo las mismas condiciones. Si quieres un crawler compacto en Go y sin navegador, Colly es otra opción razonable. Si tu problema es convertir páginas en contenido listo para LLM y no descubrir URL, Crawl4AI apunta a otra capa.
Un servicio gestionado como Thunderbit traslada el fetching, el renderizado y la extracción detrás de una API, mientras que Nutch mantiene el estado del rastreo y la infraestructura bajo tu control. Thunderbit no se ejecutó en este fixture, así que esta comparación es de modelo de propiedad, no una afirmación sobre igualdad de recall o rendimiento en páginas dinámicas.
La decisión es entre control y sobrecarga, y no es sutil. Nutch te da control total, una crawldb persistente, escalabilidad a clúster por diseño y coste marginal cero, a cambio de una JVM, una fijación de JDK LTS, 396 MB de jars, un ciclo por rondas y tu propia capa de indexado. Una API gestionada te da salida estructurada desde la primera llamada y ninguna infraestructura, a cambio de precios por llamada y menos control sobre la frontera del rastreo. Si tu trabajo es “indexar 50 millones de páginas”, el modelo de Nutch es el correcto y una API sería absurda. Si tu trabajo es “extraer registros estructurados de 200 páginas de producto antes del jueves”, ocurre lo contrario.
Prueba Thunderbit para extracción de datos web
Veredicto
Apache Nutch merece evaluarse si vas a ejecutar un rastreo continuo, multisitio, y ya trabajas con infraestructura JVM. En este fixture, el descubrimiento estático fue determinista entre repeticiones, parse-js encontró ambos endpoints literales en JavaScript, los fallos siguieron representados en la crawldb y el espaciado observado entre solicitudes coincidió con el retardo configurado.
Calcula con honestidad el coste de entrada. Nutch 1.22 falló aquí con JDK 26.0.1; OpenJDK 17.0.20 es la configuración LTS que sí se verificó en esta reseña, mientras que Java 21 no se probó. Después, configura http.agent.name, define el alcance explícitamente y cuenta con el suelo fijo observado de ~1.77 segundos por fase en esta ejecución local pequeña. Que el intercambio compense o no depende de la duración del rastreo, su amplitud y la necesidad de estado persistente.
Prueba Thunderbit para extracción de datos web Get Started Free
Preguntas frecuentes
¿Por qué Apache Nutch falla con “getSubject is not supported”?
En JDK 24 o superior, JEP 486 hizo que Subject.getSubject() lanzara una excepción de forma obligatoria, mientras que Hadoop 3.4.2, el que viene incluido, seguía llamándolo. Por eso el primer job de Hadoop falla antes de descargar cualquier página, y la antigua salida de emergencia -Djava.security.manager=allow ya no arranca la VM. Usa la configuración verificada de Java 17 y define NUTCH_JAVA_HOME; Java 21 podría estar soportado, pero esta reseña no ejecutó el ciclo completo sobre esa versión.
¿Con qué versión de Java debería ejecutar Nutch 1.22?
Java 17 es la respuesta más segura: la propia CI de Nutch apunta a esa versión y funcionó sin problemas en mis pruebas con OpenJDK 17.0.20. Java 11 también sigue siendo compatible con 1.22, aunque el proyecto ya anunció que 1.23 requerirá Java 17. Cualquier versión desde JDK 24 en adelante no funcionará. Una instalación Homebrew keg-only (brew install openjdk@17) junto con NUTCH_JAVA_HOME mantiene intacto el JDK por defecto del sistema.
¿Puede Nutch rastrear sitios con mucho JavaScript?
Parcialmente, y la diferencia importa. Con el plugin parse-js activado, Nutch encontró ambos endpoints que solo existían como literales de cadena dentro de un archivo JavaScript enlazado: 2/2, sin navegador. Con el conjunto de plugins por defecto no encontró ninguno. Pero un endpoint que solo aparece después de que JavaScript se ejecuta y modifica el DOM quedó fuera de alcance en todas las configuraciones estáticas que probé, y cambiar al protocolo HtmlUnit no fue un reemplazo directo en mi ejecución. Para aplicaciones renderizadas en el cliente, asume que necesitarás un protocolo que ejecute JavaScript y trabajo de configuración real, o usa otra herramienta.
¿Nutch necesita tener Hadoop y Solr instalados?
No. El modo local ejecuta LocalJobRunner de Hadoop dentro del proceso —sin clúster, sin demonio HDFS, sin YARN— y todo el ciclo inject → generate → fetch → parse → updatedb funciona en una sola máquina sin instalar nada más. Solr es el destino típico del indexado, pero el rastreo en sí no lo requiere. Dicho esto, los jars de Hadoop vienen incluidos (13, versión 3.4.2), y precisamente por eso existe el problema de compatibilidad con el JDK.
¿Cómo evito que Nutch rastree otros sitios?
Defínelo explícitamente, porque el valor por defecto incluido no lo impide. Nutch 1.22 trae db.ignore.external.links=false junto con un filtro de URL permisivo, y en mi prueba el rastreo por defecto siguió un enlace hacia otro host y lo descargó. Puedes establecer db.ignore.external.links=true en nutch-site.xml, o añadir una regla de host en conf/regex-urlfilter.txt (por ejemplo +^https://example\.com/ seguido de -.). Ambas opciones contuvieron completamente el rastreo en las pruebas, verificado tanto desde la propia crawldb de Nutch como desde el log de peticiones del otro servidor.


