Python實(shí)現(xiàn)模擬錕斤拷等各類亂碼詳解
錕拷碼和口字碼
說到亂碼問題就不得不提到錕斤拷,這算是非常常見的一種亂碼形式,那么它到底是經(jīng)過何種錯(cuò)誤操作產(chǎn)生的呢?下面我們一步步探究。
看一個(gè)基本示例:
"??".encode("u8").decode("gbk")
'錕斤拷'
我們將?字符以UTF-8編碼后,以GBK編碼解碼就可以得到 錕斤拷 的亂碼。
那么為什么 錕斤拷 為什么如此常見呢?這是因?yàn)榇蟛糠志幊陶Z言在使用UNICODE系列的編碼去解碼時(shí),會將不識別的字節(jié)編碼為0xFFFD(65533)即?字符表示未知字符進(jìn)行占位:
"\uFFFD"
'?'
注意:UNICODE系列包括UTF-8、UTF-16、UTF-32編碼,一般UNICODE編碼指UTF-16編碼。在python中unicode_escape編碼表示UNICODE編碼的的轉(zhuǎn)義形式:
"\uFFFD".encode("unicode_escape").decode()
'\\ufffd'
對于Python,默認(rèn)情況下解碼碰到未知字符時(shí)會直接拋出異常,但是如果設(shè)置errors參數(shù)為replace時(shí),則會將未知字符解碼為?占位。
將漢字用GBK編碼:
"小小明".encode("gbk")
b'\xd0\xa1\xd0\xa1\xc3\xf7'
將上述編碼結(jié)果用UTF-8編碼解碼,并設(shè)置為替換模式:
"小小明".encode("gbk").decode("u8", "replace")
'СС??'
0xd0a1被解碼成С,但是0xc3和0xf7無法被UTF-8編碼識別,只能用占位符?替換,于是就得到了上面的結(jié)果。
此時(shí)我們再編碼并解碼:
"小小明".encode("gbk").decode("u8", "replace") \ .encode("u8").decode("gbk", "replace")
'小小錕斤拷'
這是因?yàn)?被編碼成了0xEFBFBD
"??".encode("u8")
b'\xef\xbf\xbd\xef\xbf\xbd'
而0xEFBFBDEFBFBD被GBK解碼時(shí),正好就是錕(0xEFBF),斤(0xBDEF),拷(0xBFBD)。
上述以?為主的亂碼字符就是口字碼,原因是以UTF-8編碼讀取了GBK編碼的中文。
而錕拷體則是大部分都是錕斤拷的全中文字符,原因是用GBK編碼讀取了UTF-8編碼的口字碼中文。
古文碼與問句碼
問句碼產(chǎn)生的核心原因在于GBK對于無法編碼的字符會使用?填充:
"???".encode("gbk", "replace")
b'??'
古文碼則與前面的口字碼產(chǎn)生原因相反,使用GBK編碼讀取以UTF-8編碼的中文:
"小小明".encode("u8").decode("gbk", "replace")
'灝忓皬鏄?'
此時(shí)的 灝忓皬鏄 就非常像古文,gbk解碼對于不識別的字節(jié)也使用?占位。
此時(shí)gbk編碼對于?編碼失敗,使用?替代:
'灝忓皬鏄?'.encode("gbk", "replace")
b'\xe5\xb0\x8f\xe5\xb0\x8f\xe6\x98?'
此時(shí)再用UTF-8解碼就得到了問句碼:
b'\xe5\xb0\x8f\xe5\xb0\x8f\xe6\x98?'.decode("u8", "ignore")
'小小?'
不過問句碼只在原始字符串為奇數(shù)時(shí)產(chǎn)生,如果原始字符串長度為偶數(shù),使用上述編碼方式則可以原樣還原字符串:
"小小明月".encode("u8").decode("gbk", "replace") \ .encode("gbk", "replace").decode("u8", "ignore")
'小小明月'
這樣說明只要我們將原始漢字字符串填充到偶數(shù),就可以使用古文碼實(shí)現(xiàn)可逆的數(shù)據(jù)傳輸,而錕拷體則是一種不可逆的亂碼。
符號碼和拼音碼
還有兩種可逆的亂碼,我們先看看符號碼:
"小小明".encode("u8").decode("iso8859-1")
'å°\x8få°\x8fæ\x98\x8e'
像這種大部分字符為各種符號的亂碼就稱為符號碼,符號碼可以直接還原為原始的文本:
'?°\x8f?°\x8f?\x98\x8e'.encode("iso8859-1").decode("u8")
'小小明'
再看看拼音碼:
"小小明".encode("gbk").decode("iso8859-1")
'ССÃ÷'
這種大部分字符都是帶有聲調(diào)的字母稱為拼音碼,同樣可以直接還原:
'D?D??÷'.encode("iso8859-1").decode("gbk")
'小小明'
總結(jié)
名稱 | 示例 | 特點(diǎn) | 原因 |
---|---|---|---|
口字碼 | СС?? | 大部分字符是問號小方塊 | UTF-8解碼GBK編碼的中文 |
錕拷體 | 錕斤拷小小錕斤拷學(xué)習(xí)錕斤拷 | 全中文字符,大部分都是"錕斤拷"這幾個(gè)字符 | GBK解碼UTF-8編碼的口字碼 |
古文碼 | 灝忓皬鏄庢湀 | 大部分都是生僻字,像古文 | GBK解碼UTF-8編碼的中文漢字 |
問句碼 | 小小? | 字符串長度為奇數(shù)時(shí),結(jié)尾為問號 | GBK遇到不能編碼的字符時(shí)填充 |
符號碼 | 好好å\xad¦å¤©å¤©å\xad¦ | 大部分字符為各種符號 | ISO8859-1編碼解碼UTF-8編碼的中文漢字 |
拼音碼 | ºÃºÃѧϰÌìÌìÏòÉÏ | 大部分字符都是帶有聲調(diào)的字母 | ISO8859-1編碼解碼GBK編碼的中文漢字 |
到此這篇關(guān)于Python實(shí)現(xiàn)模擬錕斤拷等各類亂碼詳解的文章就介紹到這了,更多相關(guān)Python模擬亂碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python3用urllib抓取貼吧郵箱和QQ實(shí)例
在本篇文章里小編給大家整理了關(guān)于python3中運(yùn)用urllib抓取貼吧的郵箱以及QQ的實(shí)例內(nèi)容,需要的朋友們可以學(xué)習(xí)下。2020-03-03Python進(jìn)行數(shù)據(jù)可視化Plotly與Dash的應(yīng)用小結(jié)
數(shù)據(jù)可視化是數(shù)據(jù)分析中至關(guān)重要的一環(huán),它能夠幫助我們更直觀地理解數(shù)據(jù)并發(fā)現(xiàn)隱藏的模式和趨勢,本文主要介紹了Python進(jìn)行數(shù)據(jù)可視化Plotly與Dash的應(yīng)用小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下2024-04-04Pandas中DataFrame.drop()函數(shù)的具體使用
DataFrame.drop是Pandas庫中一個(gè)非常實(shí)用的函數(shù),用于刪除 DataFrame中的行或列,本文就來介紹一下Pandas中DataFrame.drop()函數(shù)的具體使用,感興趣的可以了解一下2024-07-07termux中matplotlib無法顯示中文問題的解決方法
這篇文章主要介紹了termux中matplotlib無法顯示中文問題的解決方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01分享5個(gè)數(shù)據(jù)處理更加靈活的pandas調(diào)用函數(shù)方法
這篇文章主要介紹了分享5個(gè)數(shù)據(jù)處理更加靈活的pandas調(diào)用函數(shù)方法,文章基于python的相關(guān)內(nèi)容展開詳細(xì)介紹,需要的小伙伴可以參考一下2022-04-04