HtmlParser基礎教程 分類: C_OHTERS 2014-05-22 11:33 1649人閱讀 評論(1) 收藏


一、相關資料html

官方文檔:http://htmlparser.sourceforge.net/samples.htmljava

API:http://htmlparser.sourceforge.net/javadoc/index.htmlnode

其它HTML 解釋器:jsoup等。因爲HtmlParser自2006年之後就再沒更新,目前不少人推薦使用jsoup代替它。api


二、使用HtmlPaser的關鍵步驟ide

(1)經過Parser類建立一個解釋器函數

(2)建立Filter或者Visitor工具

(3)使用parser根據filter或者visitor來取得全部符合條件的節點測試

(4)對節點內容進行處理ui


三、使用Parser的構造函數建立解釋器編碼

Parser() 
          Zero argument constructor.
Parser(Lexer lexer) 
          Construct a parser using the provided lexer.
Parser(Lexer lexer, ParserFeedback fb) 
          Construct a parser using the provided lexer and feedback object.
Parser(String resource) 
          Creates a Parser object with the location of the resource (URL or file).
Parser(String resource, ParserFeedback feedback) 
          Creates a Parser object with the location of the resource (URL or file) You would typically create a DefaultHTMLParserFeedback object and pass it in.
Parser(URLConnection connection) 
          Construct a parser using the provided URLConnection.
Parser(URLConnection connection, ParserFeedback fb) 
          Constructor for custom HTTP access.
        對於大多數使用者來講,使用最多的是經過一個 URLConnection 或者一個保存有網頁內容的字符串來初始化Parser,或者使用靜態函數來生成一個Parser對象。 ParserFeedback 的代碼很簡單,是針對調試和跟蹤分析過程的,通常不須要改變。而使用 Lexer 則是一個相對比較高級的話題,放到之後再討論吧。
        這裏比較有趣的一點是,若是須要設置頁面的編碼方式的話,不使用Lexer就只有靜態函數一個方法了。對於大多數中文頁面來講,好像這是應該用得比較多的一個方法。


四、HtmlPaser使用Node對象保存各節點信息


(1)訪問各個節點的方法
Node getParent ():取得父節點
NodeList getChildren ():取得子節點的列表
Node getFirstChild ():取得第一個子節點
Node getLastChild ():取得最後一個子節點
Node getPreviousSibling ():取得前一個兄弟(很差意思,英文是兄弟姐妹,直譯太麻煩並且不符合習慣,對不起女同胞了)
Node getNextSibling ():取得下一個兄弟節點
(2)取得Node內容的函數
String getText ():取得文本
String toPlainTextString():取得純文本信息。
String toHtml () :取得HTML信息(原始HTML
String toHtml (boolean verbatim):取得HTML信息(原始HTML
String toString ():取得字符串信息(原始HTML
Page getPage ():取得這個Node對應的Page對象
int getStartPosition ():取得這個NodeHTML頁面中的起始位置
int getEndPosition ():取得這個NodeHTML頁面中的結束位置


五、使用Filter訪問Node節點及其內容

(1)Filter的種類

顧名思義,Filter就是對於結果進行過濾,取得須要的內容。

全部的Filter均實現了NodeFilter接口,此接口只有一個方法Boolean accept(Node node),用於肯定某個節點是否屬於此Filter過濾的範圍。

HTMLParser在org.htmlparser.filters包以內一共定義了16個不一樣的Filter,也能夠分爲幾類。
判斷類Filter
TagNameFilter
HasAttributeFilter

HasChildFilter
HasParentFilter
HasSiblingFilter
IsEqualFilter
邏輯運算Filter
AndFilter
NotFilter

OrFilter
XorFilter
其餘Filter
NodeClassFilter
StringFilter

LinkStringFilter
LinkRegexFilter
RegexFilter
CssSelectorNodeFilter

除此之外,能夠自定義一些Filter,用於完成特殊需求的過濾。
(2)Filter的使用示例

如下示例用於提取HTML文件中的連接

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. package org.ljh.search.html;  
  2.   
  3. import java.util.HashSet;  
  4. import java.util.Set;  
  5.   
  6. import org.htmlparser.Node;  
  7. import org.htmlparser.NodeFilter;  
  8. import org.htmlparser.Parser;  
  9. import org.htmlparser.filters.NodeClassFilter;  
  10. import org.htmlparser.filters.OrFilter;  
  11. import org.htmlparser.tags.LinkTag;  
  12. import org.htmlparser.util.NodeList;  
  13. import org.htmlparser.util.ParserException;  
  14.   
  15. //本類建立用於HTML文件解釋工具  
  16. public class HtmlParserTool {  
  17.   
  18.     // 本方法用於提取某個html文檔中內嵌的連接  
  19.     public static Set<String> extractLinks(String url, LinkFilter filter) {  
  20.         Set<String> links = new HashSet<String>();  
  21.         try {  
  22.             // 一、構造一個Parser,並設置相關的屬性  
  23.             Parser parser = new Parser(url);  
  24.             parser.setEncoding("gb2312");  
  25.   
  26.             // 2.一、自定義一個Filter,用於過濾<Frame >標籤,而後取得標籤中的src屬性值  
  27.             NodeFilter frameNodeFilter = new NodeFilter() {  
  28.                 @Override  
  29.                 public boolean accept(Node node) {  
  30.                     if (node.getText().startsWith("frame src=")) {  
  31.                         return true;  
  32.                     } else {  
  33.                         return false;  
  34.                     }  
  35.                 }  
  36.             };  
  37.               
  38.             //2.二、建立第二個Filter,過濾<a>標籤  
  39.             NodeFilter aNodeFilter = new NodeClassFilter(LinkTag.class);  
  40.               
  41.             //2.三、淨土上述2個Filter造成一個組合邏輯Filter。  
  42.             OrFilter linkFilter = new OrFilter(frameNodeFilter, aNodeFilter);  
  43.               
  44.             //三、使用parser根據filter來取得全部符合條件的節點  
  45.             NodeList nodeList = parser.extractAllNodesThatMatch(linkFilter);  
  46.               
  47.             //四、對取得的Node進行處理  
  48.             for(int i = 0; i<nodeList.size();i++){  
  49.                 Node node = nodeList.elementAt(i);  
  50.                 String linkURL = "";  
  51.                 //若是連接類型爲<a />  
  52.                 if(node instanceof LinkTag){  
  53.                     LinkTag link = (LinkTag)node;  
  54.                     linkURL= link.getLink();  
  55.                 }else{  
  56.                     //若是類型爲<frame />  
  57.                     String nodeText = node.getText();  
  58.                     int beginPosition = nodeText.indexOf("src=");  
  59.                     nodeText = nodeText.substring(beginPosition);  
  60.                     int endPosition = nodeText.indexOf(" ");  
  61.                     if(endPosition == -1){  
  62.                         endPosition = nodeText.indexOf(">");  
  63.                     }  
  64.                     linkURL = nodeText.substring(5, endPosition - 1);  
  65.                 }  
  66.                 //判斷是否屬於本次搜索範圍的url  
  67.                 if(filter.accept(linkURL)){  
  68.                     links.add(linkURL);  
  69.                 }  
  70.             }  
  71.               
  72.         } catch (ParserException e) {  
  73.             e.printStackTrace();  
  74.         }  
  75.         return links;  
  76.     }  
  77. }  

程序中的一些說明:

(1)經過Node#getText()取得節點的String。

(2)node instanceof TagLink,即<a/>節點,其它還有不少的相似節點,如tableTag等,基本上每一個常見的html標籤均會對應一個tag。官方文檔說明以下:

org.htmlparser.nodes The nodes package has the concrete node implementations.
org.htmlparser.tags The tags package contains specific tags.
所以能夠經過此方法直接判斷一個節點是否某個標籤內容。


其中用到的LinkFilter接口定義以下:

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. package org.ljh.search.html;  
  2.   
  3. //本接口所定義的過濾器,用於判斷url是否屬於本次搜索範圍。  
  4. public interface LinkFilter {  
  5.     public boolean accept(String url);  
  6. }  


測試程序以下:

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
  1. package org.ljh.search.html;  
  2.   
  3. import java.util.Iterator;  
  4. import java.util.Set;  
  5.   
  6. import org.junit.Test;  
  7.   
  8. public class HtmlParserToolTest {  
  9.   
  10.     @Test  
  11.     public void testExtractLinks() {  
  12.         String url = "http://www.baidu.com";  
  13.         LinkFilter linkFilter = new LinkFilter(){  
  14.             @Override  
  15.             public boolean accept(String url) {  
  16.                 if(url.contains("baidu")){  
  17.                     return true;  
  18.                 }else{  
  19.                     return false;  
  20.                 }  
  21.             }  
  22.               
  23.         };  
  24.         Set<String> urlSet = HtmlParserTool.extractLinks(url, linkFilter);  
  25.           
  26.         Iterator<String> it = urlSet.iterator();  
  27.         while(it.hasNext()){  
  28.             System.out.println(it.next());  
  29.         }  
  30.     }  
  31.   
  32. }  


輸出結果以下:

http://www.hao123.com http://www.baidu.com/ http://www.baidu.com/duty/ http://v.baidu.com/v?ct=301989888&rn=20&pn=0&db=0&s=25&word= http://music.baidu.com http://ir.baidu.com http://www.baidu.com/gaoji/preferences.html http://news.baidu.com http://map.baidu.com http://music.baidu.com/search?fr=ps&key= http://image.baidu.com http://zhidao.baidu.com http://image.baidu.com/i?tn=baiduimage&ct=201326592&lm=-1&cl=2&nc=1&word= http://www.baidu.com/more/ http://shouji.baidu.com/baidusearch/mobisearch.html?ref=pcjg&from=1000139w http://wenku.baidu.com http://news.baidu.com/ns?cl=2&rn=20&tn=news&word= https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F http://www.baidu.com/cache/sethelp/index.html http://zhidao.baidu.com/q?ct=17&pn=0&tn=ikaslist&rn=10&word=&fr=wwwt http://tieba.baidu.com/f?kw=&fr=wwwt http://home.baidu.com https://passport.baidu.com/v2/?reg&regType=1&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F http://v.baidu.com http://e.baidu.com/?refer=888 ; http://tieba.baidu.com http://baike.baidu.com http://wenku.baidu.com/search?word=&lm=0&od=0 http://top.baidu.com http://map.baidu.com/m?word=&fr=ps01000

相關文章
相關標籤/搜索