Java解析 HTML

一、垂直搜索介紹

1、垂直搜索--即需要抓去大量的網頁,分析其中的數據。垂直搜索更着重於正文內容模式分離,數據調整,相關鏈接分析,是一種結構化分析過程。

2、垂直搜索技術主要分爲兩個層次:模版級和網頁庫級

3、模版級是針對網頁進行模版設定或者自動生成模版的方式抽取數據,對網頁的採集也是針對性的採集,適合規模比較小、信息源少且穩定的需求,優點是快速實施、成本低、靈活性強,缺點是後期維護成本高,信息源和信息量小。

4、網頁庫級和模版方式最大的區別是對具體網頁不依賴,可針對任意正常的網頁信息採集信息抽取。缺點是其靈活性差、成本高。


垂直搜索大致需要以下技術:

1、信息採集技術

2、網頁信息抽取技術

3、信息的處理技術(重複識別、聚類、比較、分析等)

4、語意相關性分析

5、分詞

6、索引


二、使用HttpClient採集頁面

1、HTTPClient項目就是專門設計來簡化HTTP客戶端與服務器進行各種通訊編程。

2、HTTPClient是基於HttpCore實現的一個HTTP/1.1兼容HTTP客戶端,它提供了一系列可重用的客戶端身份驗證、HTTP狀態保持、HTTP鏈接管理module。功能豐富的HTTPClient同時兼具出色的可拓展性和健壯性,目前已經成爲了最爲流行的JavaHttp客戶端組件,爲開發Web瀏覽器、WebService客戶端提供了很大的便利。

下載地址: http://hc.apache.org/downloads.cgi

使用HttpClient

一般情況下,使用HttpClient需要以下5個步驟:

1、創建HttpClient的實例

2、創建某種連接方法的實例,在這裏是最常見的是Get和Post

3、調用第一步中創建好的HttpClient實例的execute方法,得到執行結果

4、釋放連接

5、對得到後的內容進行處理


下面來看兩個抓去網頁的實例

1、抓取搜索後的頁面然後保存

package com.qianyan.test;  
  
import java.io.BufferedReader;  
import java.io.File;  
import java.io.FileWriter;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.InputStreamReader;  
  
import org.apache.http.HttpEntity;  
import org.apache.http.HttpResponse;  
import org.apache.http.client.ClientProtocolException;  
import org.apache.http.client.HttpClient;  
import org.apache.http.client.methods.HttpGet;  
import org.apache.http.impl.client.DefaultHttpClient;  
  
public class TestHttpClient {  
  
    public static void main(String[] args) throws ClientProtocolException, IOException {  
        HttpClient httpClient = new DefaultHttpClient();  
        HttpGet httpGet = new HttpGet("http://www.baidu.com/s?wd=java");  
        HttpResponse response = httpClient.execute(httpGet);  
        HttpEntity entity = response.getEntity();  
  
        InputStream ins = entity.getContent();  
        BufferedReader reader = new BufferedReader(new InputStreamReader(ins));  
        FileWriter writer = new FileWriter(new File("E:/baidu.htm"));  
  
        String strLine = reader.readLine();  
        while (null != strLine) {  
            writer.write(strLine);  
            strLine = reader.readLine();  
        }  
        writer.close();  
        ins.close();  
        reader.close();  
        httpClient.getConnectionManager().shutdown();  
        System.out.println("網頁生成完畢!");  
    }  
}


1、抓取搜索後的頁面打印出來

package com.qianyan.test;  
  
import org.apache.http.HttpEntity;  
import org.apache.http.HttpResponse;  
import org.apache.http.client.HttpClient;  
import org.apache.http.client.methods.HttpGet;  
import org.apache.http.impl.client.DefaultHttpClient;  
import org.apache.http.util.EntityUtils;  
  
public class TestHttpClient2 {  
  
    public static void main(String[] args) {  
        HttpClient httpClient = new DefaultHttpClient();    
        try {    
                
            //創建HttpGet    
            HttpGet httpGet = new HttpGet("http://www.ifeng.com");    
            System.err.println("executing request " + httpGet.getURI());    
            //執行get請求    
            HttpResponse response = httpClient.execute(httpGet);    
            //獲取響應實體    
            HttpEntity entity = response.getEntity();    
            System.err.println("======================================================");    
            //打印響應狀態    
            System.out.println(response.getStatusLine());    
            if (entity != null) {    
                //打印響應內容的長度    
            
                System.out.println("Response content lenght:"    
                        + entity.getContentLength());    
                String content = EntityUtils.toString(entity);    
                    
                //解決HttpClient獲取中文亂碼 ,用String對象進行轉碼    
                System.out.println("Response content:"    
                        + new String(content.getBytes("ISO-8859-1"),"UTF-8"));    
            }    
            System.err.println("==========================================================");    
        } catch (Exception e) {    
            // TODO: handle exception    
        }finally{    
            //關閉連接,釋放資源    
            httpClient.getConnectionManager().shutdown();    
        }    
    }  
}  


三、使用JTidy

1、Tidy是W3C用來解析網頁的一個軟件包,可以方便地將HTML文檔轉化爲符合XML標準的文檔,由於XML可以方便地使用XSLT技術對內容進行抽取,所以使用Tidy配合XSLT可以方便地將各種網頁的內容抽取出來,保存成我們需要的格式。

2、通過JTidy可以方便地將標準的HTML網頁轉換爲XML的DOM對象,然後,通過XPath和XSTL將需要的內容抽取出來。

3、下載地址:http://sourceforge.net/projects/jtidy

4、JTidy的代碼實現iew plain

package com.qianyan.test;  
  
import java.io.File;  
import java.io.FileInputStream;  
import java.io.FileOutputStream;  
import java.io.InputStreamReader;  
  
import org.w3c.dom.Document;  
import org.w3c.tidy.Tidy;  
  
public class TestJTidy {  
  
    public static void main(String[] args) throws Exception {  
        FileInputStream fis = new FileInputStream(new File("E:/baidu.htm"));  
        InputStreamReader isr = new InputStreamReader(fis, "GBK");  
          
        FileOutputStream fos = new FileOutputStream(new File("E:/baidu.xml"));  
        Tidy tidy = new Tidy();  
        tidy.setXmlTags(true);  
        Document doc = tidy.parseDOM(isr, null);  
        tidy.pprint(doc, fos);  
        fos.close();  
        fis.close();  
        isr.close();  
    }  
} 



四、使用Nekohtml

1、Nekohtml是一個Java語言的HTML掃描器和標籤補全器(tag balancer),使得程序能解析HTML文檔並用標準的XML藉口來訪問其中的信息。這個解析器能夠掃描HTML文件並“修正”許多作者(人或機器)在編寫HTML文檔過程中常犯的錯誤。

2、Nekohtml能增補缺失的父元素、自動用結束標籤關閉相應的元素,以及不匹配的內嵌元素標籤。

NekoHTML的開發使用了Xerces Native Interface(XNI),後者是Xerces2的實現基礎。

3、下載地址:http://nekohtml.sourceforge.net/index.html

4、代碼實現:

package com.qianyan.test;  
  
import java.io.BufferedReader;  
import java.io.FileReader;  
  
import org.cyberneko.html.parsers.DOMParser;  
import org.w3c.dom.Document;  
import org.w3c.dom.Element;  
import org.w3c.dom.Node;  
import org.w3c.dom.NodeList;  
import org.xml.sax.InputSource;  
  
public class TestNekoHTML {  
      
    public static String textExtractor(Node root){  
           //若是文本的話,直接返回  
           if (root.getNodeType() == Node.TEXT_NODE) {  
            return root.getNodeValue().trim();  
           }  
           if(root.getNodeType() == Node.ELEMENT_NODE) {  
            Element elmt = (Element) root;  
            //拋棄腳本  
            if (elmt.getTagName().equals("STYLE")  
              || elmt.getTagName().equals("SCRIPT")  
              ||elmt.getTagName().equals("BR"))  
             return "";  
             
            NodeList children = elmt.getChildNodes();  
            StringBuilder text = new StringBuilder();  
            for (int i = 0; i < children.getLength(); i++) {  
             text.append(textExtractor(children.item(i)));  
            }  
            return text.toString();  
           }  
           //對其他類型的節點,返回空值  
           return "";  
        }  
      
    /** 
     * @param args 
     * @throws Exception  
     */  
    public static void main(String[] args) throws Exception {  
        DOMParser parser=new DOMParser();  
        BufferedReader reader=new BufferedReader(new FileReader("e:/baidu1.htm"));  
        parser.parse(new InputSource(reader));  
        Document doc=parser.getDocument();  
        Node body=doc.getElementsByTagName("body").item(0);  
        String str=textExtractor(body);  
        System.out.println(str);  
          
    }  
  
}  



五、使用HTMLParser

1、HTML Parser是一個對HTML進行分析的快速實時的解析器。

2、用法:

1)Visitor

2))Filter

3、下載地址:http://htmlparser.sourceforget.net/

4、代碼實現:

package com.qianyan.test;  
  
import org.htmlparser.Node;  
import org.htmlparser.NodeFilter;  
import org.htmlparser.Parser;  
import org.htmlparser.Tag;  
import org.htmlparser.filters.NodeClassFilter;  
import org.htmlparser.filters.OrFilter;  
import org.htmlparser.filters.TagNameFilter;  
import org.htmlparser.tags.ImageTag;  
import org.htmlparser.tags.InputTag;  
import org.htmlparser.tags.LinkTag;  
import org.htmlparser.tags.OptionTag;  
import org.htmlparser.tags.SelectTag;  
import org.htmlparser.util.NodeList;  
import org.htmlparser.util.ParserException;  
import org.htmlparser.visitors.NodeVisitor;  
import org.htmlparser.visitors.ObjectFindingVisitor;  
import org.junit.Ignore;  
import org.junit.Test;  
  
public class TestHtmlParser {  
  
    /** 
     * 測試ObjectFindVisitor的用法 
     */  
    @Test  
//  @Ignore  
    public void testImageVistor() {  
        try {  
            ImageTag imgLink;  
            ObjectFindingVisitor visitor = new ObjectFindingVisitor(  
                    ImageTag.class);  
            Parser parser = new Parser();  
            parser.setURL("http://www.baidu.com");  
            parser.setEncoding(parser.getEncoding());  
            parser.visitAllNodesWith(visitor);  
            Node[] nodes = visitor.getTags();  
  
            for (int i = 0; i < nodes.length; i++) {  
                imgLink = (ImageTag) nodes[i];  
                StringBuilder sb = new StringBuilder();  
                sb.append(" ImageURL = " + imgLink.getImageURL());  
                sb.append("---- ImageLocation = " + imgLink.extractImageLocn());  
                sb.append("--- SRC = " + imgLink.getAttribute("SRC"));  
                System.out.println(sb.toString());  
  
            }  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
  
    /** 
     * 測試NodeVisitor的用法,遍歷所有節點 
     */  
    @Test  
    @Ignore  
    public void testVisitorAll() {  
        try {  
            Parser parser = new Parser();  
            parser.setURL("http://www.baidu.com");  
            parser.setEncoding(parser.getEncoding());  
            NodeVisitor visitor = new MyNodeVisitor();  
            parser.visitAllNodesWith(visitor);  
        } catch (ParserException e) {  
            e.printStackTrace();  
        }  
    }  
  
    /** 
     * 測試NodeClassFilter用法 
     */  
    @Test  
    @Ignore  
    public void testLinkTag(){  
        try{  
            NodeFilter filter = new NodeClassFilter(LinkTag.class);  
            Parser parser = new Parser();  
            parser.setURL("http://www.baidu.com");  
            parser.setEncoding(parser.getEncoding());  
            NodeList list = parser.extractAllNodesThatMatch(filter);  
            for(int i = 0; i < list.size(); i++){  
                LinkTag node = (LinkTag) list.elementAt(i);  
                System.out.println("Link is :" + node.extractLink());  
            }  
        }catch(Exception e){  
            e.printStackTrace();  
        }  
    }  
      
    /** 
     * 測試TagNameFilter用法 
     */  
    @Test  
    @Ignore  
    public void testNodeFilter(){  
        try{  
            NodeFilter filter = new TagNameFilter("IMG");  
            Parser parser = new Parser();  
            parser.setURL("http://www.baidu.com");  
            parser.setEncoding(parser.getEncoding());  
            NodeList list = parser.extractAllNodesThatMatch(filter);  
            for(int i = 0; i < list.size(); i++){  
                System.out.println(" " + list.elementAt(i).toHtml());  
            }  
        }catch(Exception e){  
            e.printStackTrace();  
        }  
    }  
      
    /** 
     * 測試OrFilter的用法 
     */  
    @Test  
    @Ignore  
    public void testOrFliter(){  
        NodeFilter inputFilter = new NodeClassFilter(InputTag.class);  
        NodeFilter selectFilter = new NodeClassFilter(SelectTag.class);  
        NodeList  nodeList = null;  
        try{  
            Parser parser = new Parser();  
            parser  
            .setInputHTML("<head><title>OrFilter Test</title>"  
            + "<link href=http://www.baidu.com/test01/css.css’ text=’text/css’ rel=’stylesheet’ />"  
            + "<link href=http://www.baidu.com/test02/css.css’ text=’text/css’ rel=’stylesheet’ />"  
            + "</head>"  
            + "<body>"  
            + "<input type=’text’ value=’text1′ name=’text1′/>"  
            + "<input type=’text’ value=’text2′ name=’text2′/>"  
            + "<select><option id=’1′>1</option><option id=’2′>2</option><option id=’3′>3</option></select>"  
            + "<a href='http://www.baidu.com/'>baidu.com</a>"  
            + "</body>");  
              
            parser.setEncoding(parser.getEncoding());  
            OrFilter lastFilter = new OrFilter();  
            lastFilter.setPredicates(new NodeFilter[]{selectFilter, inputFilter});  
            nodeList = parser.parse(lastFilter);  
            for(int i = 0; i <= nodeList.size(); i++){  
                if(nodeList.elementAt(i) instanceof InputTag){  
                    InputTag tag = (InputTag)nodeList.elementAt(i);  
                    System.out.println("OrFilter tag name is :" + tag.getTagName()  
                            + " ,tag value is:" + tag.getAttribute("value"));  
                }  
                if(nodeList.elementAt(i) instanceof SelectTag){  
                    SelectTag tag = (SelectTag)nodeList.elementAt(i);  
                    NodeList list = tag.getChildren();  
                    for(int j = 0; j < list.size(); j++){  
                        OptionTag option = (OptionTag)list.elementAt(j);  
                        System.out.println("OrFilter Option"  
                            + option.getOptionText());  
                    }  
                }  
            }  
        }catch(Exception e){  
            e.printStackTrace();  
        }  
    }  
  
}  
  
/** 
 * 內部實現了NodeVisitor下的visitTag方法 
 * @author Administrator 
 * 
 */  
class MyNodeVisitor extends NodeVisitor {  
    public void visitTag(Tag tag) {  
        System.out  
                .println("Tag name is :" + tag.getTagName()  
                        + "--- Class is :" + tag.getClass() + "---"  
                        + tag.getText());  
    }  
} 



使用htmlparser 獲得頁面中的所有超鏈接

import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.htmlparser.visitors.HtmlPage;
public class ParserHtmlPage {
    public NodeList parser(String url) throws ParserException{
        /**根據url創建parser對象,   || Parser parser = Parser.createParser(url,encoding)**/
        Parser parser =  new Parser(url);
       
        /**設置編碼,必須與url編碼一樣,否則掛掉 **/
        parser.setEncoding("utf-8");
       
        /** 構建一個html頁面對象 **/
        HtmlPage htmlPage = new HtmlPage(parser);
        parser.visitAllNodesWith(htmlPage);
       
        /** 獲取body下面所有的節點 **/
        NodeList list = htmlPage.getBody();
       
        /** 建立一個filter,用於過濾節點 **/
        NodeFilter filter = new TagNameFilter("A");
       
        /** 得到過濾後的節點 **/
        list = list.extractAllNodesThatMatch(filter, true);
       
       
        for(int c =0; c < list.size(); c ++){
                LinkTag linkTag = (LinkTag) list.elementAt(c);
                System.out.println("["+linkTag.getStringText()+"]"+linkTag.getAttribute("href"));//取得href屬性的值
                //System.out.println(linkTag.getStringText());//取得鏈接的 文本
        }
        return list;
    }
   
    public static void main(String[] args) throws ParserException {
       ParserHtmlPage pp = new ParserHtmlPage();
       pp.parser("http://www.baidu.com");
    }
}



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