Python之中文亂碼解決方案
下方查看歷史精選文章
大數(shù)據(jù)測試過程、策略及挑戰(zhàn)
在Python2.X及Python3有時經(jīng)常碰到各種中文亂碼的情況,這里整理了相關(guān)各種情況匯總。
字符串在Python內(nèi)部的表示是unicode編碼,因此,在做編碼轉(zhuǎn)換時,通常需要以unicode作為中間編碼,即先將其他編碼的字符串解碼(decode)成unicode,再從unicode編碼(encode)成另一種編碼。
decode的作用是將其他編碼的字符串轉(zhuǎn)換成unicode編碼,如str1.decode('gb2312'),表示將gb2312編碼的字符串str1轉(zhuǎn)換成unicode編碼。
encode的作用是將unicode編碼轉(zhuǎn)換成其他編碼的字符串,如str2.encode('gb2312'),表示將unicode編碼的字符串str2轉(zhuǎn)換成gb2312編碼。
因此,轉(zhuǎn)碼的時候一定要先搞明白,字符串str是什么編碼,然后decode成unicode,然后再encode成其他編碼
代碼中字符串的默認編碼與代碼文件本身的編碼一致。
如:s='中文'
如果是在utf8的文件中,該字符串就是utf8編碼,如果是在gb2312的文件中,則其編碼為gb2312。
(與代碼本身的編碼是一致的!)
測試:
我的eclipse里面代碼為utf-8編碼的。然后我這樣寫代碼
s="你好"
s=s.decode('gb2312').encode('utf-8')
print s
報錯:
UnicodeDecodeError: 'gb2312' codec can't decode bytes in position 2-3: illegal multibyte sequence
原因:因為我的文件為UTF-8編碼的。所以你想用gb2312將其轉(zhuǎn)成unicode是不可能的。
所以正確的寫法應(yīng)當(dāng)是:
s="你好"
print s
s=s.decode('utf-8').encode('utf-8') 要用UTF-8來做編碼
print s
哈哈發(fā)現(xiàn)打印出來的是亂碼那只能說明一件事情就是我的eclipse控制臺是GB2312的編碼!
請看:
如何獲得系統(tǒng)的默認編碼?
#!/usr/bin/env python
#coding=utf-8
import sys
print sys.getdefaultencoding()
該段程序在英文WindowsXP上輸出為:ascii 。我發(fā)現(xiàn)我的linux上面也是ascii編碼。所以我想打印出來看到的亂碼是正常的。因為我其實是utf-8編碼的。
在某些IDE中,字符串的輸出總是出現(xiàn)亂碼,甚至錯誤,其實是由于IDE的結(jié)果輸出控制臺自身不能顯示字符串的編碼,而不是程序本身的問題。(是的。我的eclipse控制臺就是gb2312的編碼所以我文件保存為utf-8的時候然后再通過打印是亂碼了?。?/span>
1、讀文件命令肯定是:
myfile = codecs.open("c.html","r","utf-8") 因為我用gb2312來讀的話報錯
心得:檢查一個字符串是什么編碼只需要看一下decode 如果用gb2312來decode沒報錯的話就表示是gb2312
如果用utf-8來decode沒有報錯的話就表示是utf-8
現(xiàn)在遇到一個問題就是
請看:
myfile = codecs.open("c.html","r","utf-8")
str = myfile.read()
content = str.replace("\n"," ")
content = content.encode('utf-8')
print content
沒有報錯
再看:
myfile = codecs.open("c.html","r","utf-8")
str = myfile.read() # 顯示中文
content = str.replace("\n"," ")
content = content.encode('gb2312') # 用gb2312
print content
報錯:UnicodeEncodeError: 'gb2312' codec can't encode character u'\u2014' in position 12628
再看:
myfile = codecs.open("d.html","r","utf-8")
str = myfile.read() #顯示中文
content = str.replace("\n"," ")
content = content.encode('gb2312') # 用gb2312
print content
沒問題
myfile = codecs.open("d.html","r","utf-8")
str = myfile.read() #顯示中文
content = str.replace("\n"," ")
content = content.encode('utf-8')
print content
也沒問題
結(jié)論:我想是c.html頁面里面 存在某些 特殊字符 只支持utf-8編碼。而不支持gb2312的編碼!
而d.html沒有這種特殊字符。這也就解釋了為什么
有的文件并沒有發(fā)生我們想像中的問題!
所以我感覺打開文件肯定是用utf-8來讀取得到一個unicode編碼值!
然后對其做utf-8的編碼處理。因為如果你做gb2312處理的話就會報錯了!
接著:
我看了一下我的正則表達式發(fā)現(xiàn)如果用gb2312做解碼處理的話一樣會報錯。所以斷定肯定是utf-8編碼了!
regex3 = regex3.decode('utf-8')
print type(regex3) # 返回為unicode碼了!
print regex3 # 居然打印為正常的中文顯示了 奇怪
1、全部用unicode處理
即正則我用regex3 = regex3.decode('utf-8') 將其處理成 unicode編碼了。然后內(nèi)容也
print type(content) 也是unicode編碼。結(jié)果還是不行!
難道是我的linux終端的編碼引起的嗎?我看了一下
locale 發(fā)現(xiàn)是GBK的終端的。即只有GBK編碼才能顯示出來為中文的!
于是我將
regex3 = regex3.decode('utf-8').encode('gb2312') 編碼成gb2312結(jié)果可以顯示中文!
OK。我又將我的內(nèi)容也一起弄成GB2312
content = content.encode('gb2312','ignore')
print content 也可以成功打印出來中文。
我想這個時候應(yīng)該沒有什么問題了吧。結(jié)果一用正則又死掉了?;杷溃。。。。。?!
換另外一個好的文件測試下看看:換了之后發(fā)現(xiàn)沒死而且成功了!
所以我覺得:肯定是這個文件里面的某些內(nèi)容與正則匹配出現(xiàn)了沖突!導(dǎo)致的!
繼續(xù)跟蹤:
出現(xiàn)如下的情況
myfile = codecs.open("01.htm","r","utf-8","ignore")
str = myfile.read()
content = str.replace("\n"," ")
print type(content) #發(fā)現(xiàn)是unicode碼
regex3 = 'class=wpcpsCSS>([^<]+)(?:.*?wpcppb_CSS> ([0-9]+) </span>)?.*?(?:.*?(已被關(guān)閉))?.*?([0-9]+)個回答.*?([0-9]+)次瀏覽.*?(?:<div class=wpcptfCSS>.*?user\?userid=([0-9]+).*?>(.*?)</a> </div>.*?)?(?:user\?userid=([0-9]+)")? class="wpfitCSS[^"]+">([^<]+).*?class=wpcptsCSS>([^<]+).*?([0-9.]{9,}\*).*?class=wpcpdCSS>(.*?)</div> <div class=wpcpfCSS>'
content = content.encode('utf-8')
p=re.compile(regex3)
results = p.findall(content)
沒有什么問題可以成功出來結(jié)果。但是我
將content = content.encode('gb2312') 的話就發(fā)現(xiàn) 死掉了!
說明我的內(nèi)容content與我的正則的編碼其實是不一樣的!
我現(xiàn)在將我的正則也調(diào)成gb2312來測試。結(jié)果發(fā)現(xiàn)可以出來。而且我的結(jié)果
results = p.findall(content)
for ele in results:
print ele[0],ele[1],ele[2],ele[3],ele[4],ele[5],ele[6],ele[7],ele[8],ele[9],ele[10]
在eclipse(默認為gb2312)下面也是沒有問題的了!~
所以我想:如果content是GBK那正則的內(nèi)容也應(yīng)當(dāng)是GBK 即兩者的編碼一定要保持一致!否則就會出現(xiàn)死掉程序的情況!
現(xiàn)在我這樣來處理
全部使用unicode編碼處理
myfile = codecs.open("right.html","r")
str = myfile.read()
content = str.replace("\n"," ")
content = content.decode('utf-8','ignore') #使用utf-8解碼出來
都使用unicode編碼吧
現(xiàn)在正則也用
regex3 = regex3.decode('utf-8','ignore') 使用utf-8搞成unicode編碼
OK現(xiàn)在再來測試!
結(jié)論:
解決正則出現(xiàn)中文的BUG結(jié)論:
1、打開文件
myfile = codecs.open("right.html","r")
不需要設(shè)置其編碼的!
設(shè)置編碼格式
str = myfile.read()
content = str.replace("\n"," ")
content = content.decode('utf-8','ignore') #使用utf-8解碼成unicode格式
正則:
regex3 = regex3.decode('utf-8','ignore') #正則也統(tǒng)一使用utf-8解碼成unicode格式
然后就可以
p=re.compile(regex3)
results = p.findall(content)
調(diào)用正則了!
這樣我就不用擔(dān)心說 因為編碼問題導(dǎo)致出來的錯誤。
Python之所以出現(xiàn)100%的CPU消耗原因在于 我的正則里面有一個死循環(huán)一直出不來。汗!?。。。?!


