最近在做周报的时候,需要把csv文本中的数据提取出来制作表格后生产图表。

在获取csv文本内容的时候,基本上都是用with open(filename, encoding =\’UTF-8\’) as f:来打开csv文本,但是实际使用过程中发现有些csv文本并不是utf-8格式,从而导致程序在run的过程中报错,每次都需要手动去把该文本文件的编码格式修改成utf-8,再次来run该程序,所以想说:直接在程序中判断并修改文本编码。

基本思路:先查找该文本是否是utf-8的编码,如果不是则修改为utf-8编码的文本,然后再处理。

python有chardet库可以查看到文本的encoding信息:

detect函数只需要一个 非unicode字符串参数,返回一个字典(例如:{\’encoding\’: \’utf-8\’, \’confidence\’: 0.99})。该字典包括判断到的编码格式及判断的置信度。

  1. import chardet
  2. def get_encode_info(file):
  3. with open(file, \'rb\') as f:
  4. return chardet.detect(f.read())[\'encoding\']

 

不过这个在从处理小文件的时候性能还行,如果文本稍微过大就很慢了,目前我本地的csv文件是近200k,就能明显感觉到速度过慢了,效率低下。不过chardet库中提供UniversalDetector对象来处理:创建UniversalDetector对象,然后对每个文本块重复调用其feed方法。如果检测器达到了最小置信阈值,它就会将detector.done设置为True。一旦您用完了源文本,请调用detector.close(),这将完成一些最后的计算,以防检测器之前没有达到其最小置信阈值。结果将是一个字典,其中包含自动检测的字符编码和置信度(与charde.test函数返回的相同)。

  1. from chardet.universaldetector import UniversalDetector
  2. def get_encode_info(file):
  3. with open(file, \'rb\') as f:
  4. detector = UniversalDetector()
  5. for line in f.readlines():
  6. detector.feed(line)
  7. if detector.done:
  8. break
  9. detector.close()
  10. return detector.result[\'encoding\']

 

在做编码转换的时候遇到问题:UnicodeDecodeError: \’charmap\’ codec can\’t decode byte 0x90 in position 178365: character maps to <undefined>

  1. def read_file(file):
  2. with open(file, \'rb\') as f:
  3. return f.read()
  4. def write_file(content, file):
  5. with open(file, \'wb\') as f:
  6. f.write(content)
  7. def convert_encode2utf8(file, original_encode, des_encode):
  8. file_content = read_file(file)
  9. file_decode = file_content.decode(original_encode) #-->此处有问题
  10. file_encode = file_decode.encode(des_encode)
  11. write_file(file_encode, file)

 

这是由于byte字符组没解码好,要加另外一个参数errors。官方文档中写道:

bytearray.decode(encoding=”utf-8”, errors=”strict”)

Return a string decoded from the given bytes. Default encoding is \’utf-8\’. errors may be given to set a different error handling scheme. The default for errors is \’strict\’, meaning that encoding errors raise a UnicodeError. Other possible values are \’ignore\’, \’replace\’ and any other name registered via codecs.register_error(), see section Error Handlers. For a list of possible encodings, see section Standard Encodings.

意思就是字符数组解码成一个utf-8的字符串,可能被设置成不同的处理方案,默认是‘严格’的,有可能抛出UnicodeError,可以改成‘ignore’,’replace’就能解决。

所以将此行代码file_decode = file_content.decode(original_encode)修改成file_decode = file_content.decode(original_encode,\’ignore\’)即可。

完整代码:

  1. from chardet.universaldetector import UniversalDetector
  2. def get_encode_info(file):
  3. with open(file, \'rb\') as f:
  4. detector = UniversalDetector()
  5. for line in f.readlines():
  6. detector.feed(line)
  7. if detector.done:
  8. break
  9. detector.close()
  10. return detector.result[\'encoding\']
  11. def read_file(file):
  12. with open(file, \'rb\') as f:
  13. return f.read()
  14. def write_file(content, file):
  15. with open(file, \'wb\') as f:
  16. f.write(content)
  17. def convert_encode2utf8(file, original_encode, des_encode):
  18. file_content = read_file(file)
  19. file_decode = file_content.decode(original_encode,\'ignore\')
  20. file_encode = file_decode.encode(des_encode)
  21. write_file(file_encode, file)
  22. if __name__ == "__main__":
  23. filename = r\'C:\Users\danvy\Desktop\Automation\testdata\test.csv\'
  24. file_content = read_file(filename)
  25. encode_info = get_encode_info(filename)
  26. if encode_info != \'utf-8\':
  27. convert_encode2utf8(filename, encode_info, \'utf-8\')
  28. encode_info = get_encode_info(filename)
  29. print(encode_info)

 参考:https://chardet.readthedocs.io/en/latest/usage.html

  

版权声明:本文为danvy原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/danvy/p/11417782.html