htmlparser是一個純的java寫的html解析的庫,它不依賴于其它的java庫檔案,主要用于改造或提取html。它能超高速解析html,而且不會出錯。
毫不誇張地說,htmlparser就是目前最好的html解析和分析的工具。
無論你是想抓取網頁資料還是改造html的内容,用了htmlparser絕對會忍不住稱贊。
<b></b>
<b>簡單的教程:</b>
(1)、資料組織分析:
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:文本節點
(2)、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組合是難以做成什麼事情的。
(3)、系統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:用來修改網頁中的連結。
(4)、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來過濾節點,提取出我們所關注的節點,再對節點進行處理。通過這樣的組合,一定能夠找出我們所需要的資訊。
<b>代碼例子:</b>
htmlparser取得一段html代碼裡面所有的連結C#版本,java版本類似:
string htmlcode = "<HTML><HEAD><TITLE>AAA</TITLE></HEAD><BODY>" + ...... + "</BODY></HTML>";
Parser parser = Parser.CreateParser(htmlcode, "GBK");
HtmlPage page = new HtmlPage(parser);
try
{ parser.VisitAllNodesWith(page);}
catch (ParserException e1)
{ e1 = null;}
NodeList nodelist = page.Body;
NodeFilter filter = new TagNameFilter("A");
nodelist = nodelist.ExtractAllNodesThatMatch(filter, true);
for (int i = 0; i < nodelist.Size(); i++)
{
LinkTag link=(LinkTag) nodelist.ElementAt(i);
System.Console.Write(link.GetAttribute("href") + "/n");
}