搜索SO和Google,我发现有一些Java HTML解析器一直被各方推荐。不幸的是,很难找到有关各种图书馆优势和劣势的任何信息。我希望有些人花了一些时间来比较这些库,并且可以分享他们所学到的东西。
这是我见过的:
如果有一个我错过的主要解析器,我也很想知道它的优点和缺点。
谢谢!
答案 0 :(得分:220)
几乎所有已知的HTML解析器都实现了W3C DOM API(JAXP API的一部分,用于XML处理的Java API),并为您提供了org.w3c.dom.Document
,可供JAXP API直接使用。主要差异通常在所讨论的解析器的功能中找到。对于非格式良好的HTML(“tagsoup”),大多数解析器都在某种程度上宽容和宽容,例如JTidy,NekoHTML,TagSoup和HtmlCleaner。您通常使用这种HTML解析器来“整理”HTML源代码(例如,用XML有效的<br>
替换HTML有效的<br />
),以便您可以“通常的方式”遍历它使用W3C DOM和JAXP API。
HtmlUnit提供了一个完全自己的API,使您可以通过编程方式像webbrowser一样工作。即输入表单值,单击元素,调用JavaScript等。它不仅仅是一个HTML解析器。它是一个真正的“无GUI的webbrowser”和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就是您的选择。
答案 1 :(得分:13)
答案 2 :(得分:7)
将Java中HTML5解析算法的实现The validator.nu HTML Parser添加到列表中。
从好的方面来说,它专门设计用于匹配HTML5,并且是HTML5验证器的核心,因此非常有可能将未来浏览器的解析行为与非常高的准确度相匹配。
从消极方面来看,没有任何浏览器的遗留解析工作与此完全相同,并且HTML5仍处于草案状态,可能会发生变化。
在实践中,这些问题只影响模糊的角落情况,并且出于所有实际目的,它是一个出色的解析器。
答案 3 :(得分:7)
我发现Jericho HTML Parser编写得非常好,保持最新(许多解析器都没有),没有依赖关系,并且易于使用。
答案 4 :(得分:6)
在使用Java中的大多数HTML解析库之后,我只会添加@MJB答案,有一个很大的pro / con被省略:解析器保留输入和输出上HTML的格式和错误。
当你更改文档时,大多数解析器会破坏DOM的空格,注释和不正确性,特别是如果它们是类似XML的库。
Jericho是我所知道的唯一一个解析器,允许你操作讨厌的HTML,同时保留空格格式和HTML的不正确性(如果有的话)。
答案 5 :(得分:3)
另外两个选项是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的评论,杰里科在某些情况下是好的,因为它保留了基础HTML。它有一种非标准的SAX接口,所以对于XPath处理,HTMLCleaner更好。
在Java中解析HTML是一个令人难以置信的难题,因为所有解析器似乎都难以处理某些类型的格式错误的HTML内容。