正則表達式 _HTMLParser使用詳解-2010-03-21.ppt_第1頁
正則表達式 _HTMLParser使用詳解-2010-03-21.ppt_第2頁
正則表達式 _HTMLParser使用詳解-2010-03-21.ppt_第3頁
正則表達式 _HTMLParser使用詳解-2010-03-21.ppt_第4頁
正則表達式 _HTMLParser使用詳解-2010-03-21.ppt_第5頁
已閱讀5頁,還剩75頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

1、Java正則表達式入門 + HTMLParser使用詳解,一、 Java正則表達式入門 眾所周知,在程序開發(fā)中,難免會遇到需要匹配、查找、替換、判斷字符串的情況發(fā)生,而這些情況有時又比較復雜,如果用純編碼方式解決,往往會浪費程序員的時間及精力。 因此,學習及使用正則表達式,便成了解決這一矛盾的主要手段。 大家都知道,正則表達式是一種可以用于模式匹配和替換的規(guī)范,一個正則表達式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)組成的文字模式,它 用以描述在查找文字主體時待匹配的一個或多個字符串。正則表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。 自從jdk1.4推出java.

2、util.regex包,就為我們提供了很好的JAVA正則表達式應用平臺。,說明,轉(zhuǎn)義符,a,f,響鈴符 = x07,換頁符 = x0C,換頁符,n,響鈴符 = x07,換行 (u000A),r,回車符 = x0D,回車 (u000D),t,制表符 = x09,間隔 (u0009),v,垂直制表符 = x0B,e,ESC 符 = x1B, Escape,x20,使用兩位十六進制表示形式,可與該編號的字符匹配,u002B,使用四位十六進制表示形式,可與該編號的字符匹配,x20A060,使用任意位十六進制表示形式,可與該編號的字符匹配,說明,字符,$,匹配輸入字符串的開始位置。要匹配 字符本身,請使

3、用 ,匹配輸入字符串的結(jié)尾位置。要匹配 “$” 字符本身,請使用 “$”,( ),標記一個子表達式的開始和結(jié)束位置。要匹配小括號,請使用 ( 和 ), ,用來自定義能夠匹配 多種字符 的表達式。要匹配中括號,請使用 和 , ,修飾匹配次數(shù)的符號。要匹配大括號,請使用 和 ,.,匹配除了換行符(n)以外的任意一個字符。要匹配小數(shù)點本身,請使用 .,?,修飾匹配次數(shù)為 0 次或 1 次。要匹配 ? 字符本身,請使用 ?,+,修飾匹配次數(shù)為至少 1 次。要匹配 + 字符本身,請使用 +,*,修飾匹配次數(shù)為 0 次或任意次。要匹配 * 字符本身,請使用*,|,左右兩邊表達式之間 或 關系。匹配 | 本

4、身,請使用 |,說明,字符集合,.,w,小數(shù)點可以匹配除了換行符(n)以外的任意一個字符,可以匹配任何一個字母或者數(shù)字或者下劃線,單獨字符 a-zA-Z_0-9,W,W大寫,可以匹配任何一個字母或者數(shù)字或者下劃線以外的字符,非單獨字符 a-zA-Z_0-9,s,可以匹配空格、制表符、換頁符等空白字符的其中任意一個,空白符號 tnx0Bfr,S,S大寫,可以匹配任何一個空白字符以外的字符,非空白符號tnx0Bfr,d,可以匹配任何一個 09 數(shù)字字符,數(shù)字 等價于0-9,D,D大寫,可以匹配任何一個非數(shù)字字符,非數(shù)字 等價于0-9,字符集合 可以匹配 “多個字符” 其中任意一個字符的正則表達式。

5、雖然是 “多個字符”,但每次只能匹配其中一個。DEELX 正則表達式中標準的字符集合有:,說明,限定符,n,m, n,表達式固定重復n次,比如:w2 相當于 ww,表達式盡可能重復n次,至少重復m次:ba1,3可以匹配 ba或baa或baaa,m, ,表達式盡可能的多匹配,至少重復m次:“wd2,”可以匹配a12,x456.,?,表達式盡可能匹配1次,也可以不匹配,相當于 0, 1,+,表達式盡可能的多匹配,至少匹配1次,相當于 1, ,*,表達式盡可能的多匹配,最少可以不匹配,相當于 0, ,匹配次數(shù)限定符 使被修飾的表達式可多次重復匹配的修飾符??墒贡恍揎椀谋磉_式重復固定次數(shù),也可以限定一

6、定的重復匹配的次數(shù)范圍。在限定符之后的表達式能夠匹配成功的情況下,不定次數(shù)的限定符總是盡可能的多匹配。如果之后的表達式匹配失敗,限定符可適當“讓出”能夠匹配的字符,以使整個表達式匹配成功。這種模式就叫“貪婪模式”。,說明,限定符,m, n?,m, ?,表達式盡量只匹配m次,最多重復n次。,表達式盡量只匹配m次,最多可以匹配任意次。,?,表達式盡量不匹配,最多匹配1次,相當于 0, 1?,+?,表達式盡量只匹配1次,最多可匹配任意次,相當于 1, ?,*?,表達式盡量不匹配,最多可匹配任意次,相當于 0, ?,“勉強模式”限定符: 在限定符之后添加問號(?),則使限定符成為“勉強模式”。勉強模式

7、的限定符,總是盡可能少的匹配。如果之后的表達式匹配失敗,勉強模式也可以盡可能少的再匹配一些,以使整個表達式匹配成功。,說明,限定符,m, n+,m, +,表達式盡可能重復n次,至少重復m次。,表達式盡可能的多匹配,至少重復m次。,?+,表達式盡可能匹配1次,也可以不匹配,相當于 0, 1+,+,表達式盡可能的多匹配,至少匹配1次,相當于 1, +,*+,表達式盡可能的多匹配,最少可以不匹配,相當于 0, +,“占有模式”限定符: 在限定符之后添加加號(+),則使限定符成為“占有模式”。占有模式的限定符,總是盡可能多的匹配。與“貪婪模式”不同的是,即使之后的表達式匹配失敗,“占有模式”也不會“讓

8、出”自己能夠匹配的字符。,轉(zhuǎn)義字符 Q.E 使用 Q 開始,E 結(jié)束,可使中間的標點符號失去特殊意義,將中間的字符作為普通字符。 例如: Q(a+b)*3E 可匹配文本 “(a+b)*3”。,因為正則表達式是一個很龐雜的體系,所以我僅例舉些入門的概念,更多的請參閱相關書籍及自行摸索。,b 一個單詞的邊界B 一個非單詞的邊界G 前一個匹配的結(jié)束 為限制開頭java 條件限制為以Java為開頭字符$為限制結(jié)尾java$ 條件限制為以java為結(jié)尾字符. 條件限制除n以外任意一個單獨字符java. 條件限制為java后除換行外任意兩個字符 加入特定限制條件a-z 條件限制在小寫a to z范圍中一個

9、字符A-Z 條件限制在大寫A to Z范圍中一個字符a-zA-Z 條件限制在小寫a to z或大寫A to Z范圍中一個字符,0-9 條件限制在小寫0 to 9范圍中一個字符0-9a-z 條件限制在小寫0 to 9或a to z范圍中一個字符0-9a-z 條件限制在小寫0 to 9或a to z范圍中一個字符(交集) 中加入后加再次限制條件a-z 條件限制在非小寫a to z范圍中一個字符A-Z 條件限制在非大寫A to Z范圍中一個字符a-zA-Z 條件限制在非小寫a to z或大寫A to Z范圍中一個字符0-9 條件限制在非小寫0 to 9范圍中一個字符0-9a-z 條件限制在非小寫0

10、to 9或a to z范圍中一個字符0-9a-z 條件限制在非小寫0 to 9或a to z范圍中一個字符(交集)在 限制條件為特定字符出現(xiàn)0次以上時,可以使用*J* 0個以上J.* 0個以上任意字符,J.*D J與D之間0個以上任意字符 在限制條件為特定字符出現(xiàn)1次以上時,可以使用+J+ 1個以上J.+ 1個以上任意字符J.+D J與D之間1個以上任意字符 在限制條件為特定字符出現(xiàn)有0或1次以上時,可以使用?JA? J或者JA出現(xiàn) 限制為連續(xù)出現(xiàn)指定次數(shù)字符aJ2 JJJ3 JJJ 文字a個以上,并且a,J3, JJJ,JJJJ,JJJJJ,?(3次以上J并存),文字個以上,b個以下a,bJ

11、3,5 JJJ或JJJJ或JJJJJ兩者取一|J|A J或AJava|Hello Java或Hello ()中規(guī)定一個組合類型比如,我查詢index中間的數(shù)據(jù),可寫作+href=?(*)?*(.+?)在使用Ppile函數(shù)時,可以加入控制正則表達式的匹配行為的參數(shù):Pattern Ppile(String regex, int flag),flag的取值范圍如下: Pattern.CANON_EQ 當且僅當兩個字符的正規(guī)分解(canonical decomposition)都完全相同的情況下,才認定匹配。比如用了這個標志之后,表達式au030A會匹配?。默認情況下,不考慮規(guī) 范相等性(canon

12、ical equivalence)。 Pattern.CASE_INSENSITIVE(?i) 默認情況下,大小寫不明感的匹配只適用于US-ASCII字符集。這個標志能讓表達式忽略大小寫進行匹配。要想對Unicode字符進行大小不明感的匹 配,只要將UNICODE_CASE與這個標志合起來就行了。 Pattern.COMMENTS(?x) 在這種模式下,匹配時會忽略(正則表達式里的)空格字符,(譯者注:不是指表達式里的s,而是指表達式里的空格,tab,回車之類)。注釋從#開始,一直到這行結(jié)束。可以通過嵌入式的標志來啟用Unix行模式。 Pattern.DOTALL(?s) 在這種模式下,表達式

13、.可以匹配任意字符,包括表示一行的結(jié)束符。默認情況下,表達式.不匹配行的結(jié)束符。Pattern.MULTILINE (?m) 在這種模式下,和$分別匹配一行的開始和結(jié)束。此外,仍然匹配字符串的開始,$也匹配字符串的結(jié)束。默認情況下,這兩個表達式僅僅匹配字符串的開始和結(jié)束。Pattern.UNICODE_CASE (?u) 在這個模式下,如果你還啟用了CASE_INSENSITIVE,2020年7月31日星期五12時28分45秒,標志,那么它會對Unicode字符進行大小寫不明感的匹配。默認情況下,大小寫不敏感的匹配只適用于US-ASCII字符集。 Pattern.UNIX_LINES(?d)

14、在這個模式下,只有n才被認作一行的中止,并且與.,以及$進行匹配。 拋開空泛的概念,下面寫出幾個簡單的Java正則用例:比如,在字符串包含驗證時/查找以Java開頭,任意結(jié)尾的字符串Pattern pattern = Ppile(Java.*);Matcher matcher = pattern.matcher(Java不是人);boolean b= matcher.matches(); /當條件滿足時,將返回true,否則返回falseSystem.out.println(b);,以多條件分割字符串時Pattern pattern = Ppile(, |+);String strs = pa

15、ttern.split(Java Hello World Java,Hello,World|Sun);for (int i=0;istrs.length;i+) System.out.println(strsi); 文字替換(首次出現(xiàn)字符)Pattern pattern = Ppile(正則表達式);Matcher matcher = pattern.matcher(正則表達式 Hello World,正則表達式 Hello World);/替換第一個符合正則的數(shù)據(jù)System.out.println(matcher.replaceFirst(Java);,文字替換(全部)Pattern pa

16、ttern = Ppile(正則表達式);Matcher matcher = pattern.matcher(正則表達式 Hello World,正則表達式 Hello World);/替換第一個符合正則的數(shù)據(jù)System.out.println(matcher.replaceAll(Java); 文字替換(置換字符)Pattern pattern = Ppile(“正則表達式”);Matcher matcher = pattern.matcher(“正則表達式 Hello World,正則表達式 Hello World ”);StringBuffer sbr = new StringBuff

17、er();while (matcher.find() matcher.appendReplacement(sbr, “Java”);,matcher.appendTail(sbr);System.out.println(sbr.toString(); 驗證是否為郵箱地址String email=“w.-+(w-+.)+w-+”;String str=”;Pattern pattern = Ppile(email,Pattern.CASE_INSENSITIVE);Matcher matcher = pattern.matcher(str);System.out.println(matcher.

18、matches(); 比較嚴格的: email=(0-9a-zA-Z(-.w*0-9a-zA-Z)*(0-9a-zA-Z)+(-w*0-9a-zA-Z)*.)+a-zA-Z2,9)$ 去除html標記 Pattern pattern = Ppile(, Pattern.DOTALL);,Matcher matcher = pattern.matcher(主頁);String string = matcher.replaceAll();System.out.println(string); 查找html中對應條件字符串Pattern pattern = Ppile(href=(.+?);Matc

19、her matcher = pattern.matcher(主頁);if(matcher.find()System.out.println(matcher.group(1); 截取http:/地址/截取urlPattern pattern = Ppile(http:/|https:/)1w.-/:+);,Matcher matcher = pattern.matcher(dsdsdsfdf); StringBuffer buffer = new StringBuffer();while(matcher.find() buffer.append(matcher.group(); buffer.a

20、ppend(rn); System.out.println(buffer.toString(); 替換指定中文字String str = Java目前的發(fā)展史是由0年-1年;String object=new String0,1995,new String1,2007;,System.out.println(replace(str,object); public static String replace(final String sourceString,Object object) String temp=sourceString; for(int i=0;iobject.length;i

21、+) String result=(String)objecti; Pattern pattern = Ppile(result0); Matcher matcher = pattern.matcher(temp); temp=matcher.replaceAll(result1); return temp;,讀取頁面鏈接和內(nèi)容: public String newsListRegExp = +href=?( *)?*(.+?) ; newsListRegExp =+hrefs*=*s*(s|+)*(; public void getLinks(String content) java.uti

22、l.regex.Pattern pattern=java.util.regex.Ppile(newsListRegExp, java.util.regex.Pattern.CASE_INSENSITIVE); java.util.regex.Matcher matcher=pattern.matcher(content); while(matcher.find() String link=matcher.group(1); String text=matcher.group(2); System.out.println(link+text); ,Java正則的功用還有很多,事實上只要是字符處理

23、,就沒有正則做不到的事情存在。 (當然,正則解釋時較耗時間就是了?。?二、 HTMLParser使用詳解,HTMLParser使用詳解(1)- 初始化Parser,在研究搜索引擎的開發(fā)中,對于HTML網(wǎng)頁的處理是核心的一個環(huán)節(jié)。網(wǎng)上有很多開源的代碼,對于Java來說,HTMLParser是比較著名并且得到廣泛應用的一個。 HTMLParser的主頁是 ,最后的更新是2006年9月的1.6版。不過沒關系,HTML的內(nèi)容已經(jīng)很久沒有大的變化了,HTMLParser處理起來基本沒有任何問題。,HTMLParser的核心模塊是org.htmlparser.Parser類,這個類實際完成了對于HTML頁

24、面的分析工作。這個類有下面幾個構(gòu)造函 數(shù): public Parser ();public Parser (Lexer lexer, ParserFeedback fb); public Parser (URLConnection connection, ParserFeedback fb) throws ParserException; public Parser (String resource, ParserFeedback feedback) throws ParserException; public Parser (String resource) throws ParserExc

25、eption;public Parser (Lexer lexer);public Parser (URLConnection connection) throws ParserException;和一個靜態(tài)類 public static Parser createParser (String html, String charset);,對于大多數(shù)使用者來說,使用最多的是通過一個URLConnection或者一個保存有網(wǎng)頁內(nèi)容的字符串來初始化Parser,或者使用靜態(tài)函數(shù)來生成一個Parser對象。 ParserFeedback的代碼很簡單,是針對調(diào)試和跟蹤分析過程的,一般不需要改變。而使用

26、Lexer則是一個相對比較高級的話題,放到以后再討論吧。 這里比較有趣的一點是,如果需要設置頁面的編碼方式的話,不使用Lexer就只有靜態(tài)函數(shù)一個方法了。 對于大多數(shù)中文頁面來說,好像這是應該用得比較多的一個方法。,HTMLParser使用詳解(2)- Node內(nèi)容,HTMLParser將解析過的信息保存為一個樹的結(jié)構(gòu)。Node是信息保存的數(shù)據(jù)類型基礎。 請看Node的定義:public interface Node extends Cloneable; Node中包含的方法有幾類: 對于樹型結(jié)構(gòu)進行遍歷的函數(shù),這些函數(shù)最容易理解: Node getParent ():取得父節(jié)點NodeLis

27、t getChildren ():取得子節(jié)點的列表,Node getFirstChild ():取得第一個子節(jié)點Node getLastChild ():取得最后一個子節(jié)點 Node getPreviousSibling ():取得前一個兄弟(不好意思,英文是兄弟姐妹,直譯太麻煩而且不符合習慣,對不起女同胞了)Node getNextSibling ():取得下一個兄弟節(jié)點 取得Node內(nèi)容的函數(shù): String getText ():取得文本String toPlainTextString():取得純文本信息。 String toHtml () :取得HTML信息(原始HTML)String

28、 toHtml (boolean verbatim):取得HTML信息(原始HTML)String toString ():取得字符串信息(原始HTML)Page getPage ():取得這個Node對應的Page對象,int getStartPosition ():取得這個Node在HTML頁面中的起始位置int getEndPosition ():取得這個Node在HTML頁面中的結(jié)束位置用于Filter過濾的函數(shù): void collectInto (NodeList list, NodeFilter filter):基于filter的條件對于這個節(jié)點進行過濾,符合條件的節(jié)點放到lis

29、t中。 用于Visitor遍歷的函數(shù): void accept (NodeVisitor visitor):對這個Node應用visitor用于修改內(nèi)容的函數(shù),這類用得比較少: void setPage (Page page):設置這個Node對應的Page對象void setText (String text):設置文本void setChildren (NodeList children):設置子節(jié)點列表,其他函數(shù): void doSemanticAction ():執(zhí)行這個Node對應的操作(只有少數(shù)Tag有對應的操作)Object clone ():接口Clone的抽象函數(shù)。 主要注意

30、一下,getText,toPlainTextString ,toHtml 區(qū)別 String a=貓撲hi來點不一樣 ; Parser p=Parser.createParser(a, UTF-8); try for(NodeIterator it= p.elements();it.hasMoreNodes();) Node node=it.nextNode() ; System.out.println(node.getText()+$+node.toPlainTextString()+$+node.toHtml(); catch (ParserException e) / TODO Auto

31、-generated catch block e.printStackTrace(); 輸出: div id=hi$貓撲hi$貓撲hi a class=link href= $來點不一樣$來點不一樣,下面是用于測試的HTML文件: 白澤居- 白澤居-白澤居- 白澤居-,toPlainTextString是把用戶可以看到的內(nèi)容都包含了。有趣的有兩點,一是標簽中的Title內(nèi)容是在plainText中的,可能在標題中可見的也算可見吧。 另外就是象前面說的,HTML內(nèi)容中的換行符什么的,也都成了plainText,這個邏輯上好像有點問題。另外可能大家發(fā)現(xiàn)toHtml,toHtml(true)和toH

32、tml(false)的結(jié)果沒什么區(qū)別。實際也是這樣的,如果,跟蹤HTMLParser的代碼就可以發(fā)現(xiàn),Node的子類是AbstractNode,其中實現(xiàn)了toHtml()的代碼,直接調(diào)用toHtml(false),而AbstractNode的三個子類RemarkNode,TagNode和TextNode中,toHtml(boolean verbatim)的實現(xiàn)中,都沒有處理verbatim參數(shù),所以三個函數(shù)的結(jié)果是一模一樣的。 如果你不需要實現(xiàn)你自己的什么特殊處理,簡單使用toHtml就可以了。,HTML的Node類繼承關系如下圖這個是從別的文章Copy的):,AbstractNodes是No

33、de的直接子類,也是一個抽象類。它的三個直接子類實現(xiàn)是RemarkNode,用于保存注釋。在輸出結(jié)果的toString部分中可以看到有一個Rem (3456,2,3566,13): 這是注釋,就是一個RemarkNode。TextNode也很簡單,就是用戶可見的文字信息。 TagNode是最復雜的,包含了HTML語言中的所有標簽,而且可以擴展(擴展 HTMLParser 對自定義標簽的處理能力 )。TagNode包含兩類,一類是簡單的Tag,實際就是不能包含其他Tag的標簽,只能做葉子節(jié)點。另一類是CompositeTag,就是可以包含其他Tag,是分支節(jié)點。,遍歷了網(wǎng)頁的內(nèi)容以后,以樹(森林

34、)結(jié)構(gòu)保存了結(jié)果。HTMLParser訪問結(jié)果內(nèi)容的方法有兩種。使用Filter和使用Visitor。 (一)Filter類 顧名思義,F(xiàn)ilter就是對于結(jié)果進行過濾,取得需要的內(nèi)容。HTMLParser在org.htmlparser.filters包之內(nèi)一共定義了16個不同的Filter,也可以分為幾類。,HTMLParser使用詳解(3)- 通過Filter訪問內(nèi)容,判斷類Filter: TagNameFilterHasAttributeFilterHasChildFilterHasParentFilterHasSiblingFilterIsEqualFilter 邏輯運算Filter:

35、 AndFilterNotFilterOrFilterXorFilter,其他Filter: NodeClassFilterStringFilterLinkStringFilterLinkRegexFilterRegexFilterCssSelectorNodeFilter 所有的Filter類都實現(xiàn)了org.htmlparser.NodeFilter接口。這個接口只有一個主要函數(shù):boolean accept (Node node); 各個子類分別實現(xiàn)這個函數(shù),用于判斷輸入的Node是否符合這個Filter的過濾條件,如果符合,返回true,否則返回false。,(二)判斷類Filter H

36、TMLParser使用入門(2)- Node內(nèi)容 ,自己添加import部分)public static void main(String args) try Parser parser = new Parser( (HttpURLConnection) (new URL(:8080/HTMLParserTester.html).openConnection() ); / 這里是控制測試的部分,后面的例子修改的就是這個地方。 NodeFilter filter = new TagNameFilter (DIV); NodeList nodes = parser.e

37、xtractAllNodesThatMatch(filter);,if(nodes!=null) for (int i = 0; i nodes.size(); i+) Node textnode = (Node) nodes.elementAt(i); message(getText:+textnode.getText(); message(=); catch( Exception e ) e.printStackTrace(); 輸出結(jié)果:getText:div id=top_main,=getText:div id=logoindex=可以看出文件中兩個Div節(jié)點都被取出了。下面可以針對

38、這兩個DIV節(jié)點進行操作 2.2 HasChildFilter 下面讓我們看看HasChildFilter。剛剛看到這個Filter的時候,我想當然地認為這個Filter返回的是有Child的Tag。直接初始化了一個NodeFilter filter = new HasChildFilter();,結(jié)果調(diào)用NodeList nodes = parser.extractAllNodesThatMatch(filter);的時候HasChildFilter內(nèi)部直接發(fā)生NullPointerException。讀了一下HasChildFilter的代碼,才發(fā)現(xiàn),實際HasChildFilter是返回

39、有符合條件的子節(jié)點的節(jié)點,需要另外一個Filter作為過濾子節(jié)點的參數(shù)。 缺省的構(gòu)造函數(shù)雖然可以初始化,但是由于子節(jié)點的Filter是null,所以使用的時候發(fā)生了Exception。 從這點來看,HTMLParser的代碼還有很多可以優(yōu)化的的地方。呵呵。,修改代碼: NodeFilter innerFilter = new TagNameFilter (DIV);NodeFilter filter = new HasChildFilter(innerFilter);NodeList nodes = parser.extractAllNodesThatMatch(filter);輸出結(jié)果: g

40、etText:body = getText:div id=top_main= 可以看到,輸出的是兩個有DIV子Tag的Tag節(jié)點。(body有子節(jié)點DIV top_main,top_main有子節(jié)點logoindex。,注意HasChildFilter還有一個構(gòu)造函數(shù):public HasChildFilter (NodeFilter filter, boolean recursive) 如果recursive是false,則只對第一級子節(jié)點進行過濾。比如前面的例子,body和top_main都是在第一級的子節(jié)點里就有DIV節(jié)點,所以匹配上了。如果我們用下面的方法調(diào)用:NodeFilter f

41、ilter = new HasChildFilter( innerFilter, true ); 輸出結(jié)果: getText:html xmlns=/1999/xhtml=getText:body = getText:div id=top_main=,可以看到輸出結(jié)果中多了一個html xmlns=/1999/xhtml,這個是整個HTML頁面的節(jié)點(根節(jié)點),雖然這個節(jié)點下直接沒有DIV節(jié)點,但是它的子節(jié)點body下面有DIV節(jié)點,所以它也被匹配上了。 2.3 HasAttributeFilter HasAttributeFil

42、ter有3個構(gòu)造函數(shù):public HasAttributeFilter ();public HasAttributeFilter (String attribute);public HasAttributeFilter (String attribute, String value);這個Filter可以匹配出包含制定名字的屬性,或者制定屬性為指定值的節(jié)點。還是用例子說明比較容易。,調(diào)用方法1: NodeFilter filter = new HasAttributeFilter();NodeList nodes = parser.extractAllNodesThatMatch(filte

43、r); 輸出結(jié)果: 什么也沒有輸出。調(diào)用方法2: NodeFilter filter = new HasAttributeFilter( id );NodeList nodes = parser.extractAllNodesThatMatch(filter);,輸出結(jié)果: getText:div id=top_main=getText:div id=logoindex= 調(diào)用方法3: NodeFilter filter = new HasAttributeFilter( id, logoindex );NodeList nodes = parser.extractAllNodesThatMa

44、tch(filter);輸出結(jié)果: getText:div id=logoindex= 很簡單吧。呵呵,2.4 其他判斷列Filter HasParentFilter和HasSiblingFilter的功能與HasChildFilter類似,大家自己試一下就應該了解了。IsEqualFilter的構(gòu)造函數(shù)參數(shù)是一個Node:public IsEqualFilter (Node node) mNode = node; accept函數(shù)也很簡單:public boolean accept (Node node) return (mNode = node);不需要過多說明了。,(三)邏輯運算Filt

45、er (四)其他Filter: HTMLParser使用入門(2)- Node內(nèi)容 中我們已經(jīng)了解了Node的不同類型,這個Filter就可以針對類型進行過濾。測試代碼: NodeFilter filter = new NodeClassFilter(RemarkNode.class); NodeList nodes = parser.extractAllNodesThatMatch(filter); 輸出結(jié)果: getText:這是注釋= 可以看到只有RemarkNode(注釋)被輸出了。,4.2 StringFilter 這個Filter用于過濾顯示字符串中包含制定內(nèi)容的Tag。注意是可顯

46、示的字符串,不可顯示的字符串中的內(nèi)容(例如注釋,鏈接等等)不會被顯示。 修改一下例子代碼: 白澤居-title-, 白澤居-字符串1- 白澤居-鏈接文本- 白澤居-字符串2-,測試代碼: NodeFilter filter = new StringFilter(); NodeList nodes = parser.extractAllNodesThatMatch(filter); 輸出結(jié)果: getText:白澤居-title-= getText: 白澤居-字符串1-=getText:白澤居-鏈接文本-=,getText: 白澤居-字符串2-= 可以看到包含title,兩個內(nèi)容字符串和鏈接的文

47、本字符串的Tag都被輸出了,但是注釋和鏈接Tag本身沒有輸出。 4.3 LinkStringFilter 這個Filter用于判斷鏈接中是否包含某個特定的字符串,可以用來過濾出指向某個特定網(wǎng)站的鏈接。測試代碼: NodeFilter filter = new LinkStringFilter(); NodeList nodes = parser.extractAllNodesThatMatch(filter);,輸出結(jié)果: getText:a href= 4.4 其他幾個Filter 其他幾個Filter也是根據(jù)字符串對不同的域進行判斷,與前面這些的區(qū)別主要就是支持正則表達式。這個不在本文的討

48、論范圍以內(nèi),大家可以自己實驗一下。 前面介紹的都是簡單的Filter,只能針對某種單一類型的條件進行過濾。HTMLParser支持對于簡單類型的Filter進行組合,從而實現(xiàn)復雜的條件。原理和一般編程語言的邏輯運算是一樣的。,3.1 AndFilter AndFilter可以把兩種Filter進行組合,只有同時滿足條件的Node才會被過濾。 測試代碼: NodeFilter filterID = new HasAttributeFilter( “id” );NodeFilter filterChild = new HasChildFilter(filterA);NodeFilter filte

49、r = new AndFilter(filterID, filterChild);輸出結(jié)果:getText:div id=“l(fā)ogoindex”=,3.2 OrFilter 把前面的AndFilter換成OrFilter測試代碼: NodeFilter filterID = new HasAttributeFilter( id );NodeFilter filterChild = new HasChildFilter(filterA);NodeFilter filter = new OrFilter(filterID, filterChild); 輸出結(jié)果: getText:div id=to

50、p_main= getText:div id=logoindex=,3.3 NotFilter 把前面的AndFilter換成NotFilter測試代碼: NodeFilter filterID = new HasAttributeFilter( id );NodeFilter filterChild = new HasChildFilter(filterA);NodeFilter filter = new NotFilter(new OrFilter(filterID, filterChild); 輸出結(jié)果: getText:!DOCTYPE html PUBLIC -/W3C/DTD XH

51、TML 1.0 Transitional/EN /TR/xhtml1/DTD/xhtml1-transitional.dtd=getText:,=getText:head=getText:meta http-equiv=Content-Type content=text/html; charset=gb2312=getText:title =getText:白澤居-=getText:/title= getText:/head,=getText:=getText:html xmlns=/1999/xhtml=getText: =ge

52、tText:body =getText:=getText:,=getText: = getText:這是注釋= getText: 白澤居- =getText:a href=getText:白澤居-=getText:/a,=getText: =getText:/div=getText: 白澤居- = getText:/div= getText:,= getText:/body= getText: =getText:/html=getText:=除了前面3.2中輸出的幾個Tag,其余的Tag都在這里了。,3.4 XorFilter 把前面的AndFilter換成NotFilter測試代碼: Nod

53、eFilter filterID = new HasAttributeFilter( id );NodeFilter filterChild = new HasChildFilter(filterA);NodeFilter filter = new XorFilter(filterID, filterChild); 輸出結(jié)果: getText:div id=top_main= 4.1 NodeClassFilter 這個Filter用于判斷節(jié)點類型是否是某個特定的Node類型。在,2.1 TagNameFilter TabNameFilter是最容易理解的一個Filter,根據(jù)Tag的名字進行

54、過濾。 下面是用于測試的HTML文件: 白澤居-, 白澤居-白澤居- 白澤居- ,HTMLParser遍歷了網(wǎng)頁的內(nèi)容以后,以樹(森林)結(jié)構(gòu)保存了結(jié)果。HTMLParser訪問結(jié)果內(nèi)容的方法有兩種。 使用Filter和使用Visitor。 下面介紹使用Visitor訪問內(nèi)容的方法。 4.1 NodeVisitor 從簡單方面的理解,F(xiàn)ilter是根據(jù)某種條件過濾取出需要的Node再進行處理。Visitor則是遍歷,HTMLParser使用詳解(4)- 通過Visitor訪問,內(nèi)容樹的每一個節(jié)點,對于符合條件的節(jié)點進行處理。實際的結(jié)果異曲同工,兩種不同的方法可以達到相同的結(jié)果。下面是一個最常見的NodeVisitro的例子。 測試代碼: public static void main(String args) try Parser parser = new Parser( (HttpURLConnection) (new URL(:8080/HTMLParserTester.html).openConnection() );,NodeVisitor visitor = new NodeVisitor( false, false ) public void visitTag(Tag tag) message(This is Tag:+ta

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論