python中⽂编码与json中⽂输出问题详解
前⾔
python2.x版本的字符编码有时让⼈很头疼,遇到问题,⽹上⽅法可以解决错误,但对原理还是⼀知半解,本⽂主要介绍python 中字符串处理的原理,附带解决 json ⽂件输出时,显⽰中⽂⽽⾮ unicode 问题。⾸先简要介绍字符串编码的历史,其次,讲解 python 对于字符串的处理,及编码的检测与转换,最后,介绍 python 爬⾍采取的 json 数据存⼊⽂件时中⽂输出的问题。
参考书籍:Python⽹络爬⾍从⼊门到实践 by唐松
在python 2或者3 ,字符串编码只有两类:
(1)通⽤的Unicode编码;
(2)将Unicode转化为某种类型的编码,如UTF-8,GBK;
1、计算机历史:
计算机只处理数字,因此处理⽂本时,必须转换成数字才⾏。
8位(bit)=1字节(byte)=256种不同状态=从000000到111111;
1GB=1024M=1024(1024kb)=1024(1024(1024b));
ASCII编码是对应英⽂字符与⼆进制数字之间的关系;ASCII⼀共规定了128种,如⼤写字母A是65,即01000001;可见⼀字母⼀字节;
GB2312编码简体中⽂常见的编码,两个字节代表⼀个中⽂汉字,理论上256*256个编码,即可表⽰65536种中⽂字;
各国编码不同,为了各国能扩平台进⾏⽂本的转换与处理,Unicode就被作为统⼀码或者单⼀码。Unicode编码通常是两个字节,unicode与ASCII编码的区别,在于unicode在ASCII编码前加了⼀个0,即字母A的ASCII编码为01000001,unicode编码即为0000000001000001;但英⽂字母其实只⽤⼀个字节就够了,unicode编码写英⽂时多了⼀个字节,浪费存储空间。因⽽unicode开发了通⽤转换格式(Unicode Transformation Format(UTF)),常见的有utf-8或者utf-16;
要明⽩encode()和decode()的区别
encode()的作⽤是将Unicode编码的字符串转换为其他编码格式。
例如:de("utf-8") 这句话的作⽤是将Unicode编码的st1编码为utf-8编码的字符串
decode()的作⽤是把其他编码格式的字符串转换成Unicode编码的字符串。
例如:st2.decode("utf-8") 这句话的作⽤是将utf-8编码的字符串st2解码为Unicode编码的字符串
第⼆,除Unicode编码的字符串以外,任何⼀种编码的字符串要想转换为其他编码格式,必须先解码后编码
⾮Unicode编码--> Unicode编码-->⾮Unicode编码
例如,utf-8编码的字符串st想要转换为gbk编码的字符串,必须经过以下步骤:
st=st.decode("utf-8") #解码为Unicode编码
de("gbk") #从Unicode编码编码为gbk编码
第三,我们经常使⽤的utf-8编码还分为有BOM的和⽆BOM的。
第四:关于json⽂件的中⽂编码。⽤Python读取Json⽂件时经常⽤到json.load()函数,该函数对json⽂件的格式是有要求的1)json⽂件是utf-8 without BOM编码的,那么可以直接⽤json.load(filename)函数读取json⽂件的内容
2)json⽂件是utf-8 with BOM编码的,不能⽤json.load()函数读取,json.load()不能正确识别
3)json⽂件时其他编码的,⽐如gbk,要把json⽂件的编码格式作为⼀个参数传给json.load() :
eg. json.load(filename,"gbk")
第五,怎么查看并且设置⾃⼰⽂件的编码呢。
介绍⼀个个⼈⽐较喜欢的⼯具"Nodtepad++",随便⼀个软件管家⾥就与⼀键安装。
⽤这个⼯具你可以⽅便的查看⾃⼰的⽂件的当前编码,并可以轻松转换成任意其他编码格式
2、python字符编码
(1)encode的作⽤是,将unicode对象编码成其他编码的字符串,de('utf-8'),编码成UTF-8;(2)decode的作⽤是将其他编码的字符串转换成Unicode编码,str.decode('UTF-8');
import chardet 查阅具体的编码类型,chardet.detect(str),但是str不能是unicode编码类型,但是该⽅法不接受本来已经是unicode的编码的参数,会有TypeError: Expected object of type bytes or bytearray, got: <type 'unicode'>错误;
作为统⼀标准,unicode不能再被解码,如果UTF-8想转⾄其他⾮unicode,则必须(2)先decode 到unicode,在encode到其他⾮unicode的编码。
爬取⽹页时,可在F12 elements meta中查看⽹页编码⽅式,如图:
(2)中⽂,Python中的字典能够被序列化到json⽂件中存⼊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'加载⼊⽂件完成...');
存储数据如图:
dump()的第⼀个参数是要序列化的对象,第⼆个参数是打开的⽂件句柄,注意⽂件打开open()时加上以UTF-8编码打开,在dump()的时候也加上ensure_ascii=False,不然会变成ascii码写到json⽂件中
json.dump(all_house,f,ensure_ascii=False,sort_keys=True, indent=4)数字转unicode编码
json.dumps()/json.loads()等⽤法
json_str = json.dumps(all_house,ensure_ascii=False); #all——books 为列表、字典等python⾃带的数据结构,将其写成json
#print json_str; #[{"brokername": "王东宇"},{},{}]
new_dict = json.loads(json_str);#主要是读json⽂件时,需要⽤到
#print new_dict; #{u'house_area': u'95', u'build_year': u'2005'}
json.dumps() 是将⼀个Python数据结构转换为⼀个JSON编码的字符串,
{"name": "xiaoming"}
json.loads() 是将⼀个JSON编码的字符串(字典形式)转换为⼀个Python数据结构,{u'name': u'xiaoming'}
dumps转化后键与值都变成了双引号,⽽在loads后变成python变量时,元素都变成了单引号,并且字符串前加多了个u。
⼀般要求当要字符串通过loads转为python数据类型时,得外层⽤单引号,⾥⾯元素key和value⽤双引号。
sort_keys:根据key排序
dump与dumps的区别
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将⼀个对象序列化存⼊⽂件,dump需要⼀个类似于⽂件指针的参数(并不是真的指针,可称之为类⽂件对象),可以与⽂件操作结合,也就是说可以将dict转成str存⼊⽂件中,
如json.dump(all_house,f,ensure_ascii=False,sort_keys=True, indent=4)中的f表⽰⼀个数据待写⼊的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,也就是直接将字典转成str,⽆需写⼊⽂件,类似⼀个数据格式的转换⽅法,将python字符串转成json字典。
所以dumps是将dict转化成str格式,loads是将str转化成dict格式。
dump和load也是类似的功能,只是与⽂件操作结合起来了。
(3)中⽂存⼊txt
f=open('net_','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中,提⽰错误TypeError: 'encoding' is an invalid keyword argument for this function,⽆法传⼊encoding的参数,但是在3.7版本可传⼊encoding='utf-8'参数,即可对 txt进⾏中⽂写⼊。
!!NOTE
中⽂写⼊txt、json⽂件是⽆⾮就是open()⽂件时,需要添加utf-8,dump()时,需要添加ensure_ascii=False,防⽌ascii 编码,但是刚开始因为python版本是2.7.15,不是3.7,导致存储不成功的时候,⼀直以为是代码的问题。所以最后发现就是版本的问题,也挺伤的。⽹上关于中⽂这个编码问题有很多,但是他们都没有强调python版本的问题其他
<的版本没有试过。
读取⽹页数据的时候,查看⽹页的charset,及chardet库对编码类型的查询,及时进⾏decode和encode的编码转化,应该就能避免很多编码问题了。其他的坑以后踩了再补吧。
总结
以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,如果有疑问⼤家可以留⾔交流,谢谢⼤家对的⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论