天天看点

Java获取网页编码

    使用爬虫从网上抓取到一个网页内容,要想能正确显示,必须要获取网页的原始编码,否则会出现乱码。首先需要获取网页内容,最简单的办法就是通过jdk自带的httpurlconnection类,要实现更复杂的抓取操作,请使用开源的爬虫框架,如crawler4j,web-harvest,jspider,webmagic,heritrix,nutch等,我并不是来说爬虫相关技术的,只是网页内容的获取需要使用到爬虫技术,所以顺带提提有关爬虫的框架,具体你们自己去研究。这里为了简便起见,我就以jdk自带的httpurlconnection类来抓取网页内容,抓取示例代码如下:

Java获取网页编码

package com.yida.test;  

import java.io.bufferedreader;  

import java.io.ioexception;  

import java.io.inputstreamreader;  

import java.net.httpurlconnection;  

import java.net.url;  

/** 

 * 提取网页内容 

 * @author lanxiaowei 

 * 

 */  

public class fetchwebpagetest {  

    public static void main(string[] args) throws ioexception {  

        string charset = "utf-8";  

        string line = "";  

        stringbuffer buffer = new stringbuffer();  

        url url = new url("http://www.baidu.com");  

        //开始访问该url  

        httpurlconnection urlconnection = (httpurlconnection)url.openconnection();  

        //获取服务器响应代码  

        int responsecode = urlconnection.getresponsecode();  

        string contenttype = urlconnection.getcontenttype();  

        //打印出content-type值,然后就可以从content-type中提取出网页编码  

        system.out.println("content-type:" + contenttype);  

        if(responsecode == 200){  

            //获取网页输入流  

            bufferedreader reader = new bufferedreader(new inputstreamreader(urlconnection.getinputstream(),charset));  

            while((line = reader.readline()) != null){  

                buffer.append(line).append("\n");  

            }  

            system.out.println(buffer.tostring());  

        }  

        else{  

            system.out.println("获取不到网页的源码,服务器响应代码为:"+responsecode);  

        urlconnection.disconnect();  

    }  

}  

     关键点在这一句代码:

Java获取网页编码

bufferedreader reader = new bufferedreader(new inputstreamreader(urlconnection.getinputstream(),charset));  

   这里的charset表示网页内容的字符集编码,上面的示例代码中charset是直接定义为utf-8,实际我们期望是能自动判断,因为并不是所有网页内容的字符集编码都为utf-8,这也是我们今天这篇文章的主题:如何获取网页内容的原始字符集编码。

    首先,我们可以通过urlconnection类的getcontenttype()方法的返回值中获取,比如:

Java获取网页编码

string contenttype = urlconnection.getcontenttype();  

     返回值类似这样:

Java获取网页编码

content-type:text/html; charset=utf-8  

     然后我们从字符串中提取出字符集编码,剩下这就是字符串处理了,没什么难度,你们都懂的!

    当然,urlconnection类的getcontenttype()方法的返回值并不能保证一定会包含字符集编码,这时我们就需要另辟蹊径,我们都知道一般html页面源代码中都会包含<meta标签,如:

Java获取网页编码

<%@ page language="java" contenttype="text/html; charset=utf-8"  

    pageencoding="utf-8"%>  

<!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd">  

<html>  

<head>  

<meta http-equiv="content-type" content="text/html; charset=utf-8">  

<title>欢迎页面</title>  

</head>  

<body>  

欢迎页面  

</body>  

</html>    

     关键点在这里:

Java获取网页编码

     我们可以通过正则表达式从中提取出编码,示例代码如下:

Java获取网页编码

import java.util.regex.matcher;  

import java.util.regex.pattern;  

 * 从html网页的meta元素中提取页面编码 

 * 这里采用的是正则表达式方式提取,你也可以采用xml解析的方式来提取[html其实就是xml] 

public class charsetextracttest {  

    public static void main(string[] args) {  

        //test1();  

        test2();  

    /** 

     * 常规情况 

     */  

    public static void test1() {  

        string content="<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +  

                "<head>\n" +  

                "<meta http-equiv = \"content-type\" content = \"text/html; charset=utf-8\" />\n" +  

                "<meta content=\"java获取 html网页编码\" name=\"keywords\"/>...\n";  

        pattern pattern = pattern.compile("<meta\\s+http-equiv\\s*=\\s*\"content-type\"\\s+content\\s*=\\s*\"[\\s\\s]*?charset=(\\s+?)\"\\s*/>");  

        matcher matcher=pattern.matcher(content);  

        if(matcher.find()){  

            system.out.println(matcher.group(1));  

     * 非常规情况,比如http-equiv和content属性颠倒了 

    public static void test2() {  

                "<meta content = \"text/html; charset=utf-8\" http-equiv = \"content-type\" />\n" +  

        string regex = "(<meta\\s+http-equiv\\s*=\\s*\"content-type\"\\s+content\\s*=\\s*\"[\\s\\s]*?charset=(\\s+?)\"\\s*/>)|" +   

                "(<meta\\s+content\\s*=\\s*\"[\\s\\s]*?charset=(\\s+?)\"\\s+http-equiv\\s*=\\s*\"content-type\"\\s*/>)";  

        pattern pattern = pattern.compile(regex);  

            system.out.println(matcher.group(4));  

     但遗憾的是,并不是每个网页内容都包含meta标签,因为总有些人不遵守html规范,这是我们该怎么办?还好我们还有一招可以来应对这种情形,那就是ibm的icu4j类库,icu4j可以从指定的字节数据从自动推断出其采用的字符集编码,具体示例代码如下:

Java获取网页编码

import java.io.inputstream;  

import com.ibm.icu.text.charsetdetector;  

import com.ibm.icu.text.charsetmatch;  

 * 使用icu4j探测内容编码,这里的内容可以来自于字符串,字节数组,输入流等等 

 *  

public class icu4jtest {  

        string data = "icu4j 是ibm的国际化开发组件icu的java语言实现版本。";  

        string encode = getencode(data);  

        system.out.println("encode:" + encode);  

    public static string getencode(string data) {  

        return getencode(data.getbytes());  

    public static string getencode(byte[] data) {  

        charsetdetector detector = new charsetdetector();  

        detector.settext(data);  

        charsetmatch match = detector.detect();  

        //取confidence值最大的  

        string encoding = match.getname();  

        system.out.println("the content in " + match.getname());  

        charsetmatch[] matches = detector.detectall();  

        system.out.println("all possibilities");  

        for (charsetmatch m : matches) {  

            system.out.println("charsetname:" + m.getname() + " confidence:"  

                    + m.getconfidence());  

        return encoding;  

    public static string getencode(inputstream data)  

            throws ioexception {  

     还有一点需要注意的就是,如果抓取到的网页内容输入流不管是使用gbk还是utf-8,都全是乱码,那很有可能是该网页所在服务器对其采用gzip压缩,所以在获取到网页输入流时首先需要对其进行gzip解压缩,那如何确定对方服务器是否有对网页进行gzip压缩呢,一般可以通过响应头信息中获取到,如果响应头里包含了如下信息:

Java获取网页编码

accept-encoding: gzip,deflate    

     则表明该网页被gzip压缩过,在获取网页内容之前,需要一个gzip解压缩过程,特此提醒!gzip解压缩示例代码如下:

Java获取网页编码

inputstream is = urlconnection.getinputstream();  

//用gzipinputstream 对原始的输入流包装一下  

gzipinputstream gis = new gzipinputstream(he.getcontent());  

bufferedreader reader = new bufferedreader(new inputstreamreader(gis,charset));  

   上述所有示例代码打包上传到我的百度网盘,代码下载地址如下:

    http://pan.baidu.com/s/1ktgqi0z

    如果你还有什么问题请加我Q-q:7-3-6-0-3-1-3-0-5,

或者加裙

Java获取网页编码

一起交流学习!

转载:http://iamyida.iteye.com/blog/2206228