热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HTMLParser使用详解(2)Node内容

HTMLParser使用详解(2)-Node内容2010-03-1813:41HTMLParser将解析过的信息留存为一个树的结构。Node是信息留存的数据类型基础。请看Node的
HTMLParser使用详解(2)- Node内容  2010-03-18 13:41
HTMLParser将解析过的信息留存为一个树的结构。Node是信息留存的数据类型基础。
请看Node的界说:
public interface Node extends Cloneable;

Node中包括的要领有几类:
  1、对付树型结构进行遍历的函数,这些函数最轻易理解:
Node getParent ():取得父节点
NodeList getChildren ():取得子节点的列表
Node getFirstChild ():取得第一个子节点
Node getLastChild ():取得最后一个子节点
Node getPreviousSibling ():取得前一个兄弟(欠好意思,英文是兄弟姐妹,直译太麻烦并且不相符习惯,抱歉女同胞了)
Node getNextSibling ():取得下一个兄弟节点
  2、取得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页面中的结束位置
  3、用于Filter过滤的函数
void collectInto (NodeList list, NodeFilter filter):基于filter的条件对付这个节点进行过滤,相符条件的节点放到list中。
  4、用于Visitor遍历的函数:
void accept (NodeVisitor visitor):对这个Node应用visitor
  5、用于修改内容的函数,这类用得比较少:
void setPage (Page page):设置这个Node对应的Page东西
void setText (String text):设置文本
void setChildren (NodeList children):设置子节点列表
  6、其他函数:
void doSemanticAction ():执行这个Node对应的操纵(只有少数Tag有对应的操纵)
Object clone ():接口Clone的抽象函数。

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

< /head>





白泽居-www.baizeju.com
白泽居-www.baizeju.com

白泽居-www.baizeju.com




测试源代码:
/**
* @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 voidmessage( 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:
toHtml(true):
toHtml(false):
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):
toString:Txt (121[0,121],123[1,0]): \n
=================================================
getText:head
getPlainText:白泽居-www.baizeju.com
toHtml:< /head>
toHtml(true):< /head>
toHtml(false):< /head>
toString:HEAD: Tag (123[1,0],129[1,6]): head
Tag (129[1,6],197[1,74]): meta http-equiv="Content-Type" cOntent="text/html; ...
Tag (197[1,74],204[1,81]): title
Txt (204[1,81],223[1,100]): 白泽居-www.baizeju.com
End (223[1,100],231[1,108]): /title
End (231[1,108],238[1,115]): /head

=================================================
getText:
getPlainText:
toHtml:
toHtml(true):
toHtml(false):
toString:Txt (238[1,115],240[2,0]): \n
=================================================
getText:html xmlns="http://www.w3.org/1999/xhtml"
getPlainText:
白泽居-www.baizeju.com
白泽居-www.baizeju.com
白泽居-www.baizeju.com
toHtml:




白泽居-www.baizeju.com
白泽居-www.baizeju.com

白泽居-www.baizeju.com



toHtml(true):




白泽居-www.baizeju.com
白泽居-www.baizeju.com

白泽居-www.baizeju.com



toHtml(false):




白泽居-www.baizeju.com
白泽居-www.baizeju.com

白泽居-www.baizeju.com



toString:Tag (240[2,0],283[2,43]): html xmlns="http://www.w3.org/1999/xhtml"
Txt (283[2,43],285[3,0]): \n
Tag (285[3,0],292[3,7]): body
Txt (292[3,7],294[4,0]): \n
Tag (294[4,0],313[4,19]): div id="top_main"
Txt (313[4,19],316[5,1]): \n\t
Tag (316[5,1],336[5,21]): div id="logoindex"
Txt (336[5,21],340[6,2]): \n\t\t
Rem (340[6,2],351[6,13]): 这是注释
Txt (351[6,13],376[8,0]): \n\t\t白泽居-www.baizeju.com\n
Tag (376[8,0],409[8,33]): a href="http://www.baizeju.com"
Txt (409[8,33],428[8,52]): 白泽居-www.baizeju.com
End (428[8,52],432[8,56]): /a
Txt (432[8,56],435[9,1]): \n\t
End (435[9,1],441[9,7]): /div
Txt (441[9,7],465[11,0]): \n\t白泽居-www.baizeju.com\n
End (465[11,0],471[11,6]): /div
Txt (471[11,6],473[12,0]): \n
End (473[12,0],480[12,7]): /body
Txt (480[12,7],482[13,0]): \n
End (482[13,0],489[13,7]): /html

=================================================
  对付第一个Node的内容,对应的就是第一行,这个比较好理解。
从这个输出结果中,也可以看出内容的树状结构。或者说是树林结构。在Page内容的第一层Tag,如DOCTYPE,head和html,分别形成了一个最高层的Node节点(很多人可能对第二个和第四个Node的内容有点希罕。实际上这两个Node就是两个换行标记。HTMLParser把HTML页面内容中的所有换行,空格,Tab等都转换成了相应的Tag,所以就出现了这样的Node。虽然内容少但是级别高,呵呵)
  getPlainTextString是把用户可以看到的内容都包括了。有趣的有两点,一是标签中的Title内容是在 plainText中的,可能在标题中可见的也算可见吧。
另外就是象前面说的,HTML内容中的换行符什么的,也都成了plainText,这个逻辑上似乎有点问题。
  另外可能大众发觉toHtml,toHtml(true)和toHtml(false)的结果没什么区别。实际也是这样的,假如跟踪HTMLParser 的源代码就可以发觉,Node的子类是AbstractNode,其中实现了toHtml()的源代码,直接挪用toHtml(false),而 AbstractNode的三个子类RemarkNode,TagNode和TextNode中,toHtml(boolean verbatim)的实现中,都没有处理verbatim参数,所以三个函数的结果是一模一样的。假如你不需要实现你自己的什么特别处理,简单使用 toHtml就可以了。
  HTML的Node类继续关系如下图(这个是从另外文章Copy的):
技术分享
     AbstractNodes是Node的直接子类,也是一个抽象类。它的三个直接子类实现是
    RemarkNode,用于留存注释。在输出结果的 toString局部中可以看到有一个"Rem (345[6,2],356[6,13]): 这是注释",就是一个RemarkNode。
    TextNode也很简单,就是用户可见的文字信息。
    TagNode是最纷乱的,包括了HTML语言中的所有标签,并且可以扩展(扩展 HTMLParser 对自界说标签的处理能力)。
TagNode包括两类,一类是简单的Tag,实际就是不克包括其他Tag的标签,只能做叶子节点。另一类是 CompositeTag,就是可以包括其他Tag,是分支节点

HTMLParser使用详解(2)- Node内容


推荐阅读
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文内容为asp.net微信公众平台开发的目录汇总,包括数据库设计、多层架构框架搭建和入口实现、微信消息封装及反射赋值、关注事件、用户记录、回复文本消息、图文消息、服务搭建(接入)、自定义菜单等。同时提供了示例代码和相关的后台管理功能。内容涵盖了多个方面,适合综合运用。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 后台获取视图对应的字符串
    1.帮助类后台获取视图对应的字符串publicclassViewHelper{将View输出为字符串(注:不会执行对应的ac ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
author-avatar
rogerddd
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有