python中文編碼與json中文輸出問題詳解
前言
python2.x版本的字符編碼有時(shí)讓人很頭疼,遇到問題,網(wǎng)上方法可以解決錯(cuò)誤,但對(duì)原理還是一知半解,本文主要介紹 python 中字符串處理的原理,附帶解決 json 文件輸出時(shí),顯示中文而非 unicode 問題。首先簡(jiǎn)要介紹字符串編碼的歷史,其次,講解 python 對(duì)于字符串的處理,及編碼的檢測(cè)與轉(zhuǎn)換,最后,介紹 python 爬蟲采取的 json 數(shù)據(jù)存入文件時(shí)中文輸出的問題。
參考書籍:Python網(wǎng)絡(luò)爬蟲從入門到實(shí)踐 by唐松
在python 2或者3 ,字符串編碼只有兩類 :
(1)通用的Unicode編碼;
(2)將Unicode轉(zhuǎn)化為某種類型的編碼,如UTF-8,GBK;
1、計(jì)算機(jī)歷史:
計(jì)算機(jī)只處理數(shù)字,因此處理文本時(shí),必須轉(zhuǎn)換成數(shù)字才行。
8位(bit)=1字節(jié)(byte)=256種不同狀態(tài)=從000000到111111;
1GB=1024M=1024(1024kb)=1024(1024(1024b));
ASCII編碼 是對(duì)應(yīng)英文字符與二進(jìn)制數(shù)字之間的關(guān)系;ASCII一共規(guī)定了128種,如大寫字母A是65,即01000001;可見一字母一字節(jié);
GB2312編碼 簡(jiǎn)體中文常見的編碼,兩個(gè)字節(jié)代表一個(gè)中文漢字 ,理論上256*256個(gè)編碼,即可表示65536種中文字;
各國編碼不同,為了各國能擴(kuò)平臺(tái)進(jìn)行文本的轉(zhuǎn)換與處理,Unicode就被作為統(tǒng)一碼或者單一碼。Unicode編碼通常是兩個(gè)字節(jié),unicode與ASCII編碼的區(qū)別,在于unicode在ASCII編碼前加了一個(gè)0,即字母A的ASCII編碼為01000001,unicode編碼即為0000000001000001;但英文字母其實(shí)只用一個(gè)字節(jié)就夠了,unicode編碼寫英文時(shí)多了一個(gè)字節(jié),浪費(fèi)存儲(chǔ)空間。因而unicode開發(fā)了通用轉(zhuǎn)換格式(Unicode Transformation Format(UTF)),常見的有utf-8或者utf-16;
要明白encode()和decode()的區(qū)別
encode()的作用是將Unicode編碼的字符串轉(zhuǎn)換為其他編碼格式。
例如: st1.encode("utf-8")
這句話的作用是將Unicode編碼的st1編碼為utf-8編碼的字符串
decode()的作用是把其他編碼格式的字符串轉(zhuǎn)換成Unicode編碼的字符串。
例如: st2.decode("utf-8")
這句話的作用是將utf-8編碼的字符串st2解碼為Unicode編碼的字符串
第二,除Unicode編碼的字符串以外,任何一種編碼的字符串要想轉(zhuǎn)換為其他編碼格式,必須先解碼后編碼
非Unicode編碼--> Unicode編碼-->非Unicode編碼
例如,utf-8編碼的字符串st想要轉(zhuǎn)換為gbk編碼的字符串,必須經(jīng)過以下步驟:
st=st.decode("utf-8") #解碼為Unicode編碼 st=st.encode("gbk") #從Unicode編碼編碼為gbk編碼
第三,我們經(jīng)常使用的utf-8編碼還分為有BOM的和無BOM的。
第四:關(guān)于json文件的中文編碼。用Python讀取Json文件時(shí)經(jīng)常用到j(luò)son.load()函數(shù),該函數(shù)對(duì)json文件的格式是有要求的
1)json文件是utf-8 without BOM編碼的,那么可以直接用json.load(filename)
函數(shù)讀取json文件的內(nèi)容
2)json文件是utf-8 with BOM編碼的,不能用json.load()
函數(shù)讀取,json.load()
不能正確識(shí)別
3)json文件時(shí)其他編碼的,比如gbk, 要把json文件的編碼格式作為一個(gè)參數(shù)傳給json.load()
:
eg. json.load(filename,"gbk")
第五,怎么查看并且設(shè)置自己文件的編碼呢。
介紹一個(gè)個(gè)人比較喜歡的工具"Nodtepad++",隨便一個(gè)軟件管家里就與一鍵安裝。
用這個(gè)工具你可以方便的查看自己的文件的當(dāng)前編碼,并可以輕松轉(zhuǎn)換成任意其他編碼格式
2、python字符編碼
參考地址:http://www.dbjr.com.cn/article/139878.htm
(1)encode的作用是,將unicode對(duì)象編碼成其他編碼的字符串,str.encode('utf-8'),編碼成UTF-8;(2)decode的作用是將其他編碼的字符串轉(zhuǎn)換成Unicode編碼,str.decode('UTF-8');
- import chardet 查閱具體的編碼類型,chardet.detect(str),但是str不能是unicode編碼類型,但是該方法 不接受 本來已經(jīng)是unicode的編碼的 參數(shù),會(huì)有TypeError: Expected object of type bytes or bytearray, got: <type 'unicode'>錯(cuò)誤;
- 作為統(tǒng)一標(biāo)準(zhǔn),unicode不能再被解碼,如果UTF-8想轉(zhuǎn)至其他非unicode,則必須(2)先decode 到unicode,在encode到其他非unicode的編碼。
爬取網(wǎng)頁時(shí),可在F12 elements meta中查看網(wǎng)頁編碼方式,如圖:
(2)中文,Python中的字典能夠被序列化到j(luò)son文件中存入json
with open("anjuke_salehouse.json","w",encoding='utf-8') as f: json.dump(all_house,f,ensure_ascii=False,sort_keys=True, indent=4); print(u'加載入文件完成...');
存儲(chǔ)數(shù)據(jù)如圖:
- dump()的第一個(gè)參數(shù)是要序列化的對(duì)象,第二個(gè)參數(shù)是打開的文件句柄,注意文件打開open()時(shí)加上以UTF-8編碼打開,在dump()的時(shí)候也加上ensure_ascii=False,不然會(huì)變成ascii碼寫到j(luò)son文件中json.dump(all_house,f,ensure_ascii=False,sort_keys=True, indent=4)
json.dumps()/json.loads()等用法
json_str = json.dumps(all_house,ensure_ascii=False); #all——books 為列表、字典等python自帶的數(shù)據(jù)結(jié)構(gòu),將其寫成json #print json_str; #[{"brokername": "王東宇"},{},{}] new_dict = json.loads(json_str);#主要是讀json文件時(shí),需要用到 #print new_dict; #{u'house_area': u'95', u'build_year': u'2005'}
- json.dumps() 是將一個(gè)Python數(shù)據(jù)結(jié)構(gòu)轉(zhuǎn)換為一個(gè)JSON編碼的字符串,
{"name": "xiaoming"}
json.loads() 是將一個(gè)JSON編碼的字符串(字典形式)轉(zhuǎn)換為一個(gè)Python數(shù)據(jù)結(jié)構(gòu),{u'name': u'xiaoming'}
dumps轉(zhuǎn)化后鍵與值都變成了雙引號(hào),而在loads后變成python變量時(shí),元素都變成了單引號(hào),并且字符串前加多了個(gè)u。
一般要求當(dāng)要字符串通過loads轉(zhuǎn)為python數(shù)據(jù)類型時(shí),得外層用單引號(hào),里面元素key和value用雙引號(hào)。
- sort_keys:根據(jù)key排序
dump與dumps的區(qū)別
dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding='utf-8', default=None, sort_keys=False, **kw);
dump將一個(gè)對(duì)象序列化存入文件,dump需要一個(gè)類似于文件指針的參數(shù)(并不是真的指針,可稱之為類文件對(duì)象),可以與文件操作結(jié)合,也就是說可以將dict轉(zhuǎn)成str存入文件中,如json.dump(all_house,f,ensure_ascii=False,sort_keys=True, indent=4)
中的f表示一個(gè)數(shù)據(jù)待寫入的json文件句柄;dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, encoding='utf-8', default=None, sort_keys=False, **kw);而dumps(str)
直接給的是str,也就是直接將字典轉(zhuǎn)成str,無需寫入文件,類似一個(gè)數(shù)據(jù)格式的轉(zhuǎn)換方法,將python字符串轉(zhuǎn)成json字典。- 所以dumps是將dict轉(zhuǎn)化成str格式,loads是將str轉(zhuǎn)化成dict格式。
dump和load也是類似的功能,只是與文件操作結(jié)合起來了。
(3)中文存入txt
f=open('net_saving_data.txt','w',encoding='utf-8'); for item in all_house: # house_area=item['house_area']; # price=item['price']; output='\t'.join([str(item['house_area']),str(item['price']),str(item['build_year']),str(item['house_title'])]); f.write(output); f.write('\n'); f.close();
- 在2.7.15版本的python中,提示錯(cuò)誤TypeError: 'encoding' is an invalid keyword argument for this function,無法傳入encoding的參數(shù),但是在3.7版本可傳入encoding='utf-8'參數(shù),即可對(duì) txt進(jìn)行中文寫入。
!!NOTE
- 中文寫入txt、json文件是無非就是open()文件時(shí),需要添加utf-8,dump()時(shí),需要添加ensure_ascii=False,防止ascii編碼,但是剛開始因?yàn)閜ython版本是2.7.15,不是3.7,導(dǎo)致存儲(chǔ)不成功的時(shí)候,一直以為是代碼的問題。所以最后發(fā)現(xiàn)就是版本的問題,也挺傷的。網(wǎng)上關(guān)于中文這個(gè)編碼問題有很多,但是他們都沒有強(qiáng)調(diào)python版本的問題!??!其他3.xx的版本沒有試過。
- 讀取網(wǎng)頁數(shù)據(jù)的時(shí)候,查看網(wǎng)頁的charset,及chardet庫對(duì)編碼類型的查詢,及時(shí)進(jìn)行decode和encode的編碼轉(zhuǎn)化,應(yīng)該就能避免很多編碼問題了。其他的坑以后踩了再補(bǔ)吧。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
對(duì)dataframe進(jìn)行列相加,行相加的實(shí)例
今天小編就為大家分享一篇對(duì)dataframe進(jìn)行列相加,行相加的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-06-06python實(shí)現(xiàn)按行切分文本文件的方法
這篇文章主要介紹了python實(shí)現(xiàn)按行切分文本文件的方法,涉及Python利用shell命令操作文本文件的相關(guān)技巧,需要的朋友可以參考下2016-04-04Python 的七個(gè)HTTP請(qǐng)求庫對(duì)比小結(jié)
本文主要介紹了Python 的七個(gè)HTTP請(qǐng)求庫對(duì)比小結(jié),文中通過圖表,示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06python selenium登錄豆瓣網(wǎng)過程解析
這篇文章主要介紹了python selenium登錄豆瓣網(wǎng)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-08-08解決Pyinstaller打包為可執(zhí)行文件編碼錯(cuò)誤的問題
這篇文章主要介紹了解決Pyinstaller打包為可執(zhí)行文件編碼錯(cuò)誤的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03python通過wxPython打開一個(gè)音頻文件并播放的方法
這篇文章主要介紹了python通過wxPython打開一個(gè)音頻文件并播放的方法,實(shí)例分析了wxPython操作音頻文件的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03python實(shí)現(xiàn)Virginia無密鑰解密
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)Virginia無密鑰解密,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-03-03python將pandas datarame保存為txt文件的實(shí)例
今天小編就為大家分享一篇python將pandas datarame保存為txt文件的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-02-02