HtmlParser初步研究
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:文本节点
- 用一个URL或页面String做一个Parser
- 用这个Parser做一个Visitor
- 使用Parser.visitAllNodeWith(Visitor)来遍历节点
- 获取Visitor遍历后得到的数据
- 做解析之前做的事情:visitor.beginParsing();
- 每次取到一个节点Node,让该Node接受accept该Visitor
- 做解析后做的事情:visitor.finishedParsing();
- 对于所有TagNode都使用一个accept方法,即TagNode的accept方法。首先判断是否是标签结尾,如果是就visitor.visitEndTag (this);否则visitor.visitTag (this);
- 如果是TextNode,那就visitor.visitStringNode (this);就可以了。
- 如果是RemarkNode,那就visitor.visitRemarkNode (this);就可以了。
实际上NodeVisitor里边这四种visit方法都是空的,因为在不同的Visitor中对于这三类节点的处理是不同的;对于需要处理的节点,只要重载对应的visit方法就行了,如果不处理那就不理会就可以了;另外,如果用户用自己的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:用来修改网页中的链接。
邮件列表:
http://sourceforge.net/mail/?group_id=24399
主页上的sample:
http://htmlparser.sourceforge.net/samples.html
在发布的包里没有demo或example文件夹,但是在有些类,比如org.htmlparser.Parser
有public static void main(String[] args)这个方法,其中有一些该类的使用方法。
org.htmlparser.Parser.main(String[] args)中就有Parse a web page and print the tags in a simple loop的方法。这在http://htmlparser.sourceforge.net/samples.html上有说明。
特别的:一个java web start
http://htmlparser.sourceforge.net/samples/filterbuilder.jnlp
帮助认识和使用filter。
一些常见处理:
应用HtmlParser处理含HTML标签的字符串或网页
String Extraction
To get all the text content from a web page, use the TextExtractingVisitor, like so:
import org.htmlparser.Parser;import org.htmlparser.util.ParserException;import org.htmlparser.visitors.TextExtractingVisitor;public class StringDemo{ public static void main (String[] args) throws ParserException { Parser parser = new Parser ("http://pageIwantToParse.com"); TextExtractingVisitor visitor = new TextExtractingVisitor (); parser.visitAllNodesWith (visitor); System.out.println (visitor.getExtractedText()); }}
If you want a more browser like behaviour, use the StringBean like so:
import org.htmlparser.beans.StringBean;public class StringDemo{ public static void main (String[] args) { StringBean sb = new StringBean (); sb.setLinks (false); sb.setReplaceNonBreakingSpaces (true); sb.setCollapse (true); sb.setURL ("http://pageIwantToParse.com"); System.out.println (sb.getStrings ()); }}
To get all the text content from a web page you already have in a string:
import org.htmlparser.Parser;import org.htmlparser.Node;import org.htmlparser.nodes.TextNode;import org.htmlparser.util.ParserException;public class StringDemo{ public static void main (String[] args) throws ParserException { Parser myParser; Node[] nodes = null; String content = ""; myParser = Parser.createParser(content, null); nodes = myParser.extractAllNodesThatAre(TextNode.class); //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(line); } } http://blog.csdn.net/redez/archive/2005/11/21/534277.aspx
最近在研究lucene,主要做ftp搜索和网页的站内搜索。
ftp搜索比较好做,主流的FTP有两种一种是IIS的一种是Server-U的.
真对这两种FTP分别进行分析就可以得到FTP资源的文件名和路径及大小和日期
然后对其进行索引就可以了,比较简单。
网页检索可不像ftp那样了,我试着用lucene自带的htmlparser,解析纯英文的网页
没有问题,可解析中文的网页时有时会遇到编码问题。郁闷。。。
SourceForge搜到了一个开源的HTMLParser。网址是http://htmlparser.sourceforge.net
目前的版本为1.6。
测试代码为:
import java.io.*;
import org.htmlparser.filters.*;
import org.htmlparser.*;
import org.htmlparser.nodes.*;
import org.htmlparser.tags.*;
import org.htmlparser.util.*;
import org.htmlparser.visitors.*;
public class HTMLParserTest
{
public static void main(String args[]) throws Exception
{
String path = "D://Webdup//MyWebsites//biti//download//latest//cisco.biti.edu.cn//index.html";
StringBuffer sbStr = new StringBuffer();
BufferedReader reader = new BufferedReader(new FileReader(new File(path)));
String temp = "";
while((temp=reader.readLine())!=null)
{
sbStr.append(temp);
sbStr.append("/r/n");
}
reader.close();
String result = sbStr.toString();
readAll(result);
readTextAndLink(result);
readByHtml(result);
readTextAndTitle(result);
}
//按页面方式处理.解析标准的html页面
public static void readByHtml(String content) throws Exception
{
Parser myParser;
myParser = Parser.createParser(content, "GB2312");
HtmlPage visitor = new HtmlPage(myParser);
myParser.visitAllNodesWith(visitor);
String textInPage = visitor.getTitle();
System.out.println(textInPage);
NodeList nodelist ;
nodelist = visitor.getBody();
System.out.print(nodelist.asString().trim());
}
//读取文本内容和标题
public static void readTextAndTitle(String result) throws Exception
{
Parser parser ;
NodeList nodelist ;
parser = Parser.createParser(result,"GB2312");
NodeFilter textFilter = new NodeClassFilter(TextNode.class);
NodeFilter titleFilter = new NodeClassFilter(TitleTag.class);
OrFilter lastFilter = new OrFilter();
lastFilter.setPredicates(new NodeFilter[]{textFilter,titleFilter});
nodelist = parser.parse(lastFilter);
Node[] nodes = nodelist.toNodeArray();
String line ="";
for(int i=0;i<nodes.length;i++)
{
Node node = nodes[i];
if(node instanceof TextNode)
{
TextNode textnode = (TextNode) node;
line = textnode.getText();
}
else
if(node instanceof TitleTag)
{
TitleTag titlenode = (TitleTag) node;
line = titlenode.getTitle();
}
if (isTrimEmpty(line))
continue;
System.out.println(line);
}
}
//分别读纯文本和链接
public static void readTextAndLink(String result) throws Exception
{
Parser parser;
NodeList nodelist;
parser = Parser.createParser(result,"GB2312");
NodeFilter textFilter = new NodeClassFilter(TextNode.class);
NodeFilter linkFilter = new NodeClassFilter(LinkTag.class);
OrFilter lastFilter = new OrFilter();
lastFilter.setPredicates(new NodeFilter[] { textFilter, linkFilter });
nodelist = parser.parse(lastFilter);
Node[] nodes = nodelist.toNodeArray();
String line ="";
for(int i=0;i<nodes.length;i++)
{
Node node = nodes[i];
if(node instanceof TextNode)
{
TextNode textnode = (TextNode) node;
line = textnode.getText();
}
else
if(node instanceof LinkTag)
{
LinkTag link = (LinkTag)node;
line = link.getLink();
}
if (isTrimEmpty(line))
continue;
System.out.println(line);
}
}
public static void readAll(String result) throws Exception
{
Parser parser;
Node[] nodes ;
parser = Parser.createParser(result,"GB2312");
nodes = parser.extractAllNodesThatAre(TextNode.class);
//读取所有的内容节点
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(line);
}
}
/**
* 去掉左右空格后字符串是否为空
*/
public static boolean isTrimEmpty(String astr)
{
if ((null == astr) || (astr.length() == 0))
{
return true;
}
if (isBlank(astr.trim()))
{
return true;
}
return false;
}
/**
* 字符串是否为空:null或者长度为0.
*/
public static boolean isBlank(String astr)
{
if ((null == astr) || (astr.length() == 0))
{
return true;
}
else
{
return false;
}
}
}
}
来源:http://htmlparser.sourceforge.net/wiki/index.php/StringExtraction
参考:http://htmlparser.sourceforge.net/
处理特定tag:
参考:http://sourceforge.net/mailarchive/message.php?msg_id=25aac9fc0704200423h78893925y72cb75136be7330%40mail.gmail.com
package cn.yethyeth.forTest;
思路:建立一个新的NodeVisitor,在其中处理visitTag这个函数(具体原理见上面第一篇文章)
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.NodeVisitor;
public class HTMLParserHandleTag extends NodeVisitor...{
public void visitTag (Tag tag)
...{
if( tag.getAttribute("class")!=null )...{
System.out.println (" " + tag.getTagName () + tag.getAttribute("class"));
}
}
public static void main (String[] args) throws ParserException
...{
Parser parser = new Parser ("http://bbs.qihoo.com/ttgz/index.html");
NodeVisitor visitor = new HTMLParserHandleTag ();
parser.visitAllNodesWith (visitor);
}
}
更简单的方法:使用TagNameFilter , HasAttributeFilter,AndFilter。
TagNameFilter过滤特定名字的tag,
HasAttributeFilter过滤特定名字和值的tag,
AndFilter将多个filter组合起来。
* TestFilter.java, 2007-5-13 1:22:45.
*
* CopyRight (c) 2007-2007, yethyeth ,All rights reserved.
*
* This file is licenced under the Apache License.
*/
package com.bighai.forTest;
import org.apache.commons.lang.StringUtils;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.filters.AndFilter;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
public class TestFilter {
/**
* @param args
* @throws ParserException
*/
public static void main(String[] args) throws ParserException {
// TODO Auto-generated method stub
Parser parser = new Parser("http://bbs.qihoo.com/ttgz/index.html");
AndFilter filter =
new AndFilter(
new TagNameFilter("div"),
new HasAttributeFilter("class","rLCon") );
NodeList nodes = parser.parse(filter);
for( int i = 0; i < nodes.size(); i++ ){
System.out.println(
((Tag)nodes.elementAt(i)).getTagName()+" class="+
((Tag)nodes.elementAt(i)).getAttribute("class") );
}
}
}
结果:
HtmlParser初步研究相关推荐
- GWT与Eclipse集成开发初步研究
GWT与Eclipse集成开发初步研究 原文:http://blog.sina.com.cn/s/blog_415bd707010086cy.html JDK6.0 下载.安装.配置 http://b ...
- .net HtmlParser初步使用研究
这两天准备做一些网站编程的工作,于是对HtmlParse小研究了一下,目的是快速入手,而不是深入研究,做了一下整理,和大家共同讨论一下. 一,数据组织分析: HtmlParser主要靠Node.Abs ...
- 支持小米java文件阅读器_小米开源文件管理器MiCodeFileExplorer-源码研究(0)-初步研究...
2011年对着书本Android应用开发揭秘,写了2个月的HelloWorld. 现在想复习并深入,我没有耐心再去一点点地敲代码了. 4年前自己是个学生,实习,现在有工作,只能业余时间研究. 这一点是 ...
- 小米开源文件管理器MiCodeFileExplorer-源码研究(0)-初步研究
2011年对着书本Android应用开发揭秘,写了2个月的HelloWorld. 现在想复习并深入,我没有耐心再去一点点地敲代码了. 4年前自己是个学生,实习,现在有工作,只能业余时间研究. 这一点是 ...
- 基于聚类算法的IMT-2030应用场景初步研究
[摘 要]IMT系统已进入新的研究周期,支持的业务种类将更为丰富,业务品质将更加高级,同时业务特性表现为更多的维度和更大的范围,如何对业务进行客观而高效的分析以得到典型的应用场景,对于IMT系统的标 ...
- 图解用工具对BHO做初步研究
一 BHO和浏览器劫持 BHO Browser Helper Objects (也被称为 BHOs) 是com组件,扮演着ie插件的角色.BHOs可以在某种程度上定制IE,如:用户交互的修改,网页过滤 ...
- 一款名为Blue_Moon的后台模板的初步研究
其介绍曰,Blue Moon后台管理模板是一款适合微信公众平台后台的蓝色清爽风格模板. 1 先看下其效果 表单效果: 图表效果: 界面元素:按钮等等: 表格: 左上角用户登录: 左上角部分的代码结构如 ...
- iOS7 UIKit Dynamics 的初步研究
这回开始学习iOS7新的UIKit Dynamics,我看有人翻译成UIKit 力学,我觉得倒挺贴切的,所以就借来用一用. 这个UIKit力学系统里要设计到四个东西: 1.UIDynamicAnima ...
- IE6下z-index犯癫不起作用bug的初步研究
by zhangxinxu from http://www.zhangxinxu.com 本文地址:http://www.zhangxinxu.com/wordpress/?p=471 一.匆匆带过的 ...
- Release编译模式下,事件是否会引起内存泄漏问题初步研究
题记:不常发生的事件内存泄漏现象 想必有些朋友也常常使用事件,但是很少解除事件挂钩,程序也没有听说过内存泄漏之类的问题.幸运的是,在某些情况下,的确不会出问题,很多年前做的项目就跑得好好的,包括我也是 ...
最新文章
- wifi boombox android,android filament入门,GLB和GLTF模型查看器
- 开源FPGA硬件模拟游戏机,原汁原味的复古游戏体验带你回童年
- P4945-最后的战役【dp,离散化】
- linux vps 命令,CentOS最常用Linux vps操作命令整理大全
- 2015 年出现的十大流行 Python 库
- 本地未安装Oracle数据库,如何连接远程Oracle数据库
- 解决无法连接mysql问题
- 七月在线python数据分析_七月在线Python数据分析笔记
- 中数据库url怎么写_WIN10下怎么找到MYSQL数据库中存储数据的位置
- 如何解压 GZ 文件
- 基于HTML5实现五彩连珠小游戏
- 6. LaTeX 参考文献的排版与引用
- 第三章:x264视频制作meGUI工具使用
- 【LibTorch】Microsoft C++ 异常: c10::NotImplementedError,位于内存位置 0x000000E8A9DAEDC0 处。
- 〖2011.08.19〗秋无痕常用软件全功能装机光盘2011年八月版(支持64位WIN7)
- 洛谷 P1192 台阶问题
- 计算机名打印机无法共享,打印机共享不了怎么回事 打印机共享不了原因和解决办法【详解】...
- iscroll4升级到iscroll5全攻略笔记
- 什么才是AI公司的商业模式?
- MSP430F149学习随笔(三)
热门文章
- lighttpd http响应报文(Response)增加安全头Referrer-Policy和X-Permitted-Cross-Domain-Policies方法
- 定义并实现一个银行类
- 贝塔自助授权系统php源码,贝塔自助授权系统v1.1
- 阿里云服务器+N2N搭建远程办公环境
- 2014大众点评Hackathon参赛感想
- jpa+hibernate整合达梦数据库(附源码)
- 天津财经大学珠江学院考计算机二级,【2019年12月天津计算机二级考试报名入口已开通】- 环球网校...
- Java实现坦克大战小游戏
- 2014省赛----神奇算式(填空)
- Day001-2021-07-29 变量定义/数据类型/基础运算 判断/循环/数组