前言
最近做一個搜索項目,需要爬取很多網站獲取需要的信息。在爬取網頁的時候,需要獲得該網頁的編碼,不然的話會發現爬取下來的網頁有很多都是亂碼。
分析
一般情況下,網頁頭信息會指定編碼,可以解析header或者meta獲得charset。但有時網頁並沒沒有指定編碼,這時就需要通過網頁內容檢測編碼格式,通過調研,最好用的還是cpdetector。
cpdetector自動檢測文本編碼格式,誰先返回非空,就以該結果為字符編碼。內置了一些常用的探測實現類,這些探測實現類的實例可以通過add方法加進來,如等,detector按照“誰先返回非空的探測結果,就以誰的結果為准”的原則返回探測到的字符集編碼。
1、首先,可從header中解析charset
網頁頭信息中的Content-Type會指定編碼,如圖:
可以通過分析header,查找字符編碼。
Map<String, List<String>> map = urlConnection.getHeaderFields(); Set<String> keys = map.keySet(); Iterator<String> iterator = keys.iterator(); // 遍歷,查找字符編碼 String key = null; String tmp = null; while (iterator.hasNext()) { key = iterator.next(); tmp = map.get(key).toString().toLowerCase(); // 獲取content-type charset if (key != null && key.equals("Content-Type")) { int m = tmp.indexOf("charset="); if (m != -1) { strencoding = tmp.substring(m + 8).replace("]", ""); return strencoding; } } }
2、其次,可從網頁meta中解析出charset
正常情況下,在寫網頁時,會指定網頁編碼,可在meta中讀出來。如圖:
首先獲取網頁流,因為英文和數字不會亂碼,可以解析meta,獲得charset。
StringBuffer sb = new StringBuffer(); String line; try { BufferedReader in = new BufferedReader(new InputStreamReader(url .openStream())); while ((line = in.readLine()) != null) { sb.append(line); } in.close(); } catch (Exception e) { // Report any errors that arise System.err.println(e); System.err .println("Usage: java HttpClient <URL> [<filename>]"); } String htmlcode = sb.toString(); // 解析html源碼,取出<meta />區域,並取出charset String strbegin = "<meta"; String strend = ">"; String strtmp; int begin = htmlcode.indexOf(strbegin); int end = -1; int inttmp; while (begin > -1) { end = htmlcode.substring(begin).indexOf(strend); if (begin > -1 && end > -1) { strtmp = htmlcode.substring(begin, begin + end).toLowerCase(); inttmp = strtmp.indexOf("charset"); if (inttmp > -1) { strencoding = strtmp.substring(inttmp + 7, end).replace( "=", "").replace("/", "").replace("\"", "") .replace("\'", "").replace(" ", ""); return strencoding; } } htmlcode = htmlcode.substring(begin); begin = htmlcode.indexOf(strbegin); }
3、當使用1、2解析不出編碼時,使用cpdetector根據網頁內容探測出編碼格式
可以添加多個編碼探測實例:
public static void getFileEncoding(URL url) throws MalformedURLException, IOException { CodepageDetectorProxy codepageDetectorProxy = CodepageDetectorProxy.getInstance(); codepageDetectorProxy.add(JChardetFacade.getInstance()); codepageDetectorProxy.add(ASCIIDetector.getInstance()); codepageDetectorProxy.add(UnicodeDetector.getInstance()); codepageDetectorProxy.add(new ParsingDetector(false)); codepageDetectorProxy.add(new ByteOrderMarkDetector()); Charset charset = codepageDetectorProxy.detectCodepage(url); System.out.println(charset.name()); } }