Python 转换文本编码实现解析
最近在做周报的时候,需要把csv文本中的数据提取出来制作表格后生产图表。
在获取csv文本内容的时候,基本上都是用withopen(filename,encoding='UTF-8')asf:来打开csv文本,但是实际使用过程中发现有些csv文本并不是utf-8格式,从而导致程序在run的过程中报错,每次都需要手动去把该文本文件的编码格式修改成utf-8,再次来run该程序,所以想说:直接在程序中判断并修改文本编码。
基本思路:先查找该文本是否是utf-8的编码,如果不是则修改为utf-8编码的文本,然后再处理。
python有chardet库可以查看到文本的encoding信息:
detect函数只需要一个非unicode字符串参数,返回一个字典(例如:{'encoding':'utf-8','confidence':0.99})。该字典包括判断到的编码格式及判断的置信度。
importchardet defget_encode_info(file): withopen(file,'rb')asf: returnchardet.detect(f.read())['encoding']
不过这个在从处理小文件的时候性能还行,如果文本稍微过大就很慢了,目前我本地的csv文件是近200k,就能明显感觉到速度过慢了,效率低下。不过chardet库中提供UniversalDetector对象来处理:创建UniversalDetector对象,然后对每个文本块重复调用其feed方法。如果检测器达到了最小置信阈值,它就会将detector.done设置为True。
一旦您用完了源文本,请调用detector.close(),这将完成一些最后的计算,以防检测器之前没有达到其最小置信阈值。结果将是一个字典,其中包含自动检测的字符编码和置信度(与charde.test函数返回的相同)。
fromchardet.universaldetectorimportUniversalDetector defget_encode_info(file): withopen(file,'rb')asf: detector=UniversalDetector() forlineinf.readlines(): detector.feed(line) ifdetector.done: break detector.close() returndetector.result['encoding']
在做编码转换的时候遇到问题:UnicodeDecodeError:'charmap'codeccan'tdecodebyte0x90inposition178365:charactermapsto
defread_file(file): withopen(file,'rb')asf: returnf.read() defwrite_file(content,file): withopen(file,'wb')asf: f.write(content) defconvert_encode2utf8(file,original_encode,des_encode): file_content=read_file(file) file_decode=file_content.decode(original_encode)#-->此处有问题 file_encode=file_decode.encode(des_encode) write_file(file_encode,file)
这是由于byte字符组没解码好,要加另外一个参数errors。官方文档中写道:
bytearray.decode(encoding=”utf-8”,errors=”strict”)
Returnastringdecodedfromthegivenbytes.Defaultencodingis'utf-8'.errorsmaybegiventosetadifferenterrorhandlingscheme.Thedefaultforerrorsis'strict',meaningthatencodingerrorsraiseaUnicodeError.Otherpossiblevaluesare'ignore','replace'andanyothernameregisteredviacodecs.register_error(),seesectionErrorHandlers.Foralistofpossibleencodings,seesectionStandardEncodings.
意思就是字符数组解码成一个utf-8的字符串,可能被设置成不同的处理方案,默认是‘严格'的,有可能抛出UnicodeError,可以改成‘ignore','replace'就能解决。
所以将此行代码file_decode=file_content.decode(original_encode)修改成file_decode=file_content.decode(original_encode,'ignore')即可。
完整代码:
fromchardet.universaldetectorimportUniversalDetector defget_encode_info(file): withopen(file,'rb')asf: detector=UniversalDetector() forlineinf.readlines(): detector.feed(line) ifdetector.done: break detector.close() returndetector.result['encoding'] defread_file(file): withopen(file,'rb')asf: returnf.read() defwrite_file(content,file): withopen(file,'wb')asf: f.write(content) defconvert_encode2utf8(file,original_encode,des_encode): file_content=read_file(file) file_decode=file_content.decode(original_encode,'ignore') file_encode=file_decode.encode(des_encode) write_file(file_encode,file) if__name__=="__main__": filename=r'C:\Users\danvy\Desktop\Automation\testdata\test.csv' file_content=read_file(filename) encode_info=get_encode_info(filename) ifencode_info!='utf-8': convert_encode2utf8(filename,encode_info,'utf-8') encode_info=get_encode_info(filename) print(encode_info)
参考:https://chardet.readthedocs.io/en/latest/usage.html
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。