JAVA开发常用类库--HTML解析库

dom解析是常用dom4j。android中我们常用的是sax、pull。因为它们更省内存。而html解析,则也有很多框架

java的HTML解析通常用在利用java做网页的垂直爬虫

HTML是WEB的核心,互联网中你看到的所有页面都是HTML,不管它们是由JavaScript,JSP,PHP,ASP或者是别的什么WEB技术动态生成的。你的浏览器会去解析HTML并替你去渲染它们。不过如果你需要自己在Java程序中解析HTML文档并查找某些元素,标签,属性或者检查某个特定的元素是否存在的话,那又该如何呢?如果你已经使用Java编程多年了,我相信你肯定试过去解析XML,也使用过类似DOM或者SAX这样的解析器,不过很有可能你从未进行过任何的HTML解析的工作。更讽刺的是,在Java应用中,很少会有需要你去解析HTML文档的时候,这里并不包括Servlet或者其它的Java WEB技术。更糟糕的是,JDK核心里也没有包括HTTP或者HTML的库,至少我并不知道有这个。这就是为什么一碰上解析HTML文件时,许多Java程序员就得先Google一下 ,看看如何在Java中取出一个HTML的标签。当我有这个需要的时候,我相信肯定会有一些开源库能实现这个,不过我没有想到竟然有JSoup这么酷的并且功能齐全的库。它不仅能支持读取并解析HTML文档,而且还能让你从HTML文件抽取出任何的元素,以及它们的属性,它们的CSS属性,你还能进它们进行修改。有了JSoup你简直可以对HTML文档做任何事情。我们将会看到如何在Java中从google主页或者任何URL中下载并解析HTML文件的示例。

一般来说,一个爬虫包括几个部分:

  • 页面下载

页面下载是一个爬虫的基础。下载页面之后才能进行其他后续操作。

  • 链接提取

一般爬虫都会有一些初始的种子URL,但是这些URL对于爬虫是远远不够的。爬虫在爬页面的时候,需要不断发现新的链接。

  • URL管理

最基础的URL管理,就是对已经爬过的URL和没有爬的URL做区分,防止重复爬取。

  • 内容分析和持久化

一般来说,我们最终需要的都不是原始的HTML页面。我们需要对爬到的页面进行分析,转化成结构化的数据,并存储下来。

不同的爬虫,对这几部分的要求是不一样的。

HTML分析是一个比较复杂的工作,Java世界主要有几款比较方便的分析工具:

  • Jsoup

Jsoup是一个集强大和便利于一体的HTML解析工具。它方便的地方是,可以用于支持用jquery中css selector的方式选取元素,这对于熟悉js的开发者来说基本没有学习成本。

Jsoup是一个开源的Java库,它可以用于处理实际应用中的HTML。它提供了非常便利的API来进行数据的提取及修改,充分利用了DOM,CSS以及jquery风格方法的长处。Jsoup实现了WAHTWG HTML5的规范,它从HTML解析出来的DOM和Chrome以及Firefox这样的现代浏览器解析出来的完全一致。下面是Jsoup库的一些有用的特性:

1.Jsoup可以从URL,文件,或者字符串中获取并解析HTML。
2.Jsoup可以查找并提取数据,可以使用DOM遍历或者CSS选择器。
3.你可以使用Jsoup来修改HTML元素,属性以及文本。
4.Jsoup通过一个安全的白名单确保了用户提交的内容是干净的,以防止XSS攻击。
5.Jsoup还能输出整洁的HTML。

在Java中使用Jsoup进行HTML解析

在这篇Java HTML解析的教程中,我们会看到在Java中使用Jsoup解析及遍历HTML的三个不同的示例。第一个例子中,我们会解析一个HTML字符串,它的内容就是Java中的字符串字面量组成的标签。第二个例子中,我们会从WEB中下载HTML文档,而第三个例子中,我们会加载一个HTML示例文件login.html来进行解析。这个文件是一个HTML文档的示例,它包含title标签,body里面有一个div标签,里面包含一个表单。它拥有input标签来用于获取用户名及密码,同时还有提交及重置的按钮用来进行下一步操作。它是一个正确有效的HTML,也就是说,所有的标签和属性都是正确地闭合的。下面是我们这个HTML的示例文件:

复制代码代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">   
<html>   
<head>   
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">   
<title>Login Page</title>   
</head>   
<body>   
<div id="login" class="simple" >   
<form action="login.do">   
Username : <input id="username" type="text" /><br>   
Password : <input id="password" type="password" /><br>   
<input id="submit" type="submit" />   
<input id="reset" type="reset" />   
</form>   
</div>   
</body>   
</html>  

使用Jsoup来解析HTML非常简单,你只需调用它的静态方法Jsoup.parse()并传入你的HTML字符串给它就可以了。Jsoup提供了多个重载的parse()方法,它可以从字符串,文件,URI,URL,甚至InputStream中读取HTML文件。如果不是UTF-8编码的话,你还可以指定字符编码,这样可以正确地读取HTML文件。下面是Jsoup库中HTML解析方法的一个完整的列表。parse(String html)方法将输入的HTML解析成一个新的Document。在Jsoup里,Document继承了Element,而它又继承自Node。同样的TextNode也继承自Node。只要你传入的是一个不为null的字符串,你就肯定能获取到一个成功的有意义的解析,得到一个包含head和body元素的Document。一旦你拿到这个Document,你就可以调用Document以及它的父类Element和Node上面的适当的方法来获取到你想要的数据了。

解析HTML文档的Java程序

下面是一个解析HTML字符串,网络上下载的HTML文件,以及本地文件系统中的HTML文件的完整的Java程序。你可以使用Eclipse IDE或者别的IDE甚至命令来运行这个程序。在Eclipse里面则很简单,拷贝这份代码,新建一个Java工程,在src包上右键并粘贴进去就可以了。Eclipse会去创建正确的包及同名的Java源文件的,因此工作量最小。如果你已经有一个Java示例工程了,那么仅需一步就可以了。下面的这个Java程序展示了解析及遍历HTML文件的三个不同例子。第一个例子中,我们直接解析了一个内容为HTML的字符串,第二个例子中我们解析了一个从URL中下载的HTML文件,第三个中我们从本地文件系统中加载了一个HTML文档并进行解析。第一和第三个例子中都用到了parse方法来获取一个Document对象,你可以查询它来提取出任何的标签值或者属性值。第二个例子中,我们用到了Jsoup.connect方法,它会去创建URL的连接,下载HTML并进行解析。这个方法也会返回Document,它可以用于后续的查询及获取标签或者属性的值。

复制代码代码如下:

import java.io.IOException;  

import org.jsoup.Jsoup;  
import org.jsoup.nodes.Document;  
import org.jsoup.nodes.Element;  


/**  
[*] Java Program to parse/read HTML documents from File using Jsoup library.  
[*] Jsoup is an open source library which allows Java developer to parse HTML  
[*] files and extract elements, manipulate data, change style using DOM, CSS and  
[*] JQuery like method.  
[*]  
[*] @author Javin Paul  
[*]/  
public class HTMLParser{  

    public static void main(String args[]) {  

        // Parse HTML String using JSoup library  
        String HTMLSTring = "<!DOCTYPE html>"  
                + "<html>"  
                + "<head>"  
                + "<title>JSoup Example</title>"  
                + "</head>"  
                + "<body>"  
                + "|[b]HelloWorld[/b]"  
                + ""  
                + "</body>"  
                + "</html>";  

        Document html = Jsoup.parse(HTMLSTring);  
        String title = html.title();  
        String h1 = html.body().getElementsByTag("h1").text();  

        System.out.println("Input HTML String to JSoup :" + HTMLSTring);  
        System.out.println("After parsing, Title : " + title);  
        System.out.println("Afte parsing, Heading : " + h1);  

        // JSoup Example 2 - Reading HTML page from URL  
        Document doc;  
        try {  
            doc = Jsoup.connect("http://google.com/").get();  
            title = doc.title();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  

        System.out.println("Jsoup Can read HTML page from URL, title : " + title);  

        // JSoup Example 3 - Parsing an HTML file in Java  
        //Document htmlFile = Jsoup.parse("login.html", "ISO-8859-1"); // wrong  
        Document htmlFile = null;  
        try {  
            htmlFile = Jsoup.parse(new File("login.html"), "ISO-8859-1");  
        } catch (IOException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } // right  
        title = htmlFile.title();  
        Element div = htmlFile.getElementById("login");  
        String cssClass = div.className(); // getting class form HTML element  

        System.out.println("Jsoup can also parse HTML file directly");  
        System.out.println("title : " + title);  
        System.out.println("class of div tag : " + cssClass);  
    }  

}  

输出:

复制代码代码如下:

Input HTML String to JSoup :
<!DOCTYPE html><html>
<head>
<title>JSoup Example</title>
</head>
<body>
<table><tr><td><h1>HelloWorld</h1></tr>
</table>
</body>
</html>  
After parsing, Title : JSoup Example  
Afte parsing, Heading : HelloWorld  
Jsoup Can read HTML page from URL, title : Google  
Jsoup can also parse HTML file directly title : Login Page  
class of div tag : simple  

Jsoup的好处就是它的健壮性很强。Jsoup HTML解析器会对你提供的HTML进行尽量干净的解析,而不去考虑这个HTML是否是格式良好的。它可以处理如下这些错误:未闭合的标签(比如,Java

Scala to

JavaScala),隐式标签(比如,一个裸的|Java is Great被封装到了|里面),它总能创建出一个文档结构(包含head及body的HTML,并且head里只会包含正确的元素)。这就是在Java中如何进行HTML的解析。Jsoup是一个优秀的健壮的开源库,它使得读取HTML文档,body片段,HTML字符串,以及直接从WEB中解析HTML内容都变得相当简单。在这篇文章中,我们学习了如何在Java中获取一个特定的HTML标签,正如第一个例子中我们将title及H1标签的值提取成了文本,而第三个例子中我们学习到了如何通过提取CSS属性来从HTML标签中获取属性值。除了强大的jQuery风格的html.body().getElementsByTag(“h1”).text()方法,你还可以提取任意的HTML标签,它还提供了像Document.title()和Element.className()这样便捷的方法,你可以快速获取到标题及CSS类。希望JSoup能让你玩得愉快,很快我们将会看到关于这个API的更多的一些例子。

Jsoup的设计初衷是用于处理现实生活中出现的各种不同的HTML,包括正确有效的HTML以及不完整的无效的标签集合。Jsoup的一个核心竞争力就是它的健壮性。

转载自 http://www.jb51.net/article/55620.html

在线文档:http://www.osctools.net/apidocs/apidoc?api=jsoup-1.6.3;http://jsoup.org/

<!-- lang: java -->
String content = "blabla";
Document doc = JSoup.parse(content);
Elements links = doc.select("a[href]");

Jsoup还支持白名单过滤机制,对于网站防止XSS攻击也是很好的。

  • HtmlParser

HtmlParser的功能比较完备,也挺灵活,但谈不上方便。这个项目很久没有维护了,最新版本是2.1。HtmlParser的核心元素是Node,对应一个HTML标签,支持getChildren()等树状遍历方式。HtmlParser另外一个核心元素是NodeFilter,通过实现NodeFilter接口,可以对页面元素进行筛选。

htmlparser是一个纯的java写的html解析的库,它不依赖于其它的java库文件,主要用于改造或提取html。它能超高速解析html,而且不会出错。现在htmlparser最新版本为2.0。 据说htmlparser就是目前最好的html解析和分析的工具。 无论你是想抓取网页数据还是改造html的内容,用了htmlparser绝对会忍不住称赞。

在线文档:http://www.osctools.net/apidocs/apidoc?api=HTMLParser[/url];http://htmlparser.sourceforge.net/project-info.html

示例代码:
Parser parser = new Parser (“http://www.dangdang.com");
NodeList list = parser.parse (null);
Node node = list.elementAt (0);
NodeList sublist = node.getChildren ();
System.out.println (sublist.size ());

  • Apache tika

tika是专为抽取而生的工具,还支持PDF、Zip甚至是Java Class。使用tika分析HTML,需要自己定义一个抽取内容的Handler并继承org.xml.sax.helpers.DefaultHandler,解析方式就是xml标准的方式。crawler4j中就使用了tika作为解析工具。SAX这种流式的解析方式对于分析大文件很有用,我个人倒是认为对于解析html意义不是很大。

InputStream inputStream = null;
HtmlParser htmlParser = new HtmlParser();
htmlParser.parse(new ByteArrayInputStream(page.getContentData()), 
contentHandler, metadata, new ParseContext()); 
  • HtmlCleaner与XPath

HtmlCleaner最大的优点是:支持XPath的方式选取元素。XPath是一门在XML中查找信息的语言,也可以用于抽取HTML元素。XPath与CSS Selector大部分功能都是重合的,但是CSS Selector专门针对HTML,写法更简洁,而XPath则是通用的标准,可以精确到属性值。XPath有一定的学习成本,但是对经常需要编写爬虫的人来说,这点投入绝对是值得的。

学习XPath可以参考w3school的XPath 教程。
http://www.w3school.com.cn/xpath/
下面是使用HtmlCleaner和xpath进行抽取的一段代码:

<!-- lang: java -->
HtmlCleaner htmlCleaner = new HtmlCleaner();
TagNode tagNode = htmlCleaner.clean(text);
Object[] objects = tagNode.evaluateXPath("xpathStr");
  • 几个工具的对比

在这里评价这些工具的主要标准是“方便”。就拿抽取页面所有链接这一基本任务来说,几种代码分别如下:

  • XPath:

    <!-- lang: java -->
    tagNode.evaluateXPath("//a/@href")
    
  • CSS Selector:

    <!-- lang: java -->
    //使用类似js的实现
    $("a[href]").attr("href")
    
  • HtmlParser:

    <!-- lang: java -->
    Parser p = new Parser(value);
    NodeFilter aFilter = new TagNameFilter("a");
    NodeList nodes = p.extractAllNodesThatMatch(aFilter);
    for (int i = 0; i < nodes.size(); i++) {
        Node eachNode = nodes.elementAt(i);
        if (eachNode instanceof LinkTag) {
            LinkTag linkTag = (LinkTag) eachNode;
            System.out.println(linkTag.extractLink());
        }
    }
    

XPath是最简单的,可以精确选取到href属性值;而CSS Selector则次之,可以选取到HTML标签,属性值需要调用函数去获取;而HtmlParser和SAX则需要手动写程序去处理标签了,比较麻烦。

坚持原创技术分享,您的支持将鼓励我继续创作!
+