【发布时间】:2011-03-10 06:58:32
【问题描述】:
搜索 SO 和 Google,我发现有一些 Java HTML 解析器,各方一致推荐。不幸的是,很难找到有关各种库的优缺点的任何信息。我希望有人花一些时间比较这些库,并且可以分享他们学到的东西。
这是我看到的:
如果我错过了一个主要的解析器,我也很想听听它的优缺点。
谢谢!
【问题讨论】:
搜索 SO 和 Google,我发现有一些 Java HTML 解析器,各方一致推荐。不幸的是,很难找到有关各种库的优缺点的任何信息。我希望有人花一些时间比较这些库,并且可以分享他们学到的东西。
这是我看到的:
如果我错过了一个主要的解析器,我也很想听听它的优缺点。
谢谢!
【问题讨论】:
将The validator.nu HTML Parser(Java 中 HTML5 解析算法的实现)添加到您的列表中。
从好的方面来说,它是专门为匹配 HTML5 而设计的,并且是 HTML5 验证器的核心,因此很有可能以非常高的准确度匹配未来浏览器的解析行为。
不利的一面是,没有浏览器的旧版解析完全像这样工作,而且 HTML5 仍处于草稿阶段,可能会发生变化。
在实践中,此类问题只会影响晦涩的极端情况,并且出于所有实际目的,它是一个出色的解析器。
【讨论】:
【讨论】:
我发现Jericho HTML Parser 写得非常好,保持最新(许多解析器没有),没有依赖关系,并且易于使用。
【讨论】:
几乎所有已知的 HTML 解析器都实现了 W3C DOM API(JAXP API 的一部分,用于 XML 处理的 Java API),并为您提供了一个 org.w3c.dom.Document 返回,可供 JAXP API 直接使用。主要差异通常可以在所讨论的解析器的特性中找到。大多数解析器在一定程度上对非格式良好的 HTML(“tagsoup”)宽容和宽容,例如 JTidy、NekoHTML、TagSoup 和 HtmlCleaner。您通常使用这种 HTML 解析器来“整理”HTML 源代码(例如,将 HTML 有效的 <br> 替换为 XML 有效的 <br />),以便您可以使用 W3C DOM 以“通常的方式”遍历它和 JAXP API。
HtmlUnit 提供了一个完全自己的 API,让您可以像网络浏览器一样编程。 IE。输入表单值、单击元素、调用 JavaScript 等。它不仅仅是一个 HTML 解析器。这是一个真正的“无 GUI 网络浏览器”和 HTML 单元测试工具。
Jsoup 还提供了完全自己的 API。它使您可以使用jQuery 来选择元素,就像CSS selectors 一样,并提供了一个巧妙的 API 来遍历 HTML DOM 树以获取感兴趣的元素。
特别是HTML DOM树的遍历是Jsoup的主要优势。使用过org.w3c.dom.Document 的人都知道使用冗长的NodeList 和Node API 遍历DOM 是多么痛苦。诚然,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 来遍历它,那么请使用第一个提到的解析器组。其中有漂亮的a lot。选择哪一个取决于它提供的功能(HTML 清理如何让您轻松?是否有一些侦听器/拦截器和特定于标签的清理器?)以及库的健壮性(它多久更新/维护/修复? )。如果您喜欢对 HTML 进行单元测试,那么 HtmlUnit 是您的最佳选择。如果您想从 HTML 中提取特定数据(这通常是现实世界的要求),那么 Jsoup 就是您的最佳选择。
【讨论】:
Jsoup 很好。我试图将它与另一个使用org.w3c.dom.* API 的模块连接。发现Jsoup不遵守org.w3c.dom.*合约
在使用 Java 中的大多数 HTML 解析库之后,我将添加到 @MJB 答案,有一个巨大的优点/缺点被省略:在输入和输出中保留 HTML 格式和不正确性的解析器。
当您更改文档时,大多数解析器会清除 DOM 的空白、cmets 和不正确性,尤其是当它们是类似 XML 的库时。
Jericho 是我所知道的唯一一个解析器,它允许您操作讨厌的 HTML,同时保留空白格式和 HTML 的不正确性(如果有的话)。
【讨论】:
另外两个选项是HTMLCleaner 和HTMLParser。
我已经尝试了这里的大多数解析器,用于我一直在开发的爬虫/数据提取框架。我使用 HTMLCleaner 进行大部分数据提取工作。这是因为它支持带有命名空间的 HTML、XHTML、HTML 5 的相当现代的方言,并且它支持 DOM,因此可以use it with Java's built in XPath implementation。
使用 HTMLCleaner 比其他一些解析器更容易做到这一点:例如 JSoup 支持类似 DOM 的接口,而不是 DOM,因此需要一些组装。 Jericho 有一个 SAX-line 接口,所以虽然 Sujit Pal has a good description of how to do this 需要一些工作,但最终 HTMLCleaner 工作得更好。
我还使用 HTMLParser 和 Jericho 进行表格提取任务,它取代了一些使用 Perl 的 libhtml-tableextract-perl 编写的代码。我使用 HTMLParser 过滤表格的 HTML,然后使用 Jericho 解析它。我同意 MJB 和 Adam 的观点,即 Jericho 在某些情况下很好,因为它保留了底层的 HTML。它有一种非标准的 SAX 接口,所以对于 XPath 处理 HTMLCleaner 更好。
在 Java 中解析 HTML 是一个令人惊讶的难题,因为所有解析器似乎都在努力处理某些类型的格式错误的 HTML 内容。
【讨论】: