1. 網(wǎng)絡(luò)爬蟲亂碼的原因。
成都做網(wǎng)站、成都網(wǎng)站制作介紹好的網(wǎng)站是理念、設(shè)計(jì)和技術(shù)的結(jié)合。成都創(chuàng)新互聯(lián)擁有的網(wǎng)站設(shè)計(jì)理念、多方位的設(shè)計(jì)風(fēng)格、經(jīng)驗(yàn)豐富的設(shè)計(jì)團(tuán)隊(duì)。提供PC端+手機(jī)端網(wǎng)站建設(shè),用營銷思維進(jìn)行網(wǎng)站設(shè)計(jì)、采用先進(jìn)技術(shù)開源代碼、注重用戶體驗(yàn)與SEO基礎(chǔ),將技術(shù)與創(chuàng)意整合到網(wǎng)站之中,以契合客戶的方式做到創(chuàng)意性的視覺化效果。
源網(wǎng)頁的編碼與抓取后的編碼轉(zhuǎn)換不一致。如果源網(wǎng)頁是gbk編碼的字節(jié)流,程序在我們抓取后直接用utf-8編碼輸出到存儲(chǔ)文件,這必然會(huì)造成亂碼,即當(dāng)源網(wǎng)頁編碼與程序抓取后直接處理編碼一致時(shí),就不會(huì)出現(xiàn)亂碼,然后統(tǒng)一字符編碼后也就不會(huì)出現(xiàn)亂碼。注意區(qū)分源網(wǎng)絡(luò)代碼A,程序B直接使用的代碼,統(tǒng)一轉(zhuǎn)換字符的代碼C。
2. 是網(wǎng)頁的服務(wù)器端代碼。
B.捕獲的數(shù)據(jù)原本是字節(jié)數(shù)組,由A編碼,只有B=A才能保證不會(huì)出現(xiàn)亂碼;否則,當(dāng)字符集不兼容時(shí),就會(huì)出現(xiàn)亂碼字符。這一步常用于測試。
c、統(tǒng)一轉(zhuǎn)碼是指在獲得網(wǎng)頁的原始編碼A后進(jìn)行統(tǒng)一編碼,主要是將每個(gè)網(wǎng)頁的數(shù)據(jù)統(tǒng)一成一種編碼,往往首選字符集較大的utf-8。
每個(gè)網(wǎng)頁都有自己的代碼,比如gbk,utf-8,iso8859-1,日本jp系統(tǒng)代碼,西歐,俄語等等。爬行時(shí),所有類型的代碼都將被擴(kuò)展。有的爬蟲只是簡單的識(shí)別網(wǎng)頁,然后統(tǒng)一編碼,有的則直接按照utf-8統(tǒng)一處理,不需要判斷源網(wǎng)頁,顯然會(huì)造成亂碼。
3. 亂碼的解決方案。
根據(jù)原因找到解決辦法很簡單。
1) 確定源網(wǎng)頁的代碼a。
代碼a通常位于網(wǎng)頁的三個(gè)位置,即httpheader的內(nèi)容、網(wǎng)頁的元字符集和網(wǎng)頁標(biāo)題中的文檔定義。獲取源網(wǎng)頁代碼時(shí),依次判斷這三部分?jǐn)?shù)據(jù),從頭到尾優(yōu)先級(jí)相同。
理論上這是對的,但是國內(nèi)有些網(wǎng)站不符合標(biāo)準(zhǔn)。比如寫出來的gbk其實(shí)是utf-8,有的寫出來是utf-8,其實(shí)是gbk。當(dāng)然這是幾個(gè)網(wǎng)站,但是確實(shí)存在。因此,在確定網(wǎng)頁編碼時(shí),應(yīng)該對這種特殊情況給予特殊處理,如中文檢查、默認(rèn)編碼等策略。
在另一種情況下,如果以上三種都沒有編碼信息,一般使用第三方的網(wǎng)頁編碼智能識(shí)別工具,如cpdetector。原理是通過統(tǒng)計(jì)字節(jié)數(shù)組的特性來計(jì)算實(shí)際編碼,有一定的準(zhǔn)確率,但是我發(fā)現(xiàn)在實(shí)踐中準(zhǔn)確率還是很有限的。
但是綜合以上三種編碼確認(rèn)方法后,中文亂碼的問題幾乎可以完全解決。在我的基于nutch1.6的網(wǎng)絡(luò)爬蟲系統(tǒng)中,經(jīng)過統(tǒng)計(jì),編碼準(zhǔn)確率可以達(dá)到99.99%,這也證明了上述方法和策略的可行性。
2) 程序通過代碼b還原源網(wǎng)頁數(shù)據(jù)。
顯然,這里的B應(yīng)該等于a,在java中,如果源網(wǎng)頁的字節(jié)數(shù)組是source_byte_array,就會(huì)轉(zhuǎn)換成stringstr=newstring(source_byte_array,B)。即這些字節(jié)數(shù)組對應(yīng)的字符被正確編碼顯示在內(nèi)存中,此時(shí)打印結(jié)果正常。此步驟通常用于調(diào)試或控制臺(tái)輸出測試。
3) 統(tǒng)一轉(zhuǎn)碼。
網(wǎng)絡(luò)爬蟲系統(tǒng)中有很多數(shù)據(jù)源。如果無法使用數(shù)據(jù),它將被轉(zhuǎn)換為其原始數(shù)據(jù),如果這樣做是浪費(fèi)的。所以一般爬蟲系統(tǒng)要對抓取的結(jié)果進(jìn)行統(tǒng)一編碼,做到一致,使用方便。此時(shí),在(2)的基礎(chǔ)上,可以進(jìn)行統(tǒng)一的編碼轉(zhuǎn)換,在java中的實(shí)現(xiàn)如下。
源網(wǎng)頁的字節(jié)數(shù)組是source_byte_array。
轉(zhuǎn)換為普通字符串:stringnormal_source_str=newstring(source_byte_array,c)。這時(shí)候可以直接用javaapi存儲(chǔ),但是字符串往往不直接寫。因?yàn)橐话闩老x存儲(chǔ)是將多個(gè)源網(wǎng)頁存儲(chǔ)在一個(gè)文件中,所以要記錄字節(jié)偏移量,所以下一步。 再將得到的str轉(zhuǎn)換為統(tǒng)一的編碼C格式的字節(jié)數(shù)組,則byte[] new_byte_array=normal_source_str.getBytes(C)即可,此時(shí)即可用java io api將數(shù)組寫入文件,并記錄相應(yīng)的字節(jié)數(shù)組偏移量等,待真正使用時(shí),直接io讀取即可。
爬蟲過程不僅會(huì)存在亂碼問題,還會(huì)存在網(wǎng)站爬取涉及法律、IP受限,爬取行為受限等等問題,這個(gè)時(shí)候就需要不斷去解決這些問題。
1、你要將所有的文件的編碼都設(shè)置成UTF-8,還有,你的MyEclipse或者Eclipse應(yīng)該配置jsp還有java文件還有項(xiàng)目都設(shè)置為UTF-8.
2、eclipse 中使用模板新建 JSP,xhtml等 文件時(shí),默認(rèn)的編碼為:ISO-8859-1。?ISO-8859-1 編碼對于中文的顯示是不支持的,如果要支持簡體中文,則編碼方式應(yīng)為 GBK 或者 GB2312 或者 UTF-8(推薦) 等。右鍵菜單欄window -- preferences -- 在type filter text中輸入jsp; --?選擇下面的jsp - 選擇creating files組中的encoding 為UTF-8編碼就可以了
如果要使新建立工程、java文件直接使UTF-8則需要做以下工作:?
1、windows-Preferences...打開"首選項(xiàng)"對話框,左側(cè)導(dǎo)航樹,導(dǎo)航到general-Workspace,右側(cè) Text file encoding,選擇Other,改變?yōu)閁TF-8,以后新建立工程其屬性對話框中的Text file encoding即為UTF-8。
2、windows-Preferences...打開"首選項(xiàng)"對話框,左側(cè)導(dǎo)航樹,導(dǎo)航到general-Content Types,右側(cè)Context Types樹,點(diǎn)開Text,選擇Java Source File,在下面的Default encoding輸入框中輸入U(xiǎn)TF-8,點(diǎn)Update,則設(shè)置Java文件編碼為UTF-8。其他java應(yīng)用開發(fā)相關(guān)的文件 如:properties、XML等已經(jīng)由Eclipse缺省指定,分別為ISO8859-1,UTF-8,如開發(fā)中確需改變編碼格式則可以在此指定。
1、Java中,【String.getBytes(String decode)】的方法,會(huì)根據(jù)指定的decode,編碼返回某字符串在該編碼下的byte數(shù)組表示,例如:
byte[] b_gbk = "中".getBytes("GBK");
byte[] b_utf8 = "中".getBytes("UTF-8");
byte[] b_iso88591 = "中".getBytes("ISO8859-1")
上面三行代碼表示:分別返回“中”這個(gè)漢字在GBK、UTF-8和ISO8859-1編碼下的byte數(shù)組表示,此時(shí)b_gbk的長度為2,b_utf8的長度為3,b_iso88591的長度為1。
2、而通過【new String(byte[], decode)】的方式來還原這個(gè)“中”字時(shí),實(shí)際是使用decode指定的編碼來將byte[ ]解析成字符串,例如:
String s_gbk = new String(b_gbk,"GBK");
String s_utf8 = new String(b_utf8,"UTF-8");
String s_iso88591 = new String(b_iso88591,"ISO8859-1");
s_gbk和s_utf8都是“中”,而只有s_iso88591是一個(gè)不認(rèn)識(shí) 的字符,因?yàn)镮SO8859-1編碼的編碼表中,根本就沒有包含漢字字符,當(dāng)然也就無法通過"中".getBytes("ISO8859-1")。
因此,通過【String.getBytes(String decode)】方法來得到byte[ ]時(shí),要確定decode的編碼表中確實(shí)存在String表示的碼值,這樣得到的byte[ ]數(shù)組才能正確被還原。
擴(kuò)展資料
java中文編碼避免亂碼
1、為了讓中文字符適應(yīng)某些特殊要求(如http header頭要求其內(nèi)容必須為iso8859-1編碼),可能會(huì)通過將中文字符按照字節(jié)方式來編碼的情況,比如:
String s_iso88591 = new String("中".getBytes("UTF-8"),"ISO8859-1")
2、上述例子中的s_iso8859-1字符串實(shí)際是三個(gè)在 ISO8859-1中的字符,在將這些字符傳遞到目的地后,目的地程序再通過相反的方式:
String s_utf8 = new String(s_iso88591.getBytes("ISO8859-1"),"UTF-8")
來得到正確的中文漢字。這樣就既保證了遵守協(xié) 議規(guī)定、也支持中文。
3、String.getBytes(String decode)方法會(huì)根據(jù)指定的decode編碼返回某字符串在該編碼下的byte數(shù)組表示這里是encode ,not decode,從字符串到字節(jié)數(shù)組是編碼的過程,從字節(jié)數(shù)組到字符串(即 new String(byte[] , charsetname))才是解碼的過程。
參考資料:百度百科-UTF-8
要明白,用filewriter讀取文件采取的是平臺(tái)默認(rèn)編碼(視操作系統(tǒng)而定)。當(dāng)要寫入的文本文件編碼和平臺(tái)默認(rèn)編碼不一致時(shí),就會(huì)出現(xiàn)中文亂碼的情況。這時(shí)可以使用filewriter 的父類OutputStreamWriter來讀取。OutputStreamWriter允許用戶指定編碼方式,代碼為:
FileInputStream fis=new FileInputStream("文件路徑");
OutputStreamWriter osw=new OutputStreamWriter(fis,"文本文件的編碼方式(ANSI,UTF-8...)");
osw.write();
這樣寫入的編碼可以保證和源文本文件編碼一致,就不會(huì)出現(xiàn)亂碼了。。。
分享名稱:java中防止亂碼的代碼 java中防止亂碼的代碼是什么
分享地址:http://jinyejixie.com/article6/hpcdog.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)頁設(shè)計(jì)公司、響應(yīng)式網(wǎng)站、網(wǎng)站收錄、面包屑導(dǎo)航、定制網(wǎng)站、網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)