htmlparser使用指南.docx
《htmlparser使用指南.docx》由会员分享,可在线阅读,更多相关《htmlparser使用指南.docx(15页珍藏版)》请在冰豆网上搜索。
htmlparser使用指南
HTMLPARSER使用指南
Posted五月19,2008 Comments(11)
需要做一个垂直搜索引擎,比较了nekohtml和htmlparser的功能,尽管nekohtml在容错性、性能等方面的口碑好像比htmlparser好(htmlunit也用的是nekohtml),但感觉nekohtml的测试用例和文档都比htmlparser都少,而且htmlparser基本上能够满足垂直搜索引擎页面处理分析的需求,因此先研究一下htmlparser的使用,有空再研究nekohtml和mozillahtmlparser的使用。
html的功能还是官方说得最为清楚,
HTMLParserisaJavalibraryusedtoparseHTMLineitheralinearornestedfashion.Primarilyusedfortransformationorextraction,itfeaturesfilters,visitors,customtagsandeasytouseJavaBeans.Itisafast,robustandwelltestedpackage.
Thetwofundamentaluse-casesthatarehandledbytheparserare extraction andtransformation (thesynthesesuse-case,whereHTMLpagesarecreatedfromscratch,isbetterhandledbyothertoolsclosertothesourceofdata).Whilepriorversionsconcentratedondataextractionfromwebpages,Version1.4oftheHTMLParserhassubstantialimprovementsintheareaoftransformingwebpages,withsimplifiedtagcreationandediting,andverbatimtoHtml()methodoutput.
研究的重点还是extraction的使用,有空再研究transformation的使用。
1、htmlparser对html页面处理的数据结构
如图所示,HtmlParser采用了经典的Composite模式,通过RemarkNode、TextNode、TagNode、AbstractNode和Tag来描述HTML页面各元素。
∙org.htmlparser.Node:
Node接口定义了进行树形结构节点操作的各种典型操作方法,包括:
节点到html文本、text文本的方法:
toPlainTextString、toHtml
典型树形结构遍历的方法:
getParent、getChildren、getFirstChild、getLastChild、getPreviousSibling、getNextSibling、getText
获取节点对应的树形结构结构的顶级节点Page对象方法:
getPage
获取节点起始位置的方法:
getStartPosition、getEndPosition
Visitor方法遍历节点时候方法:
accept(NodeVisitorvisitor)
Filter方法:
collectInto(NodeListlist,NodeFilterfilter)
Object方法:
toString、clone
∙org.htmlparser.nodes.AbstractNode:
AbstractNode是形成HTML树形结构抽象基类,实现了Node接口。
在htmlparser中,Node分成三类:
RemarkNode:
代表Html中的注释
TagNode:
标签节点。
TextNode:
文本节点
这三类节点都继承AbstractNode。
∙org.htmlparser.nodes.TagNode:
TagNode包含了对HTML处理的核心的各个类,是所有TAG的基类,其中有分为包含其他TAG的复合节点ComositeTag和不包含其他TAG的叶子节点Tag。
复合节点CompositeTag:
AppletTag,BodyTag,Bullet,BulletList,DefinitionList,DefinitionListBullet,Div,FormTag,FrameSetTag,HeadingTag,
HeadTag,Html,LabelTag,LinkTag,ObjectTag,ParagraphTag,ScriptTag,SelectTag,Span,StyleTag,TableColumn,
TableHeader,TableRow,TableTag,TextareaTag,TitleTag
叶子节点TAG:
BaseHrefTag,DoctypeTag,FrameTag,ImageTag,InputTag,JspTag,MetaTag,ProcessingInstructionTag,
2、htmlparser对html页面处理的算法
主要是如下几种方式
∙采用Visitor方式访问Html
try{
Parserparser=newParser();
parser.setURL(“”);
parser.setEncoding(parser.getEncoding());
NodeVisitorvisitor=newNodeVisitor(){
publicvoidvisitTag(Tagtag){
logger.fatal(“testVisitorAll() Tagnameis:
”
+tag.getTagName()+”\nClassis:
”
+tag.getClass());
}
};
parser.visitAllNodesWith(visitor);
}catch(ParserExceptione){
e.printStackTrace();
}
∙采用Filter方式访问html
try{
NodeFilterfilter=newNodeClassFilter(LinkTag.class);
Parserparser=newParser();
parser.setURL(“”);
parser.setEncoding(parser.getEncoding());
NodeListlist=parser.extractAllNodesThatMatch(filter);
for(inti=0;iLinkTagnode=(LinkTag)list.elementAt(i);
logger.fatal(“testLinkTag()Linkis:
”+node.extractLink());
}
}catch(Exceptione){
e.printStackTrace();
}
∙采用org.htmlparser.beans方式
另外htmlparser还在org.htmlparser.beans中对一些常用的方法进行了封装,以简化操作,例如:
Parserparser=newParser();
LinkBeanlinkBean=newLinkBean();
linkBean.setURL(“”);
URL[]urls=linkBean.getLinks();
for(inti=0;iURLurl=urls[i];
logger.fatal(“testLinkBean()-url is:
”+url);
}
3、htmlparser关键包结构说明
htmlparser其实核心代码并不多,好好研究一下其代码,弥补文档不足的问题。
同时htmlparser的代码注释和单元测试用例还是很齐全的,也有助于了解htmlparser的用法。
3.1、org.htmlparser
定义了htmlparser的一些基础类。
其中最为重要的是Parser类。
Parser是htmlparser的最核心的类,其构造函数提供了如下:
Parser.createParser(Stringhtml,Stringcharset)、Parser()、Parser(Lexerlexer,ParserFeedbackfb)、Parser(URLConnectionconnection,ParserFeedbackfb)、Parser(Stringresource,ParserFeedbackfeedback)、Parser(Stringresource)
各构造函数的具体用法及含义可以查看其代码,很容易理解。
Parser常用的几个方法:
∙ elements获取元素
Parserparser=newParser(“”);
for(NodeIteratori=parser.elements();i.hasMoreElements();)
processMyNodes(i.nextNode());
∙parse(NodeFilterfilter):
通过NodeFilter方式获取
∙visitAllNodesWith(NodeVisitorvisitor):
通过Nodevisitor方式
∙extractAllNodesThatMatch(NodeFilterfilter):
通过NodeFilter方式
3.2、org.htmlparser.beans
对Visitor和Filter的方法进行了封装,定义了针对一些常用html元素操作的bean,简化对常用元素的提取操作。
包括:
FilterBean、HTMLLinkBean、HTMLTextBean、LinkBean、StringBean、BeanyBaby等。
3.3、org.htmlparser.nodes
定义了基础的node,包括:
AbstractNode、RemarkNode、TagNode、TextNode等。
3.4、org.htmlparser.tags
定义了htmlparser的各种tag。
3.5、org.htmlparser.filters
定义了htmlparser所提供的各种filter,主要通过extractAllNodesThatMatch(NodeFilterfilter)来对html页面指定类型的元素进行过滤,包括:
AndFilter、CssSelectorNodeFilter、HasAttributeFilter、HasChildFilter、HasParentFilter、HasSiblingFilter、IsEqualFilter、LinkRegexFilter、LinkStringFilter、NodeClassFilter、NotFilter、OrFilter、RegexFilter、StringFilter、TagNameFilter、XorFilter
3.6、org.htmlparser.visitors
定义了htmlparser所提供的各种visitor,主要通过visitAllNodesWith(NodeVisitorvisitor)来对html页面元素进行遍历,包括:
HtmlPage、LinkFindingVisitor、NodeVisitor、ObjectFindingVisitor、StringFindingVisitor、TagFindingVisitor、TextExtractingVisitor、UrlModifyingVisitor
3.7、org.htmlparser.parserapplications
定义了一些实用的工具,包括LinkExtractor、SiteCapturer、StringExtractor、WikiCapturer,这几个类也可以作为htmlparser使用样例。
3.8、org.htmlparser.tests
对各种功能的单元测试用例,也可以作为htmlparser使用的样例。
4、htmlparser的使用样例
import.URL;
importjunit.framework.TestCase;
importorg.apache.log4j.Logger;
importorg.htmlparser.Node;
importorg.htmlparser.NodeFilter;
importorg.htmlparser.Parser;
importorg.htmlparser.Tag;
importorg.htmlparser.beans.LinkBean;
importorg.htmlparser.filters.NodeClassFilter;
importorg.htmlparser.filters.OrFilter;
importorg.htmlparser.filters.TagNameFilter;
importorg.htmlparser.tags.HeadTag;
importorg.htmlparser.tags.ImageTag;
importorg.htmlparser.tags.InputTag;
importorg.htmlparser.tags.LinkTag;
importorg.htmlparser.tags.OptionTag;
importorg.htmlparser.tags.SelectTag;
importorg.htmlparser.tags.TableColumn;
importorg.htmlparser.tags.TableRow;
importorg.htmlparser.tags.TableTag;
importorg.htmlparser.tags.TitleTag;
importorg.htmlparser.util.NodeIterator;
importorg.htmlparser.util.NodeList;
importorg.htmlparser.util.ParserException;
importorg.htmlparser.visitors.HtmlPage;
importorg.htmlparser.visitors.NodeVisitor;
importorg.htmlparser.visitors.ObjectFindingVisitor;
publicclassParserTestCaseextendsTestCase{
privatestaticfinalLoggerlogger=Logger.getLogger(ParserTestCase.class);
publicParserTestCase(Stringname){
super(name);
}
/*
*测试ObjectFindVisitor的用法
*/
publicvoidtestImageVisitor(){
try{
ImageTagimgLink;
ObjectFindingVisitorvisitor=newObjectFindingVisitor(
ImageTag.class);
Parserparser=newParser();
parser.setURL(“”);
parser.setEncoding(parser.getEncoding());
parser.visitAllNodesWith(visitor);
Node[]nodes=visitor.getTags();
for(inti=0;iimgLink=(ImageTag)nodes[i];
logger.fatal(“testImageVisitor()ImageURL=”
+imgLink.getImageURL());
logger.fatal(“testImageVisitor()ImageLocation=”
+imgLink.extractImageLocn());
logger.fatal(“testImageVisitor()SRC=”
+imgLink.getAttribute(“SRC”));
}
}
catch(Exceptione){
e.printStackTrace();
}
}
/*
*测试TagNameFilter用法
*/
publicvoidtestNodeFilter(){
try{
NodeFilterfilter=newTagNameFilter(“IMG”);
Parserparser=newParser();
parser.setURL(“”);
parser.setEncoding(parser.getEncoding());
NodeListlist=parser.extractAllNodesThatMatch(filter);
for(inti=0;ilogger.fatal(“testNodeFilter()”+list.elementAt(i).toHtml());
}
}catch(Exceptione){
e.printStackTrace();
}
}
/*
*测试NodeClassFilter用法
*/
publicvoidtestLinkTag(){
try{
NodeFilterfilter=newNodeClassFilter(LinkTag.class);
Parserparser=newParser();
parser.setURL(“”);
parser.setEncoding(parser.getEncoding());
NodeListlist=parser.extractAllNodesThatMatch(filter);
for(inti=0;iLinkTagnode=(LinkTag)list.elementAt(i);
logger.fatal(“testLinkTag()Linkis:
”+node.extractLink());
}
}catch(Exceptione){
e.printStackTrace();
}
}
/*
*测试用法
*/
publicvoidtestLinkCSS(){
try{
Parserparser=newParser();
parser
.setInputHTML(“
LinkTest”
+“”
+“”
+“”+“
”);
parser.setEncoding(parser.getEncoding());
NodeListnodeList=null;
for(NodeIteratore=parser.elements();e.hasMoreNodes();){
Nodenode=e.nextNode();
logger
.fatal(“testLinkCSS()”+node.getText()
+node.getClass());
}
}catch(Exceptione){
e.printStackTrace();
}
}
/*
*测试OrFilter的用法
*/
publicvoidtestOrFilter(){
NodeFilterinputFilter=newNodeClassFilter(InputTag.class);
NodeFilterselectFilter=newNodeClassFilter(SelectTag.class);
ParsermyParser;
NodeListnodeList=null;
try{
Parserparser=newParser();
parser
.setInputHTML(“
OrFilterTest”
+“”
+“”
+“”
+“
”
+“”
+“”
+“”
+“”
+“”);
parser.setEncoding(parser.getEncoding());
OrFilterlastFilter=newOrFilter();
lastFilter.setPredicates(newNodeFilter[]{selectFilter,
inputFilter});
nodeList=parser.parse(