最新的Java HTML解析器的优缺点是什么?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (3)
  • 关注 (0)
  • 查看 (212)

搜索SO和Google,我发现有一些JavaHTML解析器,它们一直被各方推荐。不幸的是,很难找到关于各种库的优点和弱点的任何信息。我希望有些人已经花了一些时间比较这些库,并能分享他们所学到的东西。

我看到的是:

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

谢谢

提问于
用户回答回答于

另外两个选项是HTMLCleaner and HTMLParser...

我已经尝试了这里的大多数解析器作为我一直在开发的爬虫/数据提取框架。我使用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内容上苦苦挣扎。

用户回答回答于

将validator.nu HTML Parser添加到您的列表中,在Java中实现HTML 5解析算法。

从好的方面来说,它是专为匹配HTML 5而设计的,并且是HTML 5验证器的核心,因此很有可能以非常高的精确度匹配未来浏览器的解析行为。

负面的一面是,没有浏览器的遗留解析完全是这样工作的,而且HTML 5还在草稿中,可能会有变化。

在实践中,这些问题只会影响模糊的角落案例,对于所有实际目的来说,都是一个优秀的解析器。

用户回答回答于

一般

几乎所有已知的HTML解析器都实现了W3C DOM API(JAXPAPI的一部分,用于XML处理的JavaAPI),并给出org.w3c.dom.DocumentBack,它已准备好供JAXPAPI直接使用。主要的区别通常在解析器的特性中找到。大多数解析器在某种程度上是宽容的,并且对格式不正确的HTML(“tagsoup”)很宽容,就像JTidyNekoHTMLTagSoupHtmlCleaner.您通常使用这种HTML解析器来“整理”HTML源代码(例如,替换HTML-Valid)。<br>由xml-有效<br />),以便您可以使用W3CDOM和JAXPAPI来遍历它。

唯一跳出来的是HtmlUnit and Jsoup.

HtmlUnit

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

Jsoup

Jsoup还提供了一个完全自己的API。它使您可以使用jQuery-喜欢CSS选择器并提供了一个灵活的API来遍历HTMLDOM树以获得感兴趣的元素。

特别是HTML DOM树的遍历是JSOUP的主要优势。曾与之共事的人org.w3c.dom.Document知道用冗长的文字遍历DOM是多么痛苦NodeList and NodeAPI。是真的,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),那么JSOUP也相对容易掌握。

扫码关注云+社区

领取腾讯云代金券