這兩天準備作一些網站編程的工做,因而對HtmlParse小研究了一下,目的是快速入手,而不是深刻研究,作了一下整理,和你們共同討論一下。html
一,數據組織分析:
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:文本節點
二,Visitor方式訪問Html:
1,總體解析過程
用一個URL或頁面String作一個Parser
用這個Parser作一個Visitor
使用Parser.visitAllNodeWith(Visitor)來遍歷節點
獲取Visitor遍歷後獲得的數據
2,Visit過程
作解析以前作的事情:visitor.beginParsing();
每次取到一個節點Node,讓該Node接受accept該Visitor
作解析後作的事情:visitor.finishedParsing();
3,獲取節點的過程:逐步遍歷Html,分析出Node。此部分較爲複雜,且對於咱們應用來講無需不少了解,暫跳過。
4,節點訪問
節點訪問採用Visitor模式,Node的accept方法和具體Visitor的visit方法是關鍵。
首先三類Node來accept的方式各不相同:
對於全部TagNode都使用一個accept方法,即TagNode的accept方法。首先判斷是不是標籤結尾,若是是就visitor.visitEndTag (this);不然visitor.visitTag (this);
若是是TextNode,那就visitor.visitStringNode (this);就能夠了。
若是是RemarkNode,那就visitor.visitRemarkNode (this);就能夠了。
實際上NodeVisitor裏邊這四種visit方法都是空的,由於在不一樣的Visitor中對於這三類節點的處理是不一樣的;對於須要處理的節點,只要重載對應的visit方法就好了,若是不處理那就不理會就能夠了;另外,若是用戶用本身的Visitor,那麼還能夠靈活的處理不一樣類型的節點了。
系統爲咱們實現了下面我要介紹的8種Visitor,實際上能夠看做是系統給咱們演示瞭如何作各類各樣的Visitor來訪問Html,由於實際上咱們要真正來用HtmlParser的話,還須要特定的Visitor,而經過簡單的這些系統提供的Visitor組合是難以作成什麼事情的。
三,系統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:用來修改網頁中的連接。
四,Filter
若是說visitor是遍歷提取信息,固然這個信息能夠包括某些節點或者從節點分析出來的更有效的信息,這都取決於咱們的Visitor作成什麼樣子,那麼Filter則目標很明確,就是用來提取節點的。因此說要想用HtmlParser,首先要熟悉上面講到的數據組織。
系統定義了17種具體的Filter,包括依據節點父子關係的Filter,鏈接Filter組合的Filter,依據網頁內容匹配狀況的filter,等等。咱們也能夠implement Filter來作本身的Filter來提取節點。
Filter的調用是同Visitor獨立的,由於也無需先filter出一些NodeList,再用Visitor來訪問。調用Filter的方法是:
NodeList nodeList = myParser.parse(someFilter);
解析以後,咱們能夠採用:
Node[] nodes = nodeList.toNodeArray();
來獲取節點數組,也能夠直接訪問:
Node node = nodeList.elementAt(i)來獲取Node。
另外,在Filter後獲得NodeList之後,咱們仍然可使用NodeList的extractAllNodesThatMatch(someFilter)來進一步過濾,同時又能夠用NodeList的isitAllNodesWith(someVisitor)來作進一步的訪問。
這樣,咱們能夠看到HtmlParser爲咱們提供了很是方便的Html解析方式,針對不一樣的應用能夠採用visitor來遍歷Html節點提取數據,也能夠用Filter來過濾節點,提取出咱們所關注的節點,再對節點進行處理。經過這樣的組合,必定可以找出咱們所須要的信息。
參考:
http://htmlparser.sourceforge.net/
http://www.blogjava.net/rocky/archive/2005/12/21/24997.aspx
http://www.westing.cn/xblog/?p=90
From: http://www.blogjava.net/lostfire/archive/2006/07/02/56212.html