无法解码CSV文件(UTF-8):从邮件链接提取CSV转字典遇编码问题
问题:从邮件自动下载链接提取CSV并转换为字典
尝试从邮件中的链接提取CSV文件并转换为字典,但点击链接会自动下载文件,尝试了urllib和requests后出现乱码,具体情况如下:
尝试的代码与乱码现象
urllib相关尝试
最初使用urllib读取链接内容:
response = urllib.request.urlopen(<link_to_download_file>) for l in response.readlines(): #print(l) print(l.decode('utf-8', 'ignore'))
结合csv模块的代码:
lines = [l.decode('utf-8') for l in response.readlines()] cr = csv.reader(lines) for row in cr: print(row)
打印的原始字节内容:
b'PK\x03\x04\x14\x00\x08\x00\x08\x00c\x94mU\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00xl/theme/theme1.xml\xedYM\x8f\xdb6\x1a\xbe\xef\xaf xOl\xcfx&3B\x94"\xf6\xd8\xc9n2\xed`\xc6I\x91\xe3k\x89\x96\x98\xa1H\x81\xa4g\xc6\xb7"=.\xb0@\xd1\x0f\xf4R\xa0\xb7\x1e\x16\xdb\x06h\x80^\xb2\xbf&\xbbY\xecf\x81\xfc\x85\x05IQ\x16m9\x99|\x14\xc5\xa2\x99CbI\xcf\xf3~\xbf/I\xe9\xfaG\x17\x05CgD**x\x8c{W\xbb\x18\x11\x9e\x88\x94\xf2,\xc6\xf7&\xe3+{\x18)\r<\x05&8\x89\xf1\x82(\xfc\xd1\x8d?\\\x87H\xe7\xa4 \xe8\xa2`\\E\x10\xe3\\\xeb2\xeatT\x92\x93\x02\xd4UQ\x12~Q\xb0\x99\x90\x05huU\xc8\xac\x93J8\xa7<+Xg\xab\xdb\xdd\xed\x14@9F\x1c\n'
解码后的乱码字符串:
<♣&8(э?\H `\E►\2tT☻UQ↕~Q♣huUȬJ8<+Xg¶@9F∟2`IkHgƷ"=.@R▲▬♠h^&Yf♣IQ▬m9|¶ŢCbI~/IG↨♣CgD**x{W↑◄,&+{↑)
requests替代尝试
改用requests模块后依旧乱码:
with requests.Session() as s: download = s.get(link) decoded_content = download.content.decode('utf-8') cr = csv.reader(decoded_content.splitlines(), delimiter=',') my_list = list(cr) for row in my_list: print(row)
原因分析
开头的PK字节是ZIP压缩文件的标识,说明链接下载的不是纯CSV文件,而是包含CSV的压缩包,直接用utf-8解码自然会出现乱码。
解决方案:解压ZIP后读取CSV
需要先将下载的ZIP内容解压,再读取其中的CSV文件,以下是两种模块的实现代码:
使用urllib + zipfile处理
import urllib.request import zipfile from io import BytesIO import csv # 替换为实际下载链接 response = urllib.request.urlopen("<link_to_download_file>") # 将字节内容转为可读取的文件对象 zip_content = BytesIO(response.read()) with zipfile.ZipFile(zip_content, 'r') as zip_ref: # 先打印压缩包内的所有文件名,找到目标CSV print("压缩包内文件列表:", zip_ref.namelist()) # 替换为压缩包内实际的CSV文件名 with zip_ref.open('target.csv') as csv_file: # 读取为字典列表 dict_reader = csv.DictReader(csv_file) csv_dict_list = list(dict_reader) print("转换后的字典列表:", csv_dict_list)
使用requests + zipfile处理
import requests import zipfile from io import BytesIO import csv # 替换为实际下载链接 with requests.Session() as s: download = s.get("<link_to_download_file>") zip_content = BytesIO(download.content) with zipfile.ZipFile(zip_content, 'r') as zip_ref: print("压缩包内文件列表:", zip_ref.namelist()) # 替换为压缩包内实际的CSV文件名 with zip_ref.open('target.csv') as csv_file: dict_reader = csv.DictReader(csv_file) csv_dict_list = list(dict_reader) print("转换后的字典列表:", csv_dict_list)
注意事项
- 先通过
zip_ref.namelist()查看压缩包内的文件,找到正确的CSV文件名替换代码中的target.csv - 如果读取CSV时仍有乱码,可以尝试指定编码,比如
csv.DictReader(csv_file, encoding='gbk'),根据实际文件编码调整
内容的提问来源于stack exchange,提问作者musical_ant
相关产品推荐
相关产品推荐

