【知識積累】爬蟲之網頁亂碼解決方法(gb2312 -> utf-8)

leesf發表於2016-03-03

前言

  今天在測試爬蟲專案時,發現了一個很嚴肅的問題,當爬取的網頁編碼格式為gb2312時,按照一般的辦法轉化為utf-8編碼時總是亂碼,PS:爬取的所有網頁無論何種編碼格式,都轉化為utf-8格式進行儲存。

一、問題出現

  使用這篇文章裡面的方法可以直接爬取頁面資訊並儲存至本地使用Httpclient實現網頁的爬取並儲存至本地當爬取這個網頁時http://stock.10jqka.com.cn/zhuanti/hlw_list/,發現使用之前(未知編碼 -> utf-8編碼)的轉化方式總是亂碼。於是乎查閱了不少資料,發現都不是太適用。最後自己摸索出了一個解決辦法,也特此記錄。

二、解決方案

  1. 將gb2312格式轉化為gbk格式

  2. 將gbk格式轉化為utf-8格式

  這裡的轉化需要使用gbk作為一箇中間格式,作為轉化橋樑。

三、具體思路

  1. 當開啟http://stock.10jqka.com.cn/zhuanti/hlw_list/這個連結,我們檢視原始碼會發現編碼格式為gb2312,如下圖所示

  

  2. 由於本專案之前就已經使用了轉化方案,但是此轉化方案對網頁為gb2312格式無效,本專案之前的轉化方案的核心原始碼為: 

public void getContent(String url) {
        this.get = new HttpGet(url);
        HttpResponse response = client.execute(this.get);
        HttpEntity entity = response.getEntity();
        byte[] bytes = EntityUtils.toByteArray(entity);
        String content = new String(bytes);
        // 預設為utf-8編碼
        String charset = "utf-8";
        // 匹配<head></head>之間,出現在<meta>標籤中的字元編碼
        Pattern pattern = Pattern.compile("<head>([\\s\\S]*?)<meta([\\s\\S]*?)charset\\s*=(\")?(.*?)\"");
        Matcher matcher = pattern.matcher(content.toLowerCase());
        if (matcher.find()) {    
            charset = matcher.group(4);
        } 
        // 將目標字元編碼轉化為utf-8編碼
        String temp = new String(bytes, charset);
        byte[] contentData = temp.getBytes("utf-8");
        return contentData;
    }
View Code

  這種方案對gb2312轉化後還是亂碼,之後的解決方案核心原始碼為:  

public void getContent(String url) {
        this.get = new HttpGet(url);
        HttpResponse response = client.execute(this.get);
        HttpEntity entity = response.getEntity();
        byte[] bytes = EntityUtils.toByteArray(entity);
        String content = new String(bytes);
        // 預設為utf-8編碼
        String charset = "utf-8";
        // 匹配<head></head>之間,出現在<meta>標籤中的字元編碼
        Pattern pattern = Pattern.compile("<head>([\\s\\S]*?)<meta([\\s\\S]*?)charset\\s*=(\")?(.*?)\"");
        Matcher matcher = pattern.matcher(content.toLowerCase());
        if (matcher.find()) {    
            charset = matcher.group(4);
            if (charset.equals("gb2312")) {
                byte[] gbkBytes = new String(bytes, "gbk").getBytes();
                return new String(gbkBytes, "utf-8").getBytes();
            }
        } 
        // 將目標字元編碼轉化為utf-8編碼
        String temp = new String(bytes, charset);
        byte[] contentData = temp.getBytes("utf-8");
        return contentData;
    }
View Code

  通過這種方式我們就可以解決gb2312編碼轉化為utf-8編碼時出現的亂碼問題。

四、總結

  多思考,多動腦,這裡只是給出了一個工程解決方案,並沒有深入到其中的原理,由此問題可以引申出很多有意思的問題,如,utf-8、gbk、gb2312的編碼方式怎樣的?為什麼這樣轉化就可以解決問題?這些問題值得我們去深入研究。由於本篇文章主要是講工程解決方案,感興趣的讀者可以去深入瞭解。謝謝各位園友觀看~

  附送一篇關於爬蟲亂碼問題解決的很好的文章,網路爬蟲的亂碼處理 ,講得很不錯,有做爬蟲的園友遇到這一部分的問題時可以好好參考參考。

 

相關文章