`
yxgyh
  • 浏览: 274376 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

htmlparser使用(二)

    博客分类:
  • JAVA
阅读更多

这两天准备做一些网站编程的工作,于是对HtmlParse小研究了一下,目的是快速入手,而不是深入研究,做了一下整理,和大家共同讨论一下。

一,数据组织分析:

HtmlParser主要靠Node、AbstractNode和Tag来表达Html,因为Remark和Text相对简单,此处就将其忽略了。

    * Node是形成树结构表示HTML的基础,所有的数据表示都是接口Node的实现,Node定义了与页面树结构所表达的页面Page对象,定义了获取父、子、兄弟节点的方法,定义了节点到对应html文本的方法,定义了该节点对应的起止位置,定义了过滤方法,定义了Visitor访问机制。
    * AbstractNode是Node的一种具体的类实现,起到构成树形结构的作用,除了同具体Node相关的accetp方法,toString,toHtml,toPlainTextString方法以外,AbstractNode实现了大多基本的方法,使得它的子类,不用理会具体的树操作。
    * Tag是具体分析的主要内容。Tag分成composite的Tag和不能包含其他Tag的简单Tag两类,其中前者的基类是CompositeTag,其子类包含BodyTag,Div,FrameSetTag,OptionTag,等27个子类;而简单Tag有BaseHrefTag、DoctypeTag,FrameTag,ImageTag,InputTag,JspTag,MetaTag,ProcessingInstructionTag这八类。

Node分成三类:

    * RemarkNode:代表Html中的注释
    * TagNode:标签节点,是种类最多的节点类型,上述Tag的具体节点类都是TagNode的实现。
    * TextNode:文本节点


二,Visitor方式访问Html:

1,整体解析过程

    * 用一个URL或页面String做一个Parser
    * 用这个Parser做一个Visitor
    * 使用Parser.visitAllNodeWith(Visitor)来遍历节点
    * 获取Visitor遍历后得到的数据

2,Visit过程

    * 做解析之前做的事情:visitor.beginParsing();
    * 每次取到一个节点Node,让该Node接受accept该Visitor
    * 做解析后做的事情:visitor.finishedParsing();

3,获取节点的过程:逐步遍历Html,分析出Node。此部分较为复杂,且对于我们应用来说无需很多了解,暂跳过。

4,节点访问
节点访问采用Visitor模式,Node的accept方法和具体Visitor的visit方法是关键。
首先三类Node来accept的方式各不相同:

    * 对于所有TagNode都使用一个accept方法,即TagNode的accept方法。首先判断是否是标签结尾,如果是就visitor.visitEndTag (this);否则visitor.visitTag (this);
    * 如果是TextNode,那就visitor.visitStringNode (this);就可以了。
    * 如果是RemarkNode,那就visitor.visitRemarkNode (this);就可以了。


实际上NodeVisitor里边这四种visit方法都是空的,因为在不同的Visitor中对于这三类节点的处理是不同的;对于需要处理的节点,只要重载对应的visit方法就行了,如果不处理那就不理会就可以了;另外,如果用户用自己的Visitor,那么还可以灵活的处理不同类型的节点了。
系统为我们实现了下面我要介绍的8种Visitor,实际上可以看作是系统给我们演示了如何做各种各样的Visitor来访问Html,因为实际上我们要真正来用HtmlParser的话,还需要特定的Visitor,而通过简单的这些系统提供的Visitor组合是难以做成什么事情的。

三,系统Visitor功能简介:

    * ObjectFindingVisitor:用来找出所有指定类型的节点,采用getTags()来获取结果。
    * StringBean:用来从一个指定的URL获取移除了<SCRIPT></SCRIPT>和<PRE></PRE>之间代码的Html代码,也可以用做Visitor,用来移除这两种标签内部的代码,采用StringBean.getStrings()来获取结果。
    * HtmlPage:提取Title,body中的节点和页面中的TableTag节点。
    * LinkFindingVisitor:找出节点中包含某个链接的总个数。
    * StringFindingVisitor:找出遍历的TextNode中含有指定字符串的个数。
    * TagFindingVisitor:找出指定Tag的所有节点,可以指定多种类型。
    * TextExtractingVisitor:从网页中把所有标签去掉来提取文本,这个提取文本的Visitor有时是很实用的,只是注意在提取文本时将标签的属性也去掉了,也就是说只剩下标签之间的文本,例如<a>中的链接也去掉了。
    * UrlModifyingVisitor:用来修改网页中的链接。

四,Filter

如果说visitor是遍历提取信息,当然这个信息可以包括某些节点或者从节点分析出来的更有效的信息,这都取决于我们的Visitor做成什么样子,那么Filter则目标很明确,就是用来提取节点的。所以说要想用HtmlParser,首先要熟悉上面讲到的数据组织。

系统定义了17种具体的Filter,包括依据节点父子关系的Filter,连接Filter组合的Filter,依据网页内容匹配情况的filter,等等。我们也可以implement Filter来做自己的Filter来提取节点。

Filter的调用是同Visitor独立的,因为也无需先filter出一些NodeList,再用Visitor来访问。调用Filter的方法是:
NodeList nodeList = myParser.parse(someFilter);
解析之后,我们可以采用:
Node[] nodes = nodeList.toNodeArray();
来获取节点数组,也可以直接访问:
Node node = nodeList.elementAt(i)来获取Node。

另外,在Filter后得到NodeList以后,我们仍然可以使用NodeList的 extractAllNodesThatMatch(someFilter)来进一步过滤,同时又可以用NodeList的 isitAllNodesWith(someVisitor)来做进一步的访问。
这样,我们可以看到HtmlParser 为我们提供了非常方便的Html解析方式,针对不同的应用可以采用visitor来遍历Html节点提取数据,也可以用Filter来过滤节点,提取出我们所关注的节点,再对节点进行处理。通过这样的组合,一定能够找出我们所需要的信息。

package test.baidu;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;

import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.NodeClassFilter;
import org.htmlparser.filters.OrFilter;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.nodes.TextNode;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.HtmlPage;
import org.htmlparser.visitors.TextExtractingVisitor;

/**
* 演示了Html Parse的应用.
*
*/
public class ParseHtmlTest {

    public static void main(String[] args) throws Exception {
        String aFile = "F:\\百度一下,你就知道.htm";

        String content = readTextFile(aFile, "GBK");

        test1(content);
        System.out.println("====================================");

        test2(content);
        System.out.println("====================================");

        test3(content);
        System.out.println("====================================");

        test4(content);
        System.out.println("====================================");

        test5(aFile);
        System.out.println("====================================");

        //访问外部资源,相对慢
        test5("http://www.baidu.com");
        System.out.println("====================================");

    }

    /**
     * 读取文件的方式来分析内容.
     * filePath也可以是一个Url.
     *
     * @param resource 文件/Url
     */
    public static void test5(String resource) throws Exception {
        Parser myParser = new Parser(resource);

        //设置编码
        myParser.setEncoding("GBK");

        HtmlPage visitor = new HtmlPage(myParser);

        myParser.visitAllNodesWith(visitor);

        String textInPage = visitor.getTitle();

        System.out.println("test5 html title = " + textInPage);
    }

    /**
     * 按页面方式处理.对一个标准的Html页面,推荐使用此种方式.
     */
    public static void test4(String content) throws Exception {
        Parser myParser;
        myParser = Parser.createParser(content, "GBK");

        HtmlPage visitor = new HtmlPage(myParser);

        myParser.visitAllNodesWith(visitor);

        String textInPage = visitor.getTitle();

        System.out.println("test4 html title = " + textInPage);
    }

    /**
     * 利用Visitor模式解析html页面.
     *
     * 小优点:翻译了<>等符号
     * 缺点:好多空格,无法提取link
     * 
     */
    public static void test3(String content) throws Exception {
        Parser myParser;
        myParser = Parser.createParser(content, "GBK");

        TextExtractingVisitor visitor = new TextExtractingVisitor();

        myParser.visitAllNodesWith(visitor);

        String textInPage = visitor.getExtractedText();

        System.out.println("test3 = " + textInPage);
    }

    /**
     * 得到普通文本和链接的内容.
     *
     * 使用了过滤条件.
     */
    public static void test2(String content) throws ParserException {
        Parser myParser;
        NodeList nodeList = null;

        myParser = Parser.createParser(content, "GBK");

        NodeFilter textFilter = new NodeClassFilter(TextNode.class);
        NodeFilter linkFilter = new NodeClassFilter(LinkTag.class);

        //暂时不处理 meta
        //NodeFilter metaFilter = new NodeClassFilter(MetaTag.class);

        OrFilter lastFilter = new OrFilter();
        lastFilter.setPredicates(new NodeFilter[] { textFilter, linkFilter });

        nodeList = myParser.parse(lastFilter);

        Node[] nodes = nodeList.toNodeArray();

        for (int i = 0; i < nodes.length; i++) {
            Node anode = (Node) nodes[i];

            String line = "";
            if (anode instanceof TextNode) {
                TextNode textnode = (TextNode) anode;
                //line = textnode.toPlainTextString().trim();
                line = textnode.getText();
            } else if (anode instanceof LinkTag) {
                LinkTag linknode = (LinkTag) anode;

                line = linknode.getLink();
                //@todo 过滤jsp标签:可以自己实现这个函数
                //line = StringFunc.replace(line, "<%.*%>", "");
            }

            if (isTrimEmpty(line))
                continue;

            System.out.println("test2 = " + line);
        }
    }

    /**
     * 解析普通文本节点.
     *
     * @param content
     * @throws ParserException
     */
    public static void test1(String content) throws ParserException {
        Parser myParser;
        Node[] nodes = null;

        myParser = Parser.createParser(content, null);
        NodeFilter nodeFilter = new TagNameFilter(TextNode.class.getName());
        nodes = myParser.extractAllNodesThatMatch(nodeFilter).toNodeArray(); //exception could be thrown here

        for (int i = 0; i < nodes.length; i++) {
            TextNode textnode = (TextNode) nodes[i];
            String line = textnode.toPlainTextString().trim();
            if (line.equals(""))
                continue;
            System.out.println("test1 = " + line);
        }

    }

    /**
     * 读取一个文件到字符串里.
     *
     * @param sFileName 文件名
     * @param sEncode   String
     * @return 文件内容
     */
    public static String readTextFile(String sFileName, String sEncode) {
        StringBuffer sbStr = new StringBuffer();

        try {
            File ff = new File(sFileName);
            InputStreamReader read = new InputStreamReader(new FileInputStream(ff), sEncode);
            BufferedReader ins = new BufferedReader(read);

            String dataLine = "";
            while (null != (dataLine = ins.readLine())) {
                sbStr.append(dataLine);
                sbStr.append("\r\n");
            }

            ins.close();
        } catch (Exception e) {
            System.out.println("read Text File Error");
            e.printStackTrace();
        }

        return sbStr.toString();
    }

    /**
     * 去掉左右空格后字符串是否为空
     * @param astr String
     * @return boolean
     */
    public static boolean isTrimEmpty(String astr) {
        if ((null == astr) || (astr.length() == 0)) {
            return true;
        }
        if (isBlank(astr.trim())) {
            return true;
        }
        return false;
    }

    /**
     * 字符串是否为空:null或者长度为0.
     * @param astr 源字符串.
     * @return boolean
     */
    public static boolean isBlank(String astr) {
        if ((null == astr) || (astr.length() == 0)) {
            return true;
        } else {
            return false;
        }
    }

}

 

分享到:
评论

相关推荐

    HTMLParser使用文档和jar包

    HTMLParser是一个Java库,专门设计用于解析HTML文档。...本篇将详细阐述HTMLParser的使用方法、功能以及提供...通过文档学习、源代码研究和二进制包的使用,开发者可以充分利用HTMLParser的功能,提高处理HTML文档的效率。

    HTMLParser 使用文档、jar包、以及源码

    4. **HTMLParser-2.0-SNAPSHOT-bin.zip**:这是HTMLParser的二进制发行版,包含了编译好的库文件。将这个库添加到Java项目的类路径中,就可以直接使用HTMLParser的功能。 在HTMLParser中,主要的类包括`...

    Winista.Htmlparser.Net 源码 +Demo

    `HtmlParser2003`可能是一个早期版本的源代码,而`AnalyzeHtml`和`WebParser`则可能是演示如何使用HtmlParser的项目。 1. **AnalyzeHtml**:这个项目可能展示了如何分析HTML文档,通过调用HtmlParser的API来提取...

    HtmlParser的使用

    以下是对`HtmlParser`的详细解释和使用方法: 一、HTMLParser简介 HTMLParser提供了对HTML文档的解析能力,能够识别HTML标签、属性、文本内容等元素。它的设计目标是易于使用且健壮,即使面对不规则或非标准的HTML...

    java解析html工具htmlparser的jar包及api文档

    在提供的压缩包中,`HTMLParser-2.0-SNAPSHOT-bin`可能是可执行的二进制文件,包括了编译好的JAR文件和其他运行所需的资源。而`HTMLParser-2.0-SNAPSHOT`可能包含了源代码,这对于开发者来说是宝贵的,因为他们可以...

    HtmlParser提取网页信息的设计与实现

    #### 二、HtmlParser概述 HtmlParser是一种轻量级、高效且易于使用的开源库,专门用于解析HTML文档。它通过构建一个树状结构来表示HTML文档的内容,使得开发者能够方便地从中抽取所需信息。HtmlParser的核心组成...

    htmlparser使用指南

    这个使用指南将深入探讨HTMLParser的基本概念、核心功能、使用方法以及常见应用场景,帮助开发者更好地理解和应用这个库。 一、HTMLParser简介 HTMLParser是基于Java语言的轻量级HTML解析器,它的设计目标是简化...

    HTMLParser 2.0最新jar API 源代码

    将此jar包添加到项目的类路径中,就可以在程序中使用HTMLParser提供的各种解析功能了。 HTMLParser库的核心功能包括: - **HTML解析**:库能够解析HTML文档,并将其转化为一个可操作的结构,比如树形结构。这使得...

    Winista.HTMLParser源码

    1. 网页数据抓取:创建一个简单的爬虫,使用Winista.HTMLParser解析目标网页,然后通过CSS选择器提取特定内容,例如新闻标题、发布时间等。 2. 存储与检索:爬取的大量网页数据可以被压缩存储,当需要时,通过...

    Winista.HtmlParser

    二、主要功能特性 1. **DOM树构建**:Winista.HtmlParser能够将HTML文档转换为DOM(Document Object Model)树结构,使开发者能够通过节点遍历和查询来访问HTML元素。 2. **CSS选择器支持**:库内置了对CSS选择器...

    htmlparser解析Html的jar包和源文件包(两个)

    1. `htmlparser-1.6.jar` 是预编译的二进制库文件,它包含了HTMLParser的所有类和方法,可供开发者直接在项目中引用。将此jar包添加到项目的类路径中,就可以利用HTMLParser的功能来解析HTML文档了。例如,可以创建...

    使用 HttpClient 和 HtmlParser 实现简易爬虫

    ### 使用HttpClient和HtmlParser实现简易爬虫的知识点详解 #### 一、HttpClient与HtmlParser简介 **HttpClient简介:** HttpClient是Jakarta Commons项目中的一个重要组件,用于提供灵活且高效的HTTP协议支持。它...

    htmlparser实现爬虫

    #### 二、HTMLParser的特点 - **高性能**: HTMLParser能够以极快的速度解析HTML文档,并且在处理过程中极少出错。 - **轻量级**: 作为一个独立的库,HTMLParser没有外部依赖,便于集成到不同的项目中。 - **易用性**...

    HTMLParser的使用

    二、使用示例 以下是一个简单的使用HTMLParser解析HTML页面的Java代码示例: ```java import org.htmlparser.*; import org.htmlparser.filters.*; import org.htmlparser.nodes.*; import org.htmlparser.tags.*;...

    正则表达式+_HTMLParser使用详解-2010-03-21

    二、HTMLParser 1. **HTMLParser介绍**:HTMLParser是Python标准库中的一个模块,用于解析HTML和XML文档,通过事件驱动的方式处理标签的开始、结束、属性等。 2. **类结构**:HTMLParser类提供了一个基础的解析...

    htmlparser中文文档

    #### 二、HTMLParser核心功能 - **解析HTML**:能够高效地解析HTML文档,包括HTML5在内的多种版本。 - **提取内容**:可以从HTML文档中提取特定的文本、链接或其他元素。 - **修改HTML**:支持对解析后的HTML文档...

    HTMLParser抽取Web网页正文信息.doc

    #### 二、下载与配置HTMLParser 要使用HTMLParser,首先需要从官方网站(http://HTMLParser.sourceforge.net/)下载最新的HTMLParser库。解压后的`htmlparser.jar`文件需要被添加到项目的class path中,以便在编程时...

    用C#实现HtmlParser的代码

    用C#实现HtmlParser的代码 该篇文章主要介绍了用C#实现HtmlParser的两种方法,分别...用C#实现HtmlParser的两种方法都可以用来解析Html内容,但是第二种方法使用Winista.Htmlparser.Net可以更好地处理复杂的Html结构。

Global site tag (gtag.js) - Google Analytics