Каковы плюсы и минусы ведущих HTML-парсеров Java?
Ища SO и Google, я обнаружил, что есть несколько парсеров Java HTML, которые последовательно рекомендуются различными сторонами. К сожалению, трудно найти какую-либо информацию о сильных и слабых сторонах различных библиотек. Я надеюсь, что некоторые люди потратили немного времени на сравнение этих библиотек и могут поделиться тем, что они узнали.
Вот что я видел:
И если есть основной парсер, который я пропустил, я бы тоже хотел узнать о его плюсах и минусах.
Спасибо!
6 ответов
генеральный
Почти все известные анализаторы HTML реализуют DOM API W3C (часть JAXP API, Java API для обработки XML) и дают вам org.w3c.dom.Document
обратно, который готов для прямого использования API JAXP. Основные различия обычно заключаются в особенностях рассматриваемого синтаксического анализатора. Большинство синтаксических анализаторов в некоторой степени прощают и снисходительно относятся к плохо сформированному HTML ("tagsoup"), например, к JTidy, NekoHTML, TagSoup и HtmlCleaner. Вы обычно используете этот вид HTML-парсеров, чтобы "привести в порядок" исходный HTML-код (например, заменить действительный HTML-код). <br>
по XML-действительному <br />
), так что вы можете пройти его "обычным способом" с помощью W3C DOM и JAXP API.
Единственные, которые выскакивают - это HtmlUnit и Jsoup.
HtmlUnit
HtmlUnit предоставляет полностью собственный API, который дает вам возможность программно вести себя как веб-браузер. Т.е. введите значения формы, щелкните элементы, вызовите JavaScript и т. Д. Это намного больше, чем один HTML-парсер. Это настоящий "веб-браузер без GUI" и инструмент для модульного тестирования HTML.
Jsoup
Jsoup также предоставляет полностью собственный API. Это дает вам возможность выбирать элементы, используя jQuery- подобные CSS-селекторы, и предоставляет удобный API для обхода дерева HTML DOM, чтобы получить интересующие элементы.
В частности, обход HTML DOM-дерева является основной сильной стороной Jsoup. Те, кто работал с org.w3c.dom.Document
знать, что за чертовщина мучает пересекать DOM, используя многословный NodeList
а также Node
API-интерфейсы. Правда, XPath
делает жизнь проще, но, тем не менее, это еще одна кривая обучения, и она может оказаться все еще многословной.
Вот пример, который использует "простой" W3C DOM-парсер, такой как JTidy, в сочетании с XPath для извлечения первого абзаца вашего вопроса и имен всех ответчиков (я использую XPath, так как без него код необходим для сбора интересующей информации иначе вырастет в 10 раз больше, без написания вспомогательных / вспомогательных методов).
String url = "http://stackru.com/questions/3152138";
Document document = new Tidy().parseDOM(new URL(url).openStream(), null);
XPath xpath = XPathFactory.newInstance().newXPath();
Node question = (Node) xpath.compile("//*[@id='question']//*[contains(@class,'post-text')]//p[1]").evaluate(document, XPathConstants.NODE);
System.out.println("Question: " + question.getFirstChild().getNodeValue());
NodeList answerers = (NodeList) xpath.compile("//*[@id='answers']//*[contains(@class,'user-details')]//a[1]").evaluate(document, XPathConstants.NODESET);
for (int i = 0; i < answerers.getLength(); i++) {
System.out.println("Answerer: " + answerers.item(i).getFirstChild().getNodeValue());
}
И вот пример, как сделать то же самое с Jsoup:
String url = "http://stackru.com/questions/3152138";
Document document = Jsoup.connect(url).get();
Element question = document.select("#question .post-text p").first();
System.out.println("Question: " + question.text());
Elements answerers = document.select("#answers .user-details a");
for (Element answerer : answerers) {
System.out.println("Answerer: " + answerer.text());
}
Вы видите разницу? Это не только меньше кода, но Jsoup также относительно легко понять, если у вас уже есть умеренный опыт работы с CSS-селекторами (например, разработка веб-сайтов и / или использование jQuery).
Резюме
Плюсы и минусы каждого должны быть достаточно ясны сейчас. Если вы просто хотите использовать стандартный JAXP API для его обхода, перейдите к первой упомянутой группе анализаторов. Их довольно много. Какой из них выбрать, зависит от того, какие функции он предоставляет (насколько легко для вас выполняется очистка HTML? Есть ли прослушиватели / перехватчики и очистители для тегов?) И надежности библиотеки (как часто она обновляется / поддерживается / исправляется?). Если вам нравится модульное тестирование HTML, то HtmlUnit - это то, что вам нужно. Если вам нравится извлекать конкретные данные из HTML (что чаще всего является требованием реального мира), то Jsoup - это то, что вам нужно.
В этой статье сравниваются некоторые аспекты следующих парсеров:
- NekoHTML
- JTidy
- TagSoup
- HtmlCleaner
Это ни в коем случае не полное резюме, и это с 2008 года. Но вы можете найти это полезным.
Я обнаружил, что HTML-анализатор Jericho очень хорошо написан, постоянно обновляется (чего нет у многих анализаторов), нет зависимостей и прост в использовании.
Добавьте в свой список HTML-анализатор validator.nu, реализацию алгоритма синтаксического анализа HTML5 в Java.
С другой стороны, он специально разработан для соответствия HTML5 и лежит в основе валидатора HTML5, поэтому с высокой вероятностью будет соответствовать поведению синтаксического анализа будущего браузера с очень высокой степенью точности.
С другой стороны, устаревший синтаксический анализ браузеров не работает в точности так, как этот, и, поскольку HTML5 все еще находится в стадии разработки, он может быть изменен.
На практике такие проблемы влияют только на непонятные угловые случаи и для всех практических целей являются отличным парсером.
Я просто добавлю к ответу @MJB после работы с большинством библиотек разбора HTML в Java, здесь пропущен огромный аргумент pro/con: парсеры, которые сохраняют форматирование и некорректность HTML при вводе и выводе.
То есть большинство анализаторов, когда вы изменяете документ, стирают пробелы, комментарии и некорректность DOM, особенно если они представляют собой XML-подобную библиотеку.
Иерихон - единственный из известных мне анализаторов, который позволяет вам манипулировать неприятным HTML, сохраняя при этом форматирование пробелов и некорректность HTML (если таковые имеются).
Два других варианта - это HTMLCleaner и HTMLParser.
Я перепробовал большинство синтаксических анализаторов, которые я разработал. Я использую HTMLCleaner для основной массы работ по извлечению данных. Это связано с тем, что он поддерживает достаточно современный диалект HTML, XHTML, HTML 5 с пространствами имен и поддерживает DOM, поэтому его можно использовать со встроенной реализацией Java в XPath.
С HTMLCleaner сделать это намного проще, чем с некоторыми другими анализаторами: JSoup, например, поддерживает DOM-подобный интерфейс, а не DOM, поэтому требуется некоторая сборка. Иерихон имеет интерфейс SAX-line, так что, опять же, он требует некоторой работы, хотя у Sujit Pal есть хорошее описание того, как это сделать, но в итоге HTMLCleaner просто работал лучше.
Я также использую HTMLParser и Jericho для задачи извлечения таблиц, которая заменила некоторый код, написанный с использованием Perl libhtml-tableextract-perl. Я использую HTMLParser для фильтрации HTML-кода для таблицы, а затем использую Jericho для его анализа. Я согласен с замечаниями MJB и Адама, что Иерихон хорош в некоторых случаях, потому что он сохраняет основной HTML. Он имеет своего рода нестандартный интерфейс SAX, поэтому для XPath лучше использовать HTMLCleaner.
Синтаксический анализ HTML в Java представляет собой удивительно сложную проблему, так как кажется, что все синтаксические анализаторы борются с некоторыми типами искаженного содержимого HTML.