一尘不染

领先的Java HTML解析器的优缺点是什么?

java

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

这是我所看到的:

  • JTidy
  • NekoHTML
  • jsoup
  • TagSoup

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

谢谢!


阅读 590

收藏
2020-02-26

共1个答案

一尘不染

General

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

唯一跳出来的是HtmlUnit和Jsoup。

HtmlUnit

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

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

特别是遍历HTML DOM树是Jsoup的主要优势。与之共事的人org.w3c.dom.Document知道使用冗长的API NodeList和遍历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是你的最佳选择。

2020-02-26