Java HTML解析

52

我正在开发一个应用程序,该应用程序从网站上抓取数据,我想知道如何获取数据。具体来说,我需要包含在许多使用特定CSS类的div标签中的数据 - 目前(出于测试目的)我只是检查

div class = "classname"

在HTML的每一行中-这个方法是有效的,但我觉得可能有更好的解决方案。

是否有一种优雅的方式,我可以给一个HTML行添加一个类,并使用一些好用的方法,例如:

boolean usesClass(String CSSClassname);
String getText();
String getLink();

11个回答

60

另一个在处理HTML方面可能有用的库是jsoup。 Jsoup试图清理格式不正确的HTML,并使用类似于jQuery的标签选择器语法允许Java进行HTML解析。

http://jsoup.org/


有没有不需要使用外部jar包的方法? - Futuregeek
1
@Futuregeek 我以前用正则表达式,直到我读了这个答案 - Kartik Chugh

20
在之前的评论中提到的主要问题是HTML格式不正确,因此必须使用HTML清理器或HTML-XML转换器。一旦获取了XML代码(XHTML),就有很多工具可以处理它。您可以使用简单的SAX处理程序仅提取所需数据,或者任何基于树的方法(DOM、JDOM等)甚至让您修改原始代码。
以下是使用HTML清理器的示例代码,以获取所有使用特定类的DIV,并打印出其中所有文本内容。
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;

/**
 * @author Fernando Miguélez Palomo <fernandoDOTmiguelezATgmailDOTcom>
 */
public class TestHtmlParse
{
    static final String className = "tags";
    static final String url = "http://www.stackoverflow.com";

    TagNode rootNode;

    public TestHtmlParse(URL htmlPage) throws IOException
    {
        HtmlCleaner cleaner = new HtmlCleaner();
        rootNode = cleaner.clean(htmlPage);
    }

    List getDivsByClass(String CSSClassname)
    {
        List divList = new ArrayList();

        TagNode divElements[] = rootNode.getElementsByName("div", true);
        for (int i = 0; divElements != null && i < divElements.length; i++)
        {
            String classType = divElements[i].getAttributeByName("class");
            if (classType != null && classType.equals(CSSClassname))
            {
                divList.add(divElements[i]);
            }
        }

        return divList;
    }

    public static void main(String[] args)
    {
        try
        {
            TestHtmlParse thp = new TestHtmlParse(new URL(url));

            List divs = thp.getDivsByClass(className);
            System.out.println("*** Text of DIVs with class '"+className+"' at '"+url+"' ***");
            for (Iterator iterator = divs.iterator(); iterator.hasNext();)
            {
                TagNode divElement = (TagNode) iterator.next();
                System.out.println("Text child nodes of DIV: " + divElement.getText().toString());
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

18

几年前我用JTidy完成了同样的工作:

http://jtidy.sourceforge.net/

"JTidy是HTML Tidy的Java端口,是一个HTML语法检查器和美化程序。像其非Java表亲一样,JTidy可用作清理格式不正确和错误的HTML的工具。此外,JTidy提供了对正在处理的文档的DOM接口,这使您能够将JTidy用作实际 HTML 文档的 DOM 解析器。

JTidy由Andy Quick编写,后来他辞去了维护者的职位。现在,JTidy由一群志愿者维护。

有关JTidy的更多信息可以在JTidy SourceForge项目页面上找到。"


2
遗憾的是,jtidy非常慢。 - PlexQ
JTidy 似乎是一个被放弃的项目,已经好几年没有更新了。 - rlegendi

13

您可能会对TagSoup感兴趣,它是一个Java HTML解析器,能够处理格式不正确的HTML。XML解析器只能处理格式正确的XHTML。


5

5
HTMLParser项目(http://htmlparser.sourceforge.net/)可能是一个选择。它似乎相当擅长处理格式错误的HTML。以下代码片段应该可以满足您的需求:
Parser parser = new Parser(htmlInput);
CssSelectorNodeFilter cssFilter = 
    new CssSelectorNodeFilter("DIV.targetClassName");
NodeList nodes = parser.parse(cssFilter);

4

不要忘记 Jerry,它是Java中的jQuery:一个快速且简洁的Java库,简化了HTML文档解析、遍历和操作;包括使用css3选择器。

示例:

Jerry doc = jerry(html);
doc.$("div#jodd p.neat").css("color", "red").addClass("ohmy");

例子:

doc.form("#myform", new JerryFormHandler() {
    public void onForm(Jerry form, Map<String, String[]> parameters) {
        // process form and parameters
    }
});

当然,这只是一些快速的示例,来让您感受它们的外观。

虽然这个链接可能回答了问题,但最好在此处包含答案的基本部分并提供参考链接。如果链接页面更改,仅有链接的答案可能会失效。 - Engineer2021
1
谢谢,已添加示例。我在大多数其他评论中没有看到示例,所以我遵循了相同的模式。 - igr
没问题。它出现在低质量队列中。我的评论是由SO自动完成的。 - Engineer2021

4

3
nu.validator项目是一个优秀的高性能HTML解析器,严格遵循正确性原则。该解析器采用Java实现了HTML5解析算法,并被设计成XML解析器的即插即用替代品,与使用SAX、DOM或XOM接口的应用程序兼容,可为希望自行执行IO并支持document.write()脚本的应用程序提供低级别功能。该解析器核心基于Google Web Toolkit编译,可自动转换为C++(目前已将C++翻译能力用于将解析器端口到Gecko)。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接