htmlparser 源碼說明

轉自:http://tangyaot-yahoo-cn.iteye.com/blog/1460487

Htmlparser源代碼分析

一.根目錄下的類

1.Attribute.java

屬性類,四個fieldmName,mAssignment,mValue,mQuote;

空白標籤時:mName=null

除了',"兩引號和自定義參數字符表示的分隔號外,mQuote的值都以 char類型的0字符表示。

其中的getNameStringBufferbuffer)等方法,意思是將所獲得的結果存入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

by 蟄伏神獸;http://hi.csdn.net/space-8079523.html;

2.Node.java (interface) extendsCloneable

StringtoPlainTextString();

StringtoHtml();

StringtoHtml(booleanverbatim);//如果verbatimtrue相比上面一個會更接近源 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個接口用來確定3node的行爲特徵

8.NodeFilter(interface) extends Serializable,Cloneable

可序列化

唯一一個方法boolean accept(Nodenode);決定是否保留所給的這個node

即過濾器!

9.Parser implements Serializable,ConnectionMonitor

語義分析核心類,也是這個工具庫的核心應用類

二.http目錄

1.HttpHeader UtilitymethodstodisplayHTTPheaders.

所有方法都是靜態的。

獲取要發送請求的headergetRequestHeader(HttpURLConnectionconnection);static

獲取接受到的請求的headergetResponseHeader(HttpURLConnectionconn);static

三.Lexer目錄

1.Page RepresentsthecontentsofanHTMLpage.

Source作爲buffer存儲結構用來存儲數據

Source與Reader類似。InputStreamSourceInputStreamReader類似。

StringSource與StringReader類似。

2.Cursor Abookmarkinapage.

implementsSerializable,Ordered,Cloneable接口

總共有2FieldintmPosition;PagemPage;後者表示所在的頁面,前者表示所在該頁面中的具體positionOrdered接口排序是通過mPosition大小進行排序。

這個類除了這兩個Fieldset/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多了5Field,分別爲mNameStart,mNameEndmValueStartmValueEnd;4個字段作用於自身的Page字段。相對於Attribute類,我們可以通過mNameStart,mNameEnd來獲取某個Attributename信息,我們可以通過mNameEnd,mValueStart來獲取AttributeAssignment信息,我們還可以通過mValueStart,mValueEnd來獲取Attributevalue信息,當然這都是建立在Page存在的基礎之上。如果pagenull那麼自然就無法根據這些字段來獲取相應信息了。大體方法與Attribute一致。只不過在內部調用了super()而已。

5.lexer ThisclassparsestheHTMLstreamintonodes(threetypeofnodes).{Remark,Text,Tag}

四.Util目錄

1.NodeIterator

接口,節點迭代器。有2個未實現方法

booleanhasMoreNodes();

NodenextNode();

該迭代器的實現類:IteratorImpl

該迭代器的繼承接口:SimpleNodeIterator

2.IteratorImpl

3.ParserFeedback

接口,Parser的反饋機制

Info,errorwarning

4.DefaultParserFeedback

ParserFeedback的默認實現類,可序列化。

能表示3種模式,分別爲QUIETNORMALDEBUG

無參數構造器默認構造爲NORMAL模型

5.FeedbackManager

DefaultParserFeedback的一個代理

6.Sort

提供快速排序以及2分查找。

7.CharacterReference

實現序列化接口。實現Ordered接口,可用Sort進行排序和查找

8.Translate

Translatenumericcharacterreferencesandcharacterentityreferencestounicodecharacters.)

Lookup();2分查找。decode()解碼。encode()編碼

都爲static方法。

9.NodeList

主要字段nodeData[],這個ListNode是存在數組中的

添加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使用了與TextRemark對應的不同的方法。

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;表示這個linkURL

//字段mailLink,如果爲true,則表示這個link爲郵件地址

//字段javascriptLink,如果爲true,則表示這個linkjavascript文件地址

//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 //匹配才能通過(部分匹配,使用的是Matcherfind()方法)。可以設置大小寫敏感

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);

//在TextNodetext中查找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所有職能簡單的分析源代碼,也沒有什麼創新的見解。權當備案,以後用多了在來補充編輯。大家勿噴


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章