利用Java的net包获取网页源代码

来源:互联网 发布:南京大学 人工智能 编辑:程序博客网 时间:2024/06/06 08:42

读取过程分析

本文只是简单的读取网页源代码,用到的Java类很有限。

本文针对的目标网页都是一些简单的网页,这些网页不能加密,不能压缩(将网页代码去除空格、换行等,压缩成一行),不存在需要经过一次或n次跳转才能到达。PS:至少目前90%以上的网站都是这种简单的网站。

首先介绍一下HTTP请求头包含的内容:

  1. Accept:客户端希望接收的MIME数据类型,所有的数据类型可以参考http://tool.oschina.net/commons/。
  2. Accept-Encoding:浏览器支持的编码类型,包括gzip,defult,compress,identity。
  3. Accept-Language:浏览器支持的语言类型。zh-CN代表汉语,en代表英文。
  4. User-Agent:浏览器的标识,方便服务器识别。

Java代码

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL;import java.util.List;import java.util.Map;import java.util.Set;import java.util.zip.GZIPInputStream;import org.htmlparser.Node;import org.htmlparser.Parser;import org.htmlparser.filters.TagNameFilter;import org.htmlparser.nodes.TagNode;import org.htmlparser.util.ParserException;import org.htmlparser.util.SimpleNodeIterator;public class WebPageSourceCode {    private String pageEnCode;    public static void main(String[] args) {        String path = "http://www.hao123.com/";        String encode = "UTF-8";        WebPageSourceCode wb = new WebPageSourceCode();        String sourceCode = wb.getPageSourceCode(path, encode);        //http返回的头信息中没有包含网页的编码格式        if(wb.getPageEnCode() == null){            encode = getEncodeFromMeta(sourceCode);            sourceCode = wb.getPageSourceCode(path, encode);        }        System.out.println(sourceCode);    }    /**     *这里涉及到一些htmlparser包的一些知识,以后再说。     *下面使用UTF-8格式解析网页源码,可能存在中文乱码,但是我们要得到meta标签的内容     *而meta标签的内容是英文,所以中文乱码无所谓     */    private static String getEncodeFromMeta(String sourceCode) {        Parser p = Parser.createParser(sourceCode, "UTF-8");        String encode = "";        try {            SimpleNodeIterator sni = p.extractAllNodesThatMatch(new TagNameFilter("meta")).elements();            while(sni.hasMoreNodes()){                Node node = sni.nextNode();                TagNode tag = new TagNode();                tag.setText(node.toHtml());                String temp = null;                if((temp = tag.getAttribute("content")) != null &&                        temp.contains("text/html") && temp.contains("charset")){                    encode = temp.substring(temp.indexOf("=")+1);                }            }        } catch (ParserException e) {            System.out.println("HtmlParser库无法使用!");            e.printStackTrace();        }        return encode.trim();    }    public String getPageSourceCode(String path,String encode){        StringBuffer sb = new StringBuffer();        try {            //1.构建URL对象            URL url = new URL(path);            //2.打开URL链接            HttpURLConnection conn = (HttpURLConnection) url.openConnection();            //3.设置请求头属性            conn.setConnectTimeout(5000);//设置响应时间为5s            conn.setReadTimeout(3000);            conn.setRequestMethod("GET");            conn.setRequestProperty("Accept", "*/*");            conn.setRequestProperty("Accept-Encoding", "gzip,default");            conn.setRequestProperty("User-Agent",                     "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) "                    + "Chrome/23.0.1271.64 Safari/537.11");            //4.得到响应码            int responseCode = conn.getResponseCode();            Map<String, List<String>> responseHead = null;            if(responseCode == HttpURLConnection.HTTP_OK){                responseHead = conn.getHeaderFields();                //printHead(responseHead);                //5.得到网页内容的编码格式,防止中文乱码                String pageEncode = getEncode(responseHead);                if(pageEncode != null                         && pageEncode.trim().length() > 0){                    this.setPageEncode(pageEncode);                    encode = pageEncode;                }                //6.读取网页源代码                BufferedReader in = new BufferedReader(                        new InputStreamReader(                                new GZIPInputStream(conn.getInputStream()),                                encode));                String line = "";                while((line = in.readLine()) != null){                    sb.append(line);                    sb.append(System.getProperty("line.separator"));                }                in.close();                                 }else{                System.out.println("服务器响应失败,响应码:"+responseCode);            }               } catch (MalformedURLException e) {            e.printStackTrace();        } catch (UnsupportedEncodingException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        }           return sb.toString();    }    private String getEncode(Map<String, List<String>> map) {        String encode = "";        Set<Map.Entry<String, List<String>>> entry = map.entrySet();        for(Map.Entry<String, List<String>> temp: entry){            if(temp.getKey() !=null&&            temp.getKey().equals("Content-Type")){                String value = temp.getValue().toString()                        .replace("[", "").replace("]", "");                int start = value.indexOf("=");                if(start != -1){                    encode = value.substring(start+1);                }            }        }        return encode;    }    private void printHead(Map<String, List<String>> map) {        Set<Map.Entry<String, List<String>>> entry = map.entrySet();        for(Map.Entry<String, List<String>> temp: entry){            System.out.println(temp.getKey()+":"+temp.getValue());        }    }    public String getPageEnCode() {        return pageEnCode;    }    public void setPageEncode(String pageEnCode) {        this.pageEnCode = pageEnCode;    }}

实验说明

设置请求头的时候,最好设置Accept-Encoding属性,如果不设置这个属性,一般网站不会发送压缩数据,但是也有一部分网站会发送压缩数据,这大概是网站服务器的默认属性,如果有一部分是压缩有一部分不压缩,就很难处理流了,所以我设置了这个属性,网站的服务器就会发送压缩数据,这样处理流数据的方式就统一了。PS:浏览器请求头设置Accept-Encoding属性也只是建议性的!!!

处理网页数据流时,一般用UTF-8解码就可以了,但是不能排除有一部分网站是以GBK或gb2312格式编码正文内容的。不以正确的格式读取流数据,就会得到乱码。获取网页正文编码方式的途径有两种:1.返回的请求头中Content-Type属性的值中可能包含编码方式(Content-Type:[text/html;charset=UTF-8])2.如果1中没有写编码格式,就只能从meta标签中读取了。

建议先用第一种方法获取编码格式。

0 0
原创粉丝点击