【轉】python中文decode和encode轉碼

字符串在Python內部的表示是unicode編碼,所以,在作編碼轉換時,一般須要以unicode做爲中間編碼,即先將其餘編碼的字符串解碼(decode)成unicode,再從unicode編碼(encode)成另外一種編碼。html

decode的做用是將其餘編碼的字符串轉換成unicode編碼,如str1.decode('gb2312'),表示將gb2312編碼的字符串str1轉換成unicode編碼。 python

encode的做用是將unicode編碼轉換成其餘編碼的字符串,如str2.encode('gb2312'),表示將unicode編碼的字符串str2轉換成gb2312編碼。 linux

所以,轉碼的時候必定要先搞明白,字符串str是什麼編碼,而後decode成unicode,而後再encode成其餘編碼 正則表達式

(與代碼自己的編碼是一致的!)

測試:
個人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將其轉成unicode是不可能的。
因此正確的寫法應當是:
s="你好"
print s
s=s.decode('utf-8').encode('utf-8') 要用UTF-8來作編碼
print s
哈哈發現打印出來的是亂碼那隻能說明一件事情就是個人eclipse控制檯是GB2312的編碼!

請看:
如何得到系統的默認編碼?
#!/usr/bin/env python
#coding=utf-8
import sys
print sys.getdefaultencoding()

該段程序在英文WindowsXP上輸出爲:ascii 。我發現個人linux上面也是ascii編碼。因此我想打印出來看到的亂碼是正常的。由於我實際上是utf-8編碼的。

在某些IDE中,字符串的輸出老是出現亂碼,甚至錯誤,實際上是因爲IDE的結果輸出控制檯自身不能顯示字符串的編碼,而不是程序自己的問題。(是的。個人eclipse控制檯就是gb2312的編碼因此我文件保存爲utf-8的時候而後再經過打印是亂碼了!)


一、讀文件命令確定是:
myfile = codecs.open("c.html","r","utf-8") 由於我用gb2312來讀的話報錯

心得:檢查一個字符串是什麼編碼只須要看一下decode 若是用gb2312來decode沒報錯的話就表示是gb2312
若是用utf-8來decode沒有報錯的話就表示是utf-8

如今遇到一個問題就是
請看:
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
也沒問題

結論:我想是c.html頁面裏面 存在某些 特殊字符 只支持utf-8編碼。而不支持gb2312的編碼!
而d.html沒有這種特殊字符。這也就解釋了爲何
有的文件並無發生咱們想像中的問題!

因此我感受打開文件確定是用utf-8來讀取獲得一個unicode編碼值!
而後對其作utf-8的編碼處理。由於若是你作gb2312處理的話就會報錯了!

接着:
我看了一下個人正則表達式發現若是用gb2312作解碼處理的話同樣會報錯。因此判定確定是utf-8編碼了!
regex3 = regex3.decode('utf-8')
print type(regex3)                #返回爲unicode碼了!
print regex3                      #竟然打印爲正常的中文顯示了 奇怪

嘗試解決辦法:
一、所有用unicode處理
即正則我用regex3 = regex3.decode('utf-8') 將其處理成 unicode編碼了。而後內容也
print type(content) 也是unicode編碼。結果仍是不行!

難道是個人linux終端的編碼引發的嗎?我看了一下
locale 發現是GBK的終端的。即只有GBK編碼才能顯示出來爲中文的!
因而我將
regex3 = regex3.decode('utf-8').encode('gb2312') 編碼成gb2312結果能夠顯示中文!

OK。我又將個人內容也一塊兒弄成GB2312
content = content.encode('gb2312','ignore')
print content                 也能夠成功打印出來中文。

我想這個時候應該沒有什麼問題了吧。結果一用正則又死掉了。昏死!!!!!!!

換另一個好的文件測試下看看:換了以後發現沒死並且成功了!

因此我以爲:確定是這個文件裏面的某些內容與正則匹配出現了衝突!致使的!

繼續跟蹤:
出現以下的狀況
myfile = codecs.open("01.htm","r","utf-8","ignore")              
str = myfile.read()                               
content = str.replace("\n"," ")
print type(content)                               #發現是unicode碼
regex3 = 'class=wpcpsCSS>([^<]+)(?:.*?wpcppb_CSS> ([0-9]+) </span>)?.*?(?:.*?(已被關閉))?.*?([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) 

沒有什麼問題能夠成功出來結果。可是我
將content = content.encode('gb2312') 的話就發現 死掉了!
說明個人內容content與個人正則的編碼實際上是不同的!
我如今將個人正則也調成gb2312來測試。結果發現能夠出來。並且個人結果
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那正則的內容也應當是GBK 即二者的編碼必定要保持一致!不然就會出現死掉程序的狀況!



如今我這樣來處理
所有使用unicode編碼處理

myfile = codecs.open("right.html","r")    
str = myfile.read()                                 
content = str.replace("\n"," ")
content = content.decode('utf-8','ignore')     #使用utf-8解碼出來
都使用unicode編碼吧
如今正則也用
regex3 = regex3.decode('utf-8','ignore') 使用utf-8搞成unicode編碼

OK如今再來測試!

結論:
解決正則出現中文的BUG結論:
一、打開文件
myfile = codecs.open("right.html","r") 
不須要設置其編碼的!

設置編碼格式
str = myfile.read()                              
content = str.replace("\n"," ")
content = content.decode('utf-8','ignore')   #使用utf-8解碼成unicode格式

正則:
regex3 = regex3.decode('utf-8','ignore')    #正則也統一使用utf-8解碼成unicode格式

而後就能夠
p=re.compile(regex3)
results = p.findall(content) 
調用正則了! eclipse

相關文章
相關標籤/搜索