前言
今天在測試爬蟲專案時,發現了一個很嚴肅的問題,當爬取的網頁編碼格式為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; }
這種方案對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; }
通過這種方式我們就可以解決gb2312編碼轉化為utf-8編碼時出現的亂碼問題。
四、總結
多思考,多動腦,這裡只是給出了一個工程解決方案,並沒有深入到其中的原理,由此問題可以引申出很多有意思的問題,如,utf-8、gbk、gb2312的編碼方式怎樣的?為什麼這樣轉化就可以解決問題?這些問題值得我們去深入研究。由於本篇文章主要是講工程解決方案,感興趣的讀者可以去深入瞭解。謝謝各位園友觀看~
附送一篇關於爬蟲亂碼問題解決的很好的文章,網路爬蟲的亂碼處理 ,講得很不錯,有做爬蟲的園友遇到這一部分的問題時可以好好參考參考。