领先的 JavaHTML 解析器的优点和缺点是什么?

通过搜索 SO 和 Google,我发现有一些 JavaHTML 解析器一直受到各方的推荐。不幸的是,很难找到关于各种图书馆优缺点的任何信息。我希望有些人已经花了一些比较这些图书馆,并可以分享他们所学到的东西。

以下是我所看到的:

如果我错过了一个主要的解析器,我也想听听它的优缺点。

谢谢!

59080 次浏览

在列表中添加 Nu HTML 解析器,它是 Java 中 HTML5解析算法的一个实现。

从好的方面来说,它是专门设计来匹配 HTML5的,而且是 HTML5验证器的核心,所以很可能与未来浏览器的解析行为相匹配,达到非常高的准确度。

不利的一面是,没有浏览器的遗留解析工作完全像这样,因为 HTML5仍处于草案阶段,可能会有变化。

在实践中,这样的问题只影响模糊的角落情况,并为所有的实际目的,一个优秀的解析器。

本文 比较了以下解析器的某些方面:

  • 网络超文本标记语言
  • JTidy
  • 泰格汤
  • 清洁工

这绝不是一个完整的总结,它是从2008年。但你可能会发现它有帮助。

我发现 Jericho HTML 解析器编写得非常好,保持最新(很多解析器都没有) ,没有依赖性,而且易于使用。

将军

几乎所有已知的 HTML 解析器都实现了 W3C DOM API(JAXP API 的一部分,JAXP) ,并返回一个可供 JAXP API 直接使用的 org.w3c.dom.Document。主要的差异通常可以在所讨论的解析器的特性中找到。大多数解析器在一定程度上对非良好格式的 HTML (“标签汤”)比较宽容,比如 JTidy网络超文本标记语言泰格汤清洁工。您通常使用这种 HTML 解析器来“整理”HTML 源代码(例如,将 HTML 有效的 <br>替换为 XML 有效的 <br />) ,这样您就可以使用 W3C DOM 和 JAXP API“通常的方式”遍历它。

唯一突出的是 HtmlUnit

HtmlUnit

HtmlUnit 提供了一个完全属于自己的 API,让您可以以编程方式像一个网络浏览器那样工作。例如,输入表单值,单击元素,调用 JavaScript 等等。它不仅仅是一个 HTML 解析器。这是一个真正的“无 GUI 的网络浏览器”和 HTML 单元测试工具。

Jsoup 还提供了一个完全自己的 API。它提供了使用类似 JQueryCSS 选择器选择元素的可能性,并提供了一个漂亮的 API 来遍历 HTML DOM 树以获得感兴趣的元素。

特别是遍历 HTML DOM 树是 Jsoup 的主要优势。使用过 org.w3c.dom.Document的人知道使用冗长的 NodeListNode API 遍历 DOM 是多么痛苦。的确,XPath使生活变得更容易,但是,它仍然是另一个学习曲线,最终可能仍然冗长。

这里有一个例子,它使用一个“普通的”W3C DOM 解析器,比如 JTidy,结合 XPath 来提取问题的第一段和所有答案的名称(我使用 XPath 是因为如果没有它,收集感兴趣的信息所需的代码会增长10倍,而不需要编写实用程序/助手方法)。

String url = "http://stackoverflow.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://stackoverflow.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());
}

你看出区别了吗?它不仅代码少,而且如果你已经对 CSS 选择器有了一定的经验(比如开发网站和/或使用 jQuery) ,那么掌握它也相对容易。

摘要

两者的利弊现在应该已经足够清楚了。如果您只想使用标准 JAXPAPI 来遍历它,那么可以使用前面提到的解析器组。他们有很多人。选择哪一个取决于它提供的特性(HTML 清理是如何简化的?是否有一些侦听器/拦截器和特定于标记的清除程序?)以及库的健壮性(它多久更新/维护/修复一次?).如果您喜欢对 HTML 进行单元测试,那么 HtmlUnit 就是最佳选择。如果您希望从 HTML 中提取特定的数据(这通常比现实世界中的要求更高) ,那么可以选择 Jsoup。

在使用了 Java 中的大多数 HTML 解析库之后,我将添加到@MJB 回答,这里省略了一个巨大的优缺点: 解析器保留了 HTML 在输入和输出上的格式和错误。

这就是大多数解析器在更改文档时会消除 DOM 的空格、注释和错误,特别是如果它们是类似 XML 的库。

Jericho 是我所知道的唯一一个允许您在保留空格格式和 HTML 错误(如果有的话)的同时操作讨厌的 HTML 的解析器。

另外两个选项是 HTMLCleanerHTMLParser

我已经尝试了这里的大多数解析器,用于我一直在开发的爬虫/数据提取框架。我使用 HTMLCleaner 进行大量的数据提取工作。这是因为它使用名称空间支持 HTML、 XHTML、 HTML5的一种相当现代的方言,并且它支持 DOM,所以 与 Java 内置的 XPath 实现一起使用它是可能的。

与其他一些解析器相比,使用 HTMLCleaner 做到这一点要容易得多: 例如,JSoup 支持类似 DOM 的接口,而不是 DOM,因此 需要组装一些东西。Jericho 有一个 SAX-line 接口,所以它需要一些工作,虽然 Sujit Pal 对如何做到这一点有很好的描述但最终 HTMLCleaner 只是工作得更好。

我还使用 HTMLParser 和 Jericho 执行表提取任务,它们替换了使用 Perl 的 表提取 -perl编写的一些代码。我使用 HTMLParser 过滤表的 HTML,然后使用 Jericho 解析它。我同意 MJB 和 Adam 的评论,Jericho 在某些情况下是好的,因为它保留了底层的 HTML。它有一种非标准的 SAX 接口,所以对于 XPath 处理来说,HTMLCleaner 更好。

在 Java 中解析 HTML 是一个出人意料的困难问题,因为所有的解析器似乎都难以处理某些类型的畸形 HTML 内容。