领先的Java HTML解析器的优缺点是什么?[关闭]


175

在搜索SO和Google时,我发现有一些Java HTML解析器一直受到各方的推荐。不幸的是,很难找到有关各种库的优缺点的任何信息。我希望有些人花了一些时间比较这些库,并可以分享他们所学到的知识。

这是我所看到的:

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

谢谢!

Answers:


224

一般

几乎所有已知的HTML解析器都实现了W3C DOM API(JAXP API的一部分,用于XML处理的Java API),并为您提供org.w3c.dom.Document了可直接用于JAXP API的支持。通常,主要的区别在于所讨论的解析器的功能。大多数解析器在某种程度上都宽容和宽容非格式的HTML(“ tagsoup”),例如JTidyNekoHTMLTagSoupHtmlCleaner。您通常使用这种HTML解析器来“整理” HTML源(例如,用<br>XML-valid替换HTML -valid <br />),以便可以使用W3C DOM和JAXP API“以通常的方式”遍历它。

唯一跳出来的是HtmlUnitJsoup

HtmlUnit

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

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

特别是遍历HTML DOM树是Jsoup的主要优势。与之共事的人都org.w3c.dom.Document知道使用冗长的APINodeList和遍历DOM到底是多么痛苦Node。没错,这XPath使生活变得更轻松,但仍然是另一条学习曲线,最终可能会变得冗长。

这是一个示例,该示例结合使用JTidy之类的“普通” W3C DOM解析器和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),则不仅代码更少,而且Jsoup也相对容易掌握。

概要

现在每个人的利弊都应该很清楚。如果您只想使用标准的JAXP API遍历它,那么请使用第一个提到的解析器组。有很多。选择哪个选项取决于它提供的功能(如何使HTML清理更容易?是否有一些侦听器/拦截器和特定于标记的清理器?)和库的健壮性(多久更新/维护/修复一次?)。 )。如果您想对HTML进行单元测试,那么HtmlUnit是您的最佳选择。如果您想从HTML中提取特定数据(这比现实世界中的要求通常要多),那么Jsoup是您的最佳选择。


这里省略了一个巨大的优点/缺点:Jericho是我所知道的唯一解析器,它允许您在保留空白格式和HTML不正确性(如果有)的同时操作讨厌的HTML。
亚当·根特

3
Jsoup很好。我试图将其与另一个与org.w3c.dom.*API一起使用的模块进行接口。发现Jsoup不遵守org.w3c.dom.*合同
Thamme·高达

13

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

  • NekoHTML
  • 泰迪
  • 标签汤
  • HtmlCleaner

它决不是一个完整的摘要,它是2008年的。但是您可能会发现它很有用。


这是仅链接的答案。您可以在此处添加相关详细信息吗?
恢复莫妮卡-notmaynard

7

将Validator.nu HTML Parser(Java中HTML5解析算法的实现)添加到列表中。

从好的方面来说,它是专门为匹配HTML5而设计的,并且是HTML5验证程序的核心,因此很有可能以非常高的准确性匹配将来的浏览器的解析行为。

不利的一面是,没有浏览器的旧版解析完全像这样,而且HTML5仍在草稿中,随时可能更改。

实际上,此类问题仅会影响晦涩的角落情况,并且对于所有实际目的而言,都是出色的解析器。


7

我发现Jericho HTML Parser编写得很好,保持最新(许多解析器不是),没有依赖关系,并且易于使用。


6

在使用Java中的大多数HTML解析库之后,我将仅添加到@MJB答案中,这里省略了一个巨大的pro / con:解析器保留了输入和输出上HTML的格式和不正确性。

多数情况下,当您更改文档时,解析器会浪费掉DOM的空格,注释和不正确性,尤其是当它们是类似XML的库时。

Jericho是我所知道的唯一一个解析器,它允许您在保留空白格式和HTML的不正确性(如果有)的同时操作讨厌的HTML。


3

另外两个选项是HTMLCleanerHTMLParser

我在这里尝试了大多数解析器,用于我一直在开发的搜寻器/数据提取框架。我将HTMLCleaner用于大部分数据提取工作。这是因为它支持具有命名空间的HTML,XHTML,HTML 5的相当现代的方言,并且支持DOM,因此可以将其与Java的内置XPath实现一起使用

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

我还将HTMLParser和Jericho用于表提取任务,该任务替换了一些使用Perl的libhtml-tableextract-perl编写的代码。我使用HTMLParser过滤表的HTML,然后使用Jericho对其进行解析。我同意MJB和Adam的观点,即Jericho在某些情况下是好的,因为它保留了底层HTML。它具有一种非标准的SAX接口,因此对于XPath处理HTMLCleaner更好。

用Java解析HTML是一个令人惊讶的难题,因为所有解析器似乎都在处理某些类型的格式错误的HTML内容。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.