HTMLParser使用详解

来源:互联网

HTMLParser 使用详解

HTMLParser 具有小巧,快速的优点,缺点是相关文档比较少(英文的也少),很多功能需要自己摸索。对于初学者还是要费一些功夫的,而一旦上手以后,会发现 HTMLParser 的结构设计很巧妙,非常实用,基本你的各种需求都可以满足。

这里我根据自己这几个月来的经验,写了一点入门的东西,希望能对新学习 HTMLParser 的朋友们有所帮助。(不过当年高考本人语文只比及格高一分,所以文法方面的问题还希望大家多多担待)

 

HTMLParser 的核心模块是 org.htmlparser.Parser 类, 这个类实际完成了对于 HTML 页面的分析工作 。这个类有下面几个构造函数:

public Parser ();

public Parser (Lexer lexer, ParserFeedback fb);

public Parser (URLConnection connection, ParserFeedback fb) throws ParserException;

public Parser (String resource, ParserFeedback feedback) throws ParserException;

public Parser (String resource) throws ParserException;

public Parser (Lexer lexer);

public Parser (URLConnection connection) throws ParserException;

和一个静态类 public static Parser createParser (String html, String charset);

 

对于大多数使用者来说,使用最多的是通过一个 URLConnection 或者一个保存有网页内容的字符串来初始化Parser ,或者使用静态函数来生成一个 Parser 对象。 ParserFeedback 的代码很简单, 是针对调试和跟踪分析过程的 ,一般不需要改变。 而使用 Lexer 则是一个相对比较高级的话题 ,放到以后再讨论吧。

这里比较有趣的一点是, 如果需要设置页面的编码方式的话 ,不使用 Lexer 就只有静态函数一个方法了。对于大多数中文页面来说,好像这是应该用得比较多的一个方法。

 

下面是初始化 Parser 的例子。

 

package com.baizeju.htmlparsertester;

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.FileInputStream;

import java.io.File;

import java.net.HttpURLConnection;

import java.net.URL;

 

import org.htmlparser.visitors.TextExtractingVisitor;

 

import org.htmlparser.Parser;

 

/**

* @author www.baizeju.com

*/

public class Main {

private static String ENCODE = "GBK";

private static void message( String szMsg ) {

try{System.out.println(new String(szMsg.getBytes(ENCODE), System.getProperty("file.encoding"))); } catch(Exception e ){}

}

public static String openFile( String szFileName ) {

try {

BufferedReader bis = new BufferedReader(new InputStreamReader(new FileInputStream( new File(szFileName)),ENCODE ) );

String szContent="";

String szTemp;

 

while ( (szTemp = bis.readLine()) != null) {

szContent+=szTemp+"\n";

}

bis.close();

return szContent;

}

catch( Exception e ) {

return "";

}

}

 

public static void main(String[] args) {

 

String szContent = openFile( "E:/My Sites/HTMLParserTester.html");

 

try{

//Parser parser = Parser.createParser(szContent, ENCODE);

//Parser parser = new Parser( szContent );

Parser parser = new Parser( (HttpURLConnection) (new URL("http://127.0.0.1:8080/HTMLParserTester.html")).openConnection() );

 

TextExtractingVisitor visitor = new TextExtractingVisitor ();

parser. visitAllNodesWith ( visitor );

String textInPage = visitor.getExtractedText();

 

message(textInPage);

}

catch( Exception e ) {

}

}

}

加重的部分测试了几种不同的初始化方法,后面的显示了结果。大家看到能 Parser 出内容就可以了,如何操作访问 Parser 的内容我们在后面讨论。

HTMLParser 将解析过的信息保存为一个树的结构。 Node 是信息保存的数据类型基础 。

请看 Node 的定义:

public interface Node extends Cloneable;

 

Node 中包含的方法有几类:

对于树型结构进行遍历的函数 ,这些函数最容易理解:

Node getParent () : 取得父节点

NodeList getChildren () : 取得子节点的列表

Node getFirstChild () : 取得第一个子节点

Node getLastChild () : 取得最后一个子节点

Node getPreviousSibling () : 取得前一个兄弟(不好意思,英文是兄弟姐妹,直译太麻烦而且不符合习惯,对不起女同胞了)

Node getNextSibling () : 取得下一个兄弟节点

取得 Node 内容的函数

String getText () : 取得文本

String toPlainTextString () : 取得纯文本信息 。

String toHtml () : 取得 HTML 信息(原始 HTML )

String toHtml (boolean verbatim) : 取得 HTML 信息(原始 HTML )

String toString () : 取得字符串信息(原始 HTML )

Page getPage () : 取得这个 Node 对应的 Page 对象

int getStartPosition () : 取得这个 Node 在 HTML 页面中的起始位置

int getEndPosition () : 取得这个 Node 在 HTML 页面中的结束位置

用于 Filter 过滤的函数:

void collectInto (NodeList list, NodeFilter filter) : 基于 filter 的条件对于这个节点进行过滤,符合条件的节点放到 list中。

用于 Visitor 遍历的函数:

void accept (NodeVisitor visitor) : 对这个 Node 应用 visitor

用于修改内容的函数,这类用得比较少

void setPage (Page page) : 设置这个 Node 对应的 Page 对象

void setText (String text) : 设置文本

void setChildren (NodeList children) : 设置子节点列表

其他函数

void doSemanticAction () : 执行这个 Node 对应的操作(只有少数 Tag 有对应的操作)

Object clone () : 接口 Clone 的抽象函数。

 

实际我们用 HTMLParser 最多的是处理 HTML 页面, Filter 或 Visitor 相关的函数是必须的,然后第一类和第二类函数是用得最多的。第一类函数比较容易理解,下面用例子说明一下第二类函数。

下面是用于测试的 HTML 文件:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><title> 白泽居 -www.baizeju.com</title></head>

<html xmlns="http://www.w3.org/1999/xhtml">

<body >

<div id="top_main">

<div id="logoindex">

<!-- 这是注释 -->

白泽居 -www.baizeju.com

<a href="http://www.baizeju.com"> 白泽居 -www.baizeju.com</a>

</div>

白泽居 -www.baizeju.com

</div>

</body>

</html>

 

测试代码:

/**

* @author www.baizeju.com

*/

 

package com.baizeju.htmlparsertester;

import java.io.BufferedReader;

import java.io.InputStreamReader;

import java.io.FileInputStream;

import java.io.File;

import java.net.HttpURLConnection;

import java.net.URL;

 

import org.htmlparser.Node;

import org.htmlparser.util.NodeIterator;

import org.htmlparser.Parser;

 

/**

* @author www.baizeju.com

*/

public class Main {

private static String ENCODE = " GBK ";

private static void message( String szMsg ) {

try{ System.out.println(new String(szMsg.getBytes(ENCODE), System.getProperty("file.encoding"))); }      catch(Exception e ){}

}

public static String openFile ( String szFileName ) {

try {

BufferedReader bis = new BufferedReader(new InputStreamReader(new FileInputStream( new File(szFileName)),    ENCODE) );

String szContent="";

String szTemp;

 

while ( (szTemp = bis.readLine()) != null) {

szContent+=szTemp+"\n";

}

bis.close();

return szContent;

}

catch( Exception e ) {

return "";

}

}

 

public static void main(String[] args) {

 

try{

Parser parser = new Parser( (HttpURLConnection) (new URL("http://127.0.0.1:8080/HTMLParserTester.html")).openConnection() );

 

for (NodeIterator i = parser.elements (); i.hasMoreNodes(); ) {

Node node = i.nextNode();

message("getText:"+node.getText());

message("getPlainText:"+node.toPlainTextString());

message("toHtml:"+node.toHtml());

message("toHtml(true):"+node.toHtml(true));

message("toHtml(false):"+node.toHtml(false));

message("toString:"+node.toString());

message("=================================================");

}

}

catch( Exception e ) {

System.out.println( "Exception:"+e );

}

}

}

 

输出结果:

getText:!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"

getPlainText:

toHtml:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

toHtml(true):<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

toHtml(false):<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

toString:Doctype Tag : !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd; begins at : 0; ends at : 121

=================================================

getText:

 

getPlainText:

 

toHtml:

 

toHtml(true):

 

toHtml(false):

发表评论