轉自:http://tangyaot-yahoo-cn.iteye.com/blog/1460487
Htmlparser源代碼分析
一.根目錄下的類
1.Attribute.java
屬性類,四個field:mName,mAssignment,mValue,mQuote;
空白標籤時:mName=null
除了',"兩引號和自定義參數字符表示的分隔號外,mQuote的值都以 char類型的0字符表示。
其中的getName(StringBufferbuffer)等方法,意思是將所獲得的結果存入buffer內。
如果使用setRawValue()方法進行對mQuote,和,mValue賦值的時候,首尾都是雙引號或者單引號則將單引號或雙引號作爲mQuote,字符串的其他部分作爲mValue.如果首尾不同時爲一種引號則對mQuote用雙引號賦值,字符其他部分作爲mValue.如果字符串中沒有引號,並且所有字符都是由-,_,:,.和字母與數字組成,則mQuote會被用char類型的0賦值。即爲空
例如:
"abcdefg"-------------------->mQuote:" mValue: abcdefg
'abcdefg'---------------------->mQuote:' mValue: abcdefg
'abcdefg"---------------------->mQuote:" mValue: 'abcdefg"
abc-defg---------------------->mQuote:(空格) mValue: abc-defg
如果字符串中有非首尾的引號或者只有首或者尾的引號,或者有除了-,_,:,.這幾個符號以及數字和字母外的其他符號會被補上引號(字符串中沒有單引號就補單引號,沒有雙引號就補雙引號,如果都有則補雙引號,並且字符串中的雙引號被替換爲")。
例如:
abc'de"fg---------------------->mQuote:" mValue: abc'de"fg
&abcdefg--------------------->mQuote:" mValue: &abcdefg
%a'bcd"efg-------------------->mQuote:" mValue: %a'bcd"efg
%abcd"efg--------------------->mQuote:' mValue: %abcd"efg
2.Node.java (interface) extendsCloneable
StringtoPlainTextString();
StringtoHtml();
StringtoHtml(booleanverbatim);//如果verbatim爲true相比上面一個會更接近源 page。但是通過這個工具庫對這個方法的實現情況來看,以上三個方法完全一致verbatim並不起到任何作用。
voidcollectInto(NodeListlist,NodeFilterfilter);
//將這個Node以及它的所有子Node都用filter過濾器過濾後放入list.中
intgetStartPosition();//獲取該node的起始mPosition
voidsetStartPosition();//設置
voidaccept(NodeVisitorvisitor);//爲這個node添加一個visitor
voidsetParent();
voidsetChildren(NodeListchildren);//還可以通過getLastChildren等等獲取第一個或者最後一個child,但是設置就不可以。可以通過getPreviousSibling()這個node前後的兄弟姐妹node。
voiddoSemanticAction();//Performthemeaningofthistag.執行這個標籤的所表達的意思。執行該node(TagNode)的語義動作。
3.NodeFactory (interface) Thisinterfacedefinesthemethodsneededtocreatenewnodes.
Text creatStringNode(Pagepage,intstart,intend);//創建textnode
Remark creatRemarkNode(Pagepage,intstart,intend);//創建remarknode
Tag creatTagNode(Pagepage,intstart,intend,Vectorattributes);//創建tagnode
Attributes爲這個標籤的所有屬性
4.PrototypicalNodeFactory
這個類實現了NodeFactory接口,具備創建原型node的能力,這個類還有一個Map用來存儲註冊的各種Tag.
5.Remark(interface)
6.Text(interface)
這個接口比較複雜,內容較多.因爲html裏面大都是Tag
7.Tag (interface)
這3個接口用來確定3種node的行爲特徵
8.NodeFilter(interface) extends Serializable,Cloneable
可序列化
唯一一個方法boolean accept(Nodenode);決定是否保留所給的這個node
即過濾器!
9.Parser implements Serializable,ConnectionMonitor
語義分析核心類,也是這個工具庫的核心應用類
二.http目錄
1.HttpHeader UtilitymethodstodisplayHTTPheaders.
所有方法都是靜態的。
獲取要發送請求的header:getRequestHeader(HttpURLConnectionconnection);static
獲取接受到的請求的headergetResponseHeader(HttpURLConnectionconn);static
三.Lexer目錄
1.Page RepresentsthecontentsofanHTMLpage.
用Source作爲buffer存儲結構用來存儲數據
Source與Reader類似。InputStreamSource與InputStreamReader類似。
StringSource與StringReader類似。
2.Cursor Abookmarkinapage.
implementsSerializable,Ordered,Cloneable接口
總共有2個Field:intmPosition;PagemPage;後者表示所在的頁面,前者表示所在該頁面中的具體position。Ordered接口排序是通過mPosition大小進行排序。
這個類除了這兩個Field的set/get方法外還有以下幾個方法,功能如下:
Voidadvance(); //mPosition++;向前進一步
Voidretreat(); //mPosition--;後撤一步,當mPosition小於0的時候則令mPosition=0;
Cursordup() ;//返回Cursor的克隆實例。如果不支持克隆就創建一個新的Cursor實例Field值與源實例相同。
3.PageIndex Asortedarrayofintegers,thepositionsofthefirstcharactersofeachline.
這個類的核心字段int[]mIndices;用來存儲對應Page的每行的index和該行末尾字符的mPosition的值之間的對應關係
除了一些對這個數組元素的普通操作方法之外還有row();和column();方法用來獲取位置具體信息。elementAt(index);能夠獲取index表示的那一行最後一個字符的mPosition信息。
4.PageAttribute (extendsAttribute)
比Attribute多了5個Field,分別爲mNameStart,mNameEndmValueStartmValueEnd;這4個字段作用於自身的Page字段。相對於Attribute類,我們可以通過mNameStart,mNameEnd來獲取某個Attribute的name信息,我們可以通過mNameEnd,mValueStart來獲取Attribute的Assignment信息,我們還可以通過mValueStart,mValueEnd來獲取Attribute的value信息,當然這都是建立在Page存在的基礎之上。如果page爲null那麼自然就無法根據這些字段來獲取相應信息了。大體方法與Attribute一致。只不過在內部調用了super()而已。
5.lexer ThisclassparsestheHTMLstreamintonodes(threetypeofnodes).{Remark,Text,Tag}
四.Util目錄
1.NodeIterator
接口,節點迭代器。有2個未實現方法
booleanhasMoreNodes();
NodenextNode();
該迭代器的實現類:IteratorImpl
該迭代器的繼承接口:SimpleNodeIterator
2.IteratorImpl
3.ParserFeedback
接口,Parser的反饋機制
Info,error,warning
4.DefaultParserFeedback
ParserFeedback的默認實現類,可序列化。
能表示3種模式,分別爲QUIET,NORMAL,DEBUG
無參數構造器默認構造爲NORMAL模型
5.FeedbackManager
DefaultParserFeedback的一個代理
6.Sort
提供快速排序以及2分查找。
7.CharacterReference
實現序列化接口。實現Ordered接口,可用Sort進行排序和查找
8.Translate
Translatenumericcharacterreferencesandcharacterentityreferencestounicodecharacters.)
Lookup();2分查找。decode()解碼。encode()編碼
都爲static方法。
9.NodeList
主要字段nodeData[],這個List中Node是存在數組中的
添加node時可以選擇add();也可以選擇prepend();前者添加在尾部,後者添加在頭部。可以獲取部分Node:extractAllNodesThatMatch(NodeFilter,boolean);也可以保留一部分Node(源List中刪除一些Node):keepAllNodesThatMatch(NodeFilter).
10.NodeTreeWalker
可以將Node集合構建成樹形然後通過樹形的方法來獲取Node
11.ParserUtil
靜態實用工具類
1.removeChars(String,char),移除指定字符串中的字符
2.removeEscapeCharacters(StringinputString);移除指定字符串中的'\t','\n','\r'字符
3.removeTrailingBlanks(String);移除指定字符串末尾的空白符
4.findTypeInNode(Node,Class);返回指定Node中所有符合Class的子類的數組
5.splitButDigits(String,String);
6.trimButDigits(String,String);除了數字和需要的字符集合以外的字符都清空
7.trimButDigitsBeginEnd(String,String);和上一個差不多,只不過是取出頭尾部分
8.splitSpaces(String,String);trimSpaces(String,String);第二個參數是需要刪除的而不 是保留的
9.其他的和之前兩個差不多,方法裏面有But則第二個參數爲需要保留的,否則爲需 要刪除的
10.createParserParsingAnInputString(String);根據字符串返回parser
五.Nodes目錄
1.AbstractNode (abstract) implementsNode,Serializable
對Node接口中的抽象方法部分進行了簡單實現。
除了一下幾個:
StringtoPlainTextString();
StringtoHtml(booleanverbatim);
StringtoString();
voidaccept(NodeVisitorvisitor);
2.TextNode extendsAbstractNodeimplementsText
對AbstractNode抽象類中的上述沒有實現的方法進行了實現,其中toPlainTextString();與toHtml(booleanverbatim)與toHtml();3個方法等價。Verbatim
不起作用
主要方法:setText();getText();accept();
3.RemarkNode extendsAbstractNodeimplementsRemark
繼承了AbstractNode實現了其中toPlainTextString();方法,但是隻是返回一個空字符串;實現了toHtml(booleanverbatim)方法,verbatim仍然不起作用,這個方法返回的是html的註釋形式:<!——mText——>其中mText爲這個類的Field
Accept()方法也被實現了,與TextNode實現之前的區別是visitor使用了與Text,Remark對應的不同的方法。
4.TagNode extendsAbstractNodeimplementsTag
Field:
A).finalstaticString[]NONE;
a)//Anemptysetoftagnames.
B).ScannermScanner;
a)//這個標籤的掃描器
C).finalstaticScannermDefaultScanner=newTagScanne();
a)//非複合標籤的默認掃描器
D).VectormAttributes;
a)//這個Tag的屬性集合
E).staticHashtablebreakTags;
a)//Hashtable<K,V>,用來記錄標籤:
static
{
breakTags=newHashtable(30);
breakTags.put("BLOCKQUOTE",Boolean.TRUE);
breakTags.put("BODY",Boolean.TRUE);
breakTags.put("BR",Boolean.TRUE);
breakTags.put("CENTER",Boolean.TRUE);
breakTags.put("DD",Boolean.TRUE);
breakTags.put("DIR",Boolean.TRUE);
breakTags.put("DIV",Boolean.TRUE);
breakTags.put("DL",Boolean.TRUE);
breakTags.put("DT",Boolean.TRUE);
breakTags.put("FORM",Boolean.TRUE);
breakTags.put("H1",Boolean.TRUE);
breakTags.put("H2",Boolean.TRUE);
breakTags.put("H3",Boolean.TRUE);
breakTags.put("H4",Boolean.TRUE);
breakTags.put("H5",Boolean.TRUE);
breakTags.put("H6",Boolean.TRUE);
breakTags.put("HEAD",Boolean.TRUE);
breakTags.put("HR",Boolean.TRUE);
breakTags.put("HTML",Boolean.TRUE);
breakTags.put("ISINDEX",Boolean.TRUE);
breakTags.put("LI",Boolean.TRUE);
breakTags.put("MENU",Boolean.TRUE);
breakTags.put("NOFRAMES",Boolean.TRUE);
breakTags.put("OL",Boolean.TRUE);
breakTags.put("P",Boolean.TRUE);
breakTags.put("PRE",Boolean.TRUE);
breakTags.put("TD",Boolean.TRUE);
breakTags.put("TH",Boolean.TRUE);
breakTags.put("TITLE",Boolean.TRUE);
breakTags.put("UL",Boolean.TRUE);
}
toPlainTextString();方法返回的是空字符串,和RemarkNode一樣。toHtml()
中的參數也和RemarkNode一樣不起作用。這裏有幾個方法是需要注意區分
getAttribute(Stringname);//通過屬性名獲取這個屬性的值。
getAttributeEx(Stringname)//通過屬性名獲取整個屬性對象Attribute
getAttributesEx();//獲取所有屬性對象Attributes,返回值是Vector
------------------------------------------------------------------------------------------
String[]getIds();
String[]getEnders();
String[]getEndTagEnders();
3者一致,返回的都是NONE字段,以後具體Tag類型的繼承TagNode的時候會用各自的方法把它們覆蓋掉。
//原創地址:
http://write.blog.csdn.net/postedit;轉載請註明出處,蟄伏神獸
六.Tags目錄
1.CompositeTag extendsTagNode
Thebaseclassfortagsthathaveanendtag.
這個類囊括了Tag標籤的幾乎所有操作。除了一般的獲取孩子標籤:children();getChild();;getChildrenAsNodeArray();elements();移除孩子標籤:removeChild();將所有孩子以字符串形式返回toPlainTextString();或者以字符串形式導入到緩存buffer:putChildrenInto();獲取具體位置的子標籤Node:childAt();以及將所有孩子標籤通過filter過濾器存入NodeList中:collectInto(NodeList,NodeFilter);等等方法外,還有些比較重要的方法:
A).TagsearchByName(Stringname);
//用來在孩子標籤中查找擁有name(這個name是參數)屬性的第一個標籤。
B).NodeListsearchFor(StringsearchString,booleancaseSensitive,Localelocale);
//在孩子標籤中查找包含searchString字符串的Node,並將這些Node都放入NodeList中,然後返回NodeList;
C).intfindPositionOf(Stringtext,Localelocale);
//返回在孩子標籤中第一個包含text字符串的標籤的具體位置(在NodeList中的Index位置,而不是Cursor類中那樣的mPosition位置)
D).Text[]digupStringNode(StringsearchText);
//首先通過searchText找出子標籤中包換這個字符串的所有標籤。然後再從這些標籤中挑出屬於Text的節點組成Text[]返回
這個類算是Tags目錄中最重要的一個類。所有的複合標籤都需要繼承這個類。
1.BodyTag===========>"BODY";//getBody();內部調用額是toPlainTextString();
2.Bullet==============>"LI"
3.BulletList===========>"UL","OL"
4.Div===============>"DIV"
5.HeadingTag=========>"H1","H2","H3","H4","H5","H6"
6.HeadTag===========>"HEAD"
7.Html==============>"HTML"
8.InputTag===========>"INPUT"
9.JspTag============>"%","%=","%@"
10.LabelTag===========>"LABEL"
11.ParagraphTag========>"P"
12.ProcessingInstructionTag==>"?"
13.SelectTag===========>"SELECT"
14.Span===============>"SPAN"
15.StyleTag============>"STYLE"
16.TableColumn=========>"TD"
17.TableHeader==========>"TH"
18.TableRow============>"TR"
19.TableTag===============>"TABLE"
20.TextAreaTag============>"TEXTAREA"
21.TitleTag================>"TITLE"
22.DoctypeTag=============>"!DOCTYPE"
23.DefinitionListBullet========>"DD","DT"
24.DefinitionList=============>"DL"
以上的24個標籤都相對比較簡單。內部有2個或者3個字段,之中一個String[]ids就是箭頭右邊的那個字符串。另外一個或者2個字段是終結各自的終結符。
----------------------------------------------------------------------------------------------------
1.BaseHrefTag "BASE";
//setBaseUrl();getBaseUrl();對href屬性取賦值
//對doSemanticAction()的實現也是如此:page.setBaseUrl(getBaseUrl());
2.OptionTag "OPTION"
//setValue();getValue();對value屬性取賦值
//getOptionText();通過調用toPlainTextString()實現
3.FrameTag "FRAME"
//setFrameLocation();getFrameLocation();對src屬性取賦值
4.FormTag "FORM"
//有POST,GET兩靜態字段來表示FORM傳遞數據的方式
//getFormInputs();抓取子標籤中的所有InputTag並打包以NodeList返回。
//getFormTextareas();抓取子標籤中的所有TextAreaTag並打包以NodeList返回。
//getFormMethod();對method屬性取值
//getFormName();對name屬性取值
//setFormLocation();getFormLocation();extractFormLocn()對action屬性取賦值
//getInputTag(Stringname);找出name屬性爲提供參數的InputTag.
5.ImageTag "IMG"
//字段p_w_picpathUrl表示String類型的p_w_picpath地址
//extractImageLocn();獲取相對/絕對地址SRC的屬性取值
//getImageUrl();獲取絕對地址SRC的屬性取值
//setImageUrl();設置絕對地址SRC的屬性賦值
6.FrameSetTag "FRAMESET"
//getFrames(),setFrames();對該標籤的孩子標籤取賦值
//getFrame(Stringname,Localelocale);通過名字從Tag孩子中找出符合要求的//FrameTag
//原創地址:
http://hi.csdn.net/space-8079523.html;轉載請註明出處,蟄伏神獸
7.MetaTag "META"
//setHttpEquiv();getHttpEquiv();對HTTP-EQUIV屬性的取賦值
//setMetaTagContents();getMetaContent();對CONTENT屬性的取賦值
//setMetaTagName();getMetaTagName();對NAME屬性的取賦值
//doSemanticAction();的實現:(設置了一下編碼)
//if("Content-Type".equalsIgnoreCase(httpEquiv)){
//charset=getPage().getCharset(getAttribute("CONTENT"));
//getPage().setEncoding(charset);
//}
8.ScriptTag "SCRIPT"
//字段mCode表示Script的編碼
//getLanguage();setLanguage();對LANGUAGE屬性的取賦值
//setType();getType();對TYPE屬性的取賦值
//putChildrenInto(StringBuffersb,booleanverbatim);把所有孩子節點都存入sb中.
9.LinkTag "A"
//字段mLink;表示這個link的URL值
//字段mailLink,如果爲true,則表示這個link爲郵件地址
//字段javascriptLink,如果爲true,則表示這個link爲javascript文件地址
//getAccessKeyt();對ACCESSKEY屬性的取值
//extractLink();獲取URL值
//getLink();獲取URL值,與上一個方法的區別是這個值將會把"mailto:","javascript:"
//去掉。並且對mailLink或者javascriptLink字段進行設置。setLink();對href賦值
//getLinkText();如果標籤有孩子,就會返回所有孩子的字符串形式。
//isFTPLink();isIRCLink();isHTTPLink();isHTTPSLink();isHTTPLikeLink();按字面意//思理解實現的話都是通過字符串匹配實現的。
//其中isHTTPSLikeLink()=isHTTPSLink()||isHTTPLink();
10.AppletTag "APPLET"
//HashtablecreateAppletParamsTable();param標籤的name屬性和value屬性
//setAppletClass();getAppletClass();對CODE屬性取賦值
//setArchive();getArchive();對ARCHIVE屬性取賦值
//setCodeBase();getCodeBase();對CODEBASE屬性取賦值
11.ObjectTag"OBJECT"
//setObjectClassId();getObjectClassId();對CLASSID屬性的取賦值
//setObjectCodeBase();getObjectCodeBase();對CODEBASE屬性的取賦值
//setObjectCodeType();getObjectCodeType();對CODETYPE屬性的取賦值
//setObjectData();getObjectData();對DATA屬性的取賦值
//setObjectHeight();getObjectHeight();對HEIGHT屬性的取賦值
//setObjectStandby();getObjectStandby();對STANDBY屬性的取賦值
//setObjectType();getObjectType();對TYPE屬性的取賦值
//setObjectWidth();getObjectWidth();對WIDTH屬性的取賦值
//setObjectParams();設置對象屬性;
七.filters目錄
這個目錄中的類都實現了NodeFilter接口。這個接口只有一個方法accept(Nodenode);
1.IsEqualFilter Thisclassacceptsonlyonespecificnode.
booleanaccept(Nodenode);如果相等返回true,不相等返回false
2.AndFilter Acceptsnodesmatchingallofitspredicatefilters(ANDoperation).
//字段mPredicates存放被用於過濾的所有過濾器,這個類其實就是多個過濾
//器的集合,只不過通過它需要通過所有mPredicates存放的過濾器而已。
//當然他提供了相應的方法來獲取和設置存儲的過濾器
3.OrFilter Acceptsnodesmatchinganyofitspredicatesfilters(ORoperation).
//與AndFilter過濾器基本一致。只是accept()的實現中把false改成了true。功能顯 //而易見
4.NotFilter Acceptsallnodesnotacceptabletoit'spredicatefilter.
//字段mPredicate 存放過濾器
//accept();實現return((null!=mPredicate)&&!mPredicate.accept(node));
5.XorFilter
//和or基本一致,只是or是隻需在所有filter裏面有一個匹配就行,而xor則是需//要奇數個匹配。
6.HasChildFilter//這個Node的孩子能夠通過指定Filter
7.HasParentFilter//這個Node的父親能夠通過指定Filter
8.HasSiblingFilter//這個Node的兄弟能夠通過指定Filter
9.HasAttributeFilter//這個Node需要有指定的Attribute包括name,value
10.NodeClassFilter
//這個Node需要與指定class相關,就是說class可能是這個Node的父類//或者父接口的class,或者是這個類本身的class
11.TagNameFilter
//這個Node只有是TagNode,並且不是EndTag,並且是指定名字的才能通過
12.LinkStringFilter
//這個Node只有是LinkTag或者繼承LinkTag的類,並且URL中需要包含指定字 //符串才能通過,可以設定大小寫敏感
13.LinkRegexFilter
//有個PatternmRegex字段,存放需要匹配的Pattern
//這個Node只有是LinkTag或者繼承LinkTag的類,並且URL必須與給定的Pattern //匹配才能通過(部分匹配,使用的是Matcher的find()方法)。可以設置大小寫敏感
14.StringFilter
//這個Node只有是Text,並且內容必須包含指定字符串才能通過,可以設置大小 //寫敏感
15.RegexFilter
//有3中策略MATCH,LOOKINGAT,FIND.分別代表Matcher類的3個方法
//Matcher.matches();匹配整個字符串
//Matcher.lookingAt();從頭開始匹配,如果匹配則true,不用掃描整個字符串
//Matcher.find();只要有子序列匹配返回true
16.CssSelectorNodeFilter
//css選擇器過濾器比較複雜,用到的時候再看。
//原創地址:http://hi.csdn.net/space-8079523.html;轉載請註明出處,蟄伏神獸
八.visitors 這些visitor意思就是在給定的字符序列或者數組中查找需要的內容並且 記錄找到的個數
1.NodeVisitor
//這個包的基礎Visitor定義visitor的基本動作:
//voidbeginParsing()
//voidvisitTag(Tagtag)
//voidvisitEndTag(Tagtag)
//voidvisitStringNode(Textstring)
//voidvisitRemarkNode(Remarkremark)
//voidfinishedParsing()
//以及兩個遞歸的執行與否
2.TagFindingVisitor
//一個參數的構造器默認不檢查結束標籤(endTag)
//在傳入的一個待查找TagName數組中找出指定Tag以及這個Tag的個數(指定後//endTag也可以查)
3.StringFindingVisitor
//Field:
//StringstringToFind;
//boolean multipleSearchesWithinStrings;
//visitorStringNode(Text stringNode);
//在TextNode的text中查找stringToFind的個數
//如果multipleSearchesWithinStrings字段爲false那麼一次只能查到一個,查到後立//即返回了.如果爲True那麼一次visitor就能把text包含的stringToFind都招出來例//如:stringToFind=aaa;
Text=aaaaaaaaa;
那麼能找到3個。(注意不是7個)
4.ObjectFindVisitor
//查找與指定class一直的tag對象;一次比較一個tag對象
5.LinkFindVisitor
//和StringFindVisitor差不多只不過只能訪問Tag對象
6.TextExtractingVisitor
//在Text中提取text內容
7.UrlModifyingVisitor
//給相應Node添加url前綴。
8.HtmlPage
//
九.scanner目錄
1.Scanner (interface)
publicTagscan(Tagtag,Lexerlexer,NodeListstack)throwsParserException;
2.TagScanner
//scan的實現:
//tag.doSemanticAction();
//returntag;
3.JspScanner (extends)TagScanner
//比前者多了一個無參數構造器
4.StyleScanner
//
5.ScriptDecoder
//爲script解碼
因爲小弟是初次使用htmlparser所有職能簡單的分析源代碼,也沒有什麼創新的見解。權當備案,以後用多了在來補充編輯。大家勿噴