Apache Nutch — это краулер от Apache Software Foundation, разработка которого началась в 2004 году. Это JVM-система, построенная на Hadoop и работающая не как одиночная потоковая команда, а как цикл: seed URL сначала inject-ятся в постоянную базу, затем идут раунды generate → fetch → parse → updatedb, а для протоколов, парсинга, фильтрации URL и скоринга предусмотрены плагины. Обычно результатом становится не CSV, а наполнение поискового индекса вроде Solr или Elasticsearch.
Я прогнал Nutch 1.22 на контролируемом локальном тестовом сайте — таком, который логирует каждый запрос на стороне сервера, так что результаты оцениваются по тому, что сервер реально увидел, а не по заявлениям самого краулера. На запуск повлияли четыре границы: версия JDK, http.agent.name, область обхода и наличие parse-js в plugin.includes. Полный цикл многократно прогонялся в протестированной конфигурации; если сменить JDK или оставить идентификатор агента пустым, процесс останавливается ещё до полезной выборки страниц.
Граница JDK проявляется ещё до начала обхода. Nutch 1.22 не стартовал у меня на JDK 26.0.1: первый Hadoop job падал внутри Subject.getSubject(), потому что Java убрала путь через SecurityManager. В составе Nutch поставляется Hadoop 3.4.2, а исправление появилось в Hadoop 3.4.3 через семь дней после релиза Nutch 1.22. Отдельно parse-js улучшил извлечение двух JavaScript-литералов с 0/2 до 2/2 без запуска браузера.
Для чего нужен Nutch, а для чего — нет
Nutch — не scraper в привычном смысле. Его задача не в структурированном извлечении полей: он массово находит и загружает URL, ведёт постоянную базу этих адресов и их состояний (crawldb), а затем отдаёт вам сегменты, которые кто-то другой превращает в индекс. Если направить его на каталог и ждать таблицу с названиями и ценами, на выходе вы получите crawldb.
Именно этим объясняется большая часть дальнейших наблюдений. Nutch появился примерно на два десятилетия раньше эпохи однобинарных краулеров и создавался под ту проблему, под которую вообще был сделан Hadoop: обходить больше страниц, чем помещается на одной машине. Запускать его на ноутбуке против тестового стенда из 12 страниц — всё равно что арендовать грузовой поезд, чтобы перевезти книжную полку: это информативно для поезда, но странно ожидать от него эргономики велосипеда.
Текущий релиз — 1.22, анонсированный 17 февраля 2026 года. Лицензия — Apache-2.0, в момент моей проверки 27 июля 2026 года репозиторий имел 3 272 звезды и 8 открытых issues, а в master изменения вносились за четыре дня до этого. Это живой проект, а не заброшенный — и именно под таким углом стоит смотреть на проблему с JDK: не как на признак запущенности, а как на окно несовместимости, закрывшееся на неделю раньше, чем надо.
Матрица версий: JDK 24+, Hadoop 3.4.2 и двухстрочное исправление
Блокирующая проблема — это взаимодействие трёх версий, и из них под вашим контролем находится только одна: на каком JDK будет работать Nutch. Самый первый Hadoop job на стандартном JDK хоста падал уже на инициализации:
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. Ни одной страницы не загружено. bin/nutch inject даже не доходит до сети — он инициализирует Hadoop LocalJobRunner, тот выясняет текущего пользователя, затем вызывает Subject.getSubject(), а JEP 486 превратил это в безусловное исключение после окончательного удаления SecurityManager в JDK 24. На хосте у меня был OpenJDK 26.0.1, то есть далеко за этой границей.
Обычная лазейка тоже не помогает. Если добавить -Djava.security.manager=allow — флаг, который раньше возвращал старое поведение, — JVM отклоняет его ещё до загрузки кода 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.
Это код возврата 1, и тупик здесь сделан намеренно: флаг удалили вместе с функцией.
Корень проблемы — в версии Hadoop, поставляемой вместе с Nutch 1.22. Ошибка getSubject отслеживается как HADOOP-19212 и исправлена в Hadoop 3.4.3 и 3.5.0; при этом Nutch 1.22 включает hadoop-common-3.4.2. Nutch 1.22 вышел 17 февраля 2026 года, а Hadoop 3.4.3 появился примерно неделей позже.
И это не проблема зависимости от Solr или Hadoop-кластера. Часто предполагают, что Nutch вообще не умеет ничего без Hadoop-кластера и запущенного Solr. Это неверно. В локальном режиме он использует встроенный Hadoop LocalJobRunner — без HDFS-daemon, без YARN и без кластера. Весь цикл inject → generate → fetch → parse → updatedb работает на одной машине и не требует ничего дополнительного. Граница по JDK — это чисто проблема версии встроенной библиотеки, и она останавливает вас ещё до того, как возникает вопрос инфраструктуры.
Практическая матрица версий, все три строки измерены:
| Используемый 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 — JVM отказывается запускаться |
| OpenJDK 17.0.20 (LTS) | bin/nutch inject | Работает, rc=0 — Total new urls injected: 1 |
Исправление состоит из двух команд. Установите LTS JDK и укажите его Nutch:
brew install openjdk@17
export NUTCH_JAVA_HOME=/opt/homebrew/opt/openjdk@17
Пакет keg-only, так что системный JDK он не трогает. В CI самого Nutch целевой версией является Java 17, и проект официально объявил, что релиз 1.22 — последний, который запускается на Java 11, а для 1.23 потребуется Java 17. То есть LTS JDK — это не обходной путь, а поддерживаемая конфигурация. Несовпадение здесь не между Nutch и его возможностями, а между тем, что он поддерживает, и тем, что brew install openjdk выдаёт вам в 2026 году. Эти два ответа на разные вопросы просто сталкиваются в самой первой команде.
Дальше всё работало на OpenJDK 17.0.20, где весь цикл проходит чисто.
Настройка в цифрах: 396 МБ и один параметр, который блокирует всё
Слово «тяжёлый» все любят, но без цифр оно бесполезно. Вот что реально содержится в распакованной binary-дистрибуции Nutch 1.22:
| Параметр | Binary-дистрибуция Nutch 1.22 |
|---|---|
| Размер после распаковки | ≈396 МБ |
Jar-файлы в lib/ | 188 (≈113 МБ) |
| — из них в составе Hadoop-стека | 13 |
| Каталоги плагинов | 78 |
| Jar-файлы внутри этих каталогов | 533 |
| Файлы конфигурации | 35 |
Скрипты в bin/ | 2 — crawl и nutch |
Для масштаба: современный Go-краулер вроде katana поставляется как один бинарник примерно на 50 МБ, без JVM и без внешних jar-файлов.
Есть ещё одна ловушка, о которой почти никто не предупреждает. Поставляемый nutch-site.xml пуст, а http.agent.name по умолчанию тоже пустая строка. Если его не задать, мой первый обход загрузил ноль путей и записал:
ERROR Fetcher: No agents listed in 'http.agent.name' property.
Если задать только этот параметр — и больше ничего — всё начинает работать. При пустом значении команды завершаются без загрузки страниц, а в логах появляется ошибка с агентом, приведённая выше; тишины не было.
Минимально жизнеспособная конфигурация оказалась из трёх артефактов: conf/nutch-site.xml (имя агента, набор плагинов, scope), conf/regex-urlfilter.txt (ограничение по хосту) и файла seed-URL. Это не много. Просто на три файла больше, чем crawler run <url>.
Что он нашёл: важный переключатель плагина

Тестовый сайт содержал три специально разные категории endpoint-ов, и поведение Nutch разделилось по ним очень чётко:
- Класс A — обычные HTML-ссылки (4 страницы, плюс цепочка глубиной в 3 ссылки)
- Класс B — endpoint-ы, существующие только как строковые литералы внутри подключаемого JavaScript-файла: один как аргумент вызова
fetch('/api/js-endpoint-7'), другой как присваиваниеconst other = "/api/js-endpoint-8" - Класс C — endpoint, который появляется только после выполнения JavaScript и вставки его в DOM
Результаты по серверным логам запросов, повторённые три раза:
| Конфигурация плагинов | Класс A (HTML-ссылки) | Класс B (литералы в JS-файле) | Класс C (DOM во время выполнения) |
|---|---|---|---|
Стандартная поставка — parse-(html|tika) | 4/4 (recall 1.0) | 0/2 (recall 0.0) | не достигнут |
С parse-js — parse-(html|tika|js) | 4/4 (recall 1.0) | 2/2 (recall 1.0) | не достигнут |
Во всех трёх повторах результат был одинаковым. Детерминированно.
Переход для класса B — самая недооценённая часть. Nutch нашёл оба endpoint-а, встроенных в JavaScript, не запуская браузер, а просто используя regex-сканирование содержимого JavaScript через плагин parse-js. Сам файл app.js в обеих конфигурациях был загружен — Nutch считает <script src> outlink независимо от содержимого, — так что вся разница заключалась в том, читает ли кто-то содержимое файла в поисках строк, похожих на URL. Включаешь плагин — и он ловит обе буквальные формы.
На этом стенде стандартный режим Nutch и katana в обычном режиме пришли к одному и тому же набору класса A, а Nutch с parse-js и katana с -jc дошли до классов A и B без браузера. Версия Katana и полный командный запуск в этой статье не зафиксированы, так что это скорее контекст, а не жёсткое сравнение продуктов.
Класс C — честный потолок. Ни одна статическая конфигурация его не достигла, и это ожидаемо: чтобы восстановить endpoint, который существует только после выполнения скрипта, сам скрипт действительно нужно исполнять. Я пробовал заменить protocol-http на protocol-htmlunit, то есть на чисто Java-протокол Nutch, исполняющий JS. Он загрузился и не падал, но в том же четырёхраундовом harness завершил только один раунд, загрузил лишь seed-страницу и app.js, не достиг ни A, ни B, ни C, а на втором раунде сообщил 0 records selected for fetching. Это скорее тест без достаточной настройки, чем приговор HtmlUnit. Вывод уже и так достаточен: замена на протокол с выполнением JS — не plug-and-play, а класс C в каждой протестированной конфигурации остался недостижим.
Управление обходом и поведение при ошибках
Глубина — это не флаг. В Nutch нет --depth 3; глубина — это просто количество раундов generate → fetch → parse → updatedb, потому что раунд R загружает frontier, найденный в раунде R-1. Моя цепочка глубины подтвердила это буквально:
| Запущено раундов | Максимальный достигнутый путь |
|---|---|
| 2 | /depth/1 |
| 3 | /depth/2 |
| 4 | /depth/3 |
Чисто и механически, но это означает, что глубина — это счётчик циклов в вашем скрипте, а не параметр.
Теперь ловушка. В поставке по умолчанию у Nutch стоит db.ignore.external.links=false вместе с разрешающим URL-фильтром +. — то есть обычный crawl Nutch будет переходить по ссылкам на внешние хосты. Я засеял страницу, которая ссылалась на один адрес в пределах сайта и на другой хост, и обход действительно забрал страницу на чужом хосте. Два независимых сигнала совпали: сам crawldb Nutch пометил его как db_fetched, а сервер другого хоста зафиксировал запрос.
Оставаться в пределах сайта нужно включать явно, и оба способа действительно работают:
| Конфигурация | Внешний хост в crawldb | Запрос к серверу внешнего хоста | Обход ограничен? |
|---|---|---|---|
db.ignore.external.links=false (стандартная поставка) | db_fetched | +1 | Нет |
db.ignore.external.links=true | отсутствует | 0 | Да |
Правило хоста в regex-urlfilter.txt (+^http://127.0.0.1: затем -.) | отсутствует | 0 | Да |
Если вы обходите один сайт, задайте одно из этих ограничений ещё до первого настоящего запуска. Один методологический нюанс: этот тест чувствителен к нагрузке на локальный сервер, поэтому все три строки получены в запуске, где больше ничто не обращалось к стенду. Само поведение механически понятно и подтверждено двумя независимыми сигналами; конкретные значения строк — это один чистый прогон, а не среднее по многим.
Карта сайта — отдельный шаг. Вежливость включена: обычный crawl запрашивал /robots.txt, но сам sitemap требует отдельной команды:
| Подход | Был ли запрошен /sitemap.xml? | Endpoint-ы, которые существовали только в sitemap |
|---|---|---|
| Обычный crawl | ни разу не запрашивался | 0/2 |
bin/nutch sitemap, запущенный явно по crawldb | загружен | 2/2 записей injected, полный recall |
Режим известных файлов -kf у katana, тот же стенд, на IP-хосте | не зафиксировано | 0/2 |
Это другой подход по сравнению с краулерами, которые подхватывают известные файлы прямо в процессе, и за него приходится платить отдельной командой, но свою задачу он выполняет полностью.
Два менее заметных поведения тоже показали себя хорошо.
Обработка ошибок: обход страницы, которая ссылалась на 500 и 404, прошёл все раунды чисто, при этом всё равно загрузил все четыре страницы класса A и отдельно зафиксировал каждую ошибку:
| Ошибочный ответ, на который вела ссылка | Зафиксированное состояние crawldb |
|---|---|
| 500 | db_unfetched (можно повторить попытку) |
| 404 | db_gone |
Ничего не сломалось.
Вежливость обхода: при одном потоке на очередь интервал между запросами к одному и тому же хосту соответствовал настройке:
fetcher.server.delay | Медианный интервал между запросами к одному хосту |
|---|---|
| 1.0 секунда | 1.009 с (минимум 1.006 с) |
| 0.0 | 0.002 с |
Регулятор делает именно то, что обещает. Значение по умолчанию — 5.0 секунд, что консервативно и, опять же, вполне разумно для инструмента, который должен аккуратно обходить чужие серверы.
Цена пакетного режима, в секундах
Каждая команда Nutch — это новый JVM-процесс. Именно этот факт сильнее всего определяет профиль времени, гораздо сильнее, чем сам процесс загрузки страниц.
| Фаза (за раунд) | Медиана, секунды |
|---|---|
inject (один раз) | 1.81 |
generate | 3.93 |
fetch | 2.82 |
parse | 1.78 |
updatedb | 1.81 |
| Один полный раунд | 12.14 |
Минимальный порог на один job — старт JVM плюс инициализация Hadoop, измеренные как самая дешёвая фаза с тривиальной работой, — примерно 1.77 секунды. Умножьте это на четыре команды в каждом раунде и добавьте начальный inject — и картина полного обхода выглядит так:
| Инструмент | Crawl глубины 4 по стенду из 12 страниц | Процессы |
|---|---|---|
| Nutch | примерно 45 секунд (я измерил 45.8 с и 45.0 с в двух конфигурациях) | около 17 запусков JVM, почти без сетевой работы |
katana в режиме standard, тот же стенд | около 13 секунд | один процесс |
Разница здесь не в пропускной способности загрузки; оба инструмента запрашивают один и тот же небольшой набор страниц. Разница архитектурная. Nutch платит фиксированную цену за процесс на каждую фазу, потому что эти фазы спроектированы как MapReduce jobs. На маленьком локальном обходе накладные расходы доминируют. При большом объёме эта фиксированная цена должна занимать меньшую долю, но этот тест не измерял масштаб, на котором Nutch и katana сравниваются в ноль, и не проверял, меняется ли соотношение.
Плюсы и минусы
Плюсы
- Детерминированное статическое обнаружение: 4/4 страниц класса HTML, 3/3 в цепочке глубины, одинаково в трёх повторных прогонах.
parse-jsизвлекает endpoint-ы из литералов в JavaScript-файле (2/2) без браузера, ловя и форму с аргументом вызова, и форму с присваиванием.- Два проверенных способа жёстко ограничить область обхода (
db.ignore.external.linksи host-правило вregex-urlfilter). - Инжест sitemap через
bin/nutch sitemapдал полный recall 2/2 для endpoint-ов, которые обычный crawl полностью пропускал. - Устойчивость к ошибкам: 500 и 404 обрабатываются раздельными состояниями crawldb, обход продолжается.
- В этом локальном прогоне наблюдаемый интервал между запросами к одному хосту соответствовал заданной задержке 1.0 секунды; значение по умолчанию — 5.0 секунд.
- Apache-2.0, активно поддерживается, 78 плагинов и постоянный crawldb, который хранит состояние по каждому URL между раундами.
- Работает в локальном режиме без кластера, без HDFS и без обязательного Solr.
Минусы
- Не запускается на JDK 24 и новее, где ломает удаление SecurityManager (я зафиксировал сбой на 26.0.1) — bundled Hadoop 3.4.2 предшествует upstream-исправлению, а аварийный флаг исчез, так что закреплённый LTS JDK — это жёсткое требование, а не предпочтение.
- ≈396 МБ после распаковки, 188 jar-файлов библиотек, 78 каталогов плагинов, 35 конфигурационных файлов.
- Новый JVM-процесс на каждую команду означает около 1.77 с фиксированных затрат на фазу; ~45 с на crawl глубины 4 по 12 страницам против ~13 с у однобинарного краулера на тех же данных.
- Стандартная поставка следует по внешним ссылкам; чтобы оставаться на одном сайте, это нужно включать явно.
http.agent.nameпоставляется пустым, и fetcher отказывается работать, пока вы его не зададите.- Отдельного флага глубины нет — глубина это число циклов, которое вы сами управляете.
- Endpoint-ы, появляющиеся только в DOM после выполнения JS, не были достигнуты ни в одной протестированной конфигурации, а подмена на протокол с выполнением JS не была заменой «вставил и заработало».
- Я тестировал локальный режим на одном хосте и небольшом стенде. Распределённый/HDFS-режим, индексация в Solr, hostdb, resume и инкрементальное переползание по сайту выходят за рамки этого прогона — считайте их здесь не проверенными, а не одобренными.
Кому он подходит, а кому лучше пройти мимо
Nutch оправдывает себя там, где сам обход — самая сложная часть. Если вы строите поисковый индекс, запускаете широкий многодоменный crawl, вам нужна постоянная база URL с состоянием и семантикой повторных попыток, или вы заранее предполагаете распределение работы между машинами, то это инфраструктура, которая делает именно эту задачу с тех времён, когда большинства альтернатив ещё не было. Плагинная система позволяет менять поведение протокола, парсера, фильтра и скоринга без форка. Настройки вежливости по умолчанию достаточно консервативны, что говорит о том, что разработчики действительно думали о корректном поведении инструмента в чужих сетях.
Лучше пройти мимо, если вам нужны структурированные данные всего с нескольких страниц. Nutch их загрузит и распарсит, а потом отдаст вам crawldb и segments и будет ждать, что индексатор вы принесёте сами. Проходите мимо, если ваши цели — SPA с клиентским рендерингом: класс C не был достигнут ни в одном прогоне. Проходите мимо, если в вашей команде вообще не используется JVM, потому что тогда вам придётся добавлять Java toolchain, закреплённый LTS JDK и 396 МБ jar-файлов в стек, где этого ничего нет. А если задача звучит как «раз в неделю обойти один сайт на четыре уровня глубины», вы потратите больше времени на цикл раундов и конфигурационные файлы, чем этого обхода заслуживает.
Для большинства людей, ищущих scraper, именно это и есть реальный сценарий. И это не критика Nutch — это просто несоответствие инструмента и задачи. Если хотите понять более широкий рынок, наш обзор open-source scraper-ов и лучшие GitHub-проекты для web scraping подробнее покрывают более лёгкий сегмент.
Альтернативы, включая то, где в этом ряду находится наш стек
Сначала честная рамка: Nutch бесплатен, имеет Apache-лицензию, self-hosted, и вы можете запускать его сколько угодно без платы за запрос. Это реальное преимущество, и ничто ниже его не отменяет.
Связанный обзор: Обзор Browsertrix Crawler.
В open-source-мире сравнение зависит от того, что именно вы оптимизируете. Если вам нужен Python-фреймворк с управлением обходом и request-first-подходом, Scrapy для многих проектов ближе по духу; в этой статье его установочный footprint по той же методике не измерялся. Если нужен компактный Go-краулер без браузера, Colly — ещё один вариант для оценки. Если ваша задача — превращать страницы в контент, готовый для LLM, а не находить URL, то Crawl4AI нацелен на другой слой.
Управляемый сервис вроде Thunderbit переносит загрузку, рендеринг и извлечение за API, а Nutch оставляет состояние обхода и инфраструктуру под вашим контролем. Thunderbit на этом стенде не запускался, так что это сравнение моделей владения, а не утверждение о равном recall или сопоставимой работе на динамических страницах.
Компромисс здесь — контроль против накладных расходов, и он вполне очевиден. Nutch даёт полный контроль, постоянный crawldb, масштабирование на кластер по дизайну и нулевую маржинальную стоимость — в обмен на JVM, закреплённый LTS JDK, 396 МБ jar-файлов, цикл по раундам и собственный индексирующий слой. Управляемый API даёт структурированный результат с первого запроса и не требует инфраструктуры — в обмен на оплату за вызов и меньший контроль над frontier обхода. Если ваша задача — «проиндексировать 50 миллионов страниц», модель Nutch правильная, а API было бы абсурдно использовать. Если задача — «получить структурированные записи с 200 карточек товара к четвергу», то верно обратное.
Попробовать Thunderbit для извлечения веб-данных
Итог
Apache Nutch стоит рассматривать, если вы ведёте постоянный многодоменный crawl и уже используете JVM-инфраструктуру. На этом стенде статическое обнаружение было детерминированным во всех повторах, parse-js нашёл оба literal endpoint-а в JavaScript, ошибки оставались представлены в crawldb, а интервалы между запросами соответствовали заданной задержке.
Честно оцените порог входа. У меня Nutch 1.22 не запустился на JDK 26.0.1; OpenJDK 17.0.20 — это LTS-конфигурация, которую я действительно проверил в этом обзоре, а Java 21 не тестировалась. Затем задайте http.agent.name, явно определите scope и учитывайте наблюдаемый фиксированный порог примерно 1.77 секунды на фазу в этом небольшом локальном прогоне. Насколько такой обмен оправдан, зависит от длительности обхода, его ширины и необходимости в постоянном состоянии.
Попробовать Thunderbit для извлечения веб-данных Get Started Free
FAQ
Почему Apache Nutch падает с сообщением "getSubject is not supported"?
На JDK 24 и новее JEP 486 сделал Subject.getSubject() безусловно выбрасывающим исключение, а bundled Hadoop 3.4.2 всё ещё вызывал его. Поэтому первый Hadoop job падает ещё до загрузки какой-либо страницы, а старый обходной флаг -Djava.security.manager=allow больше не запускает JVM. Используйте проверенную конфигурацию на Java 17 и задайте NUTCH_JAVA_HOME; Java 21, возможно, тоже поддерживается, но в этом обзоре полный цикл на ней не прогонялся.
На какой версии Java лучше запускать Nutch 1.22?
Самый безопасный ответ — Java 17: именно её целит CI самого Nutch, и у меня она работала без проблем на 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, Nutch нашёл оба endpoint-а, которые существовали только как строковые литералы внутри подключаемого JavaScript-файла — 2/2, без браузера. Без этого набора плагинов он не нашёл ни одного. Но endpoint, который появляется только после выполнения JavaScript и изменения DOM, остался недостижимым во всех статических конфигурациях, которые я тестировал, а замена на протокол HtmlUnit в моём прогоне не оказалась простым drop-in. Для клиентских SPA планируйте JS-исполняющий протокол плюс реальную настройку — или выберите другой инструмент.
Нужны ли для Nutch отдельно Hadoop и Solr?
Нет. В локальном режиме используется встроенный Hadoop LocalJobRunner — без кластера, без HDFS-daemon, без YARN — и весь цикл inject → generate → fetch → parse → updatedb работает на одной машине без дополнительной установки. Solr — обычная цель для индексации, но сам обход его не требует. При этом Hadoop jar-файлы встроены в поставку (13 штук, версия 3.4.2), и именно поэтому вообще возникает проблема совместимости с JDK.
Как запретить Nutch ходить на другие сайты?
Задайте это явно, потому что стандартное значение этого не делает. В Nutch 1.22 по умолчанию стоит db.ignore.external.links=false вместе с разрешающим URL-фильтром, и в моём тесте обычный crawl перешёл по ссылке на другой хост и действительно её загрузил. Либо установите db.ignore.external.links=true в nutch-site.xml, либо добавьте правило для хоста в conf/regex-urlfilter.txt (например, +^https://example\.com/, а затем -.). Оба способа полностью удержали обход в пределах сайта, что было подтверждено и по crawldb самого Nutch, и по логам запросов на другом сервере.


