'utf-8'编解码器无法解码第4276个位置的字节0xa0:起始字节无效

42

我尝试读取并打印以下文件:txt.tsv (https://www.sec.gov/files/dera/data/financial-statement-and-notes-data-sets/2017q3_notes.zip)

根据美国证券交易委员会的说法,该数据集以单一编码形式提供,具体如下:

制表符分割值(.txt):utf-8编码、以制表符分隔、以\n结尾的行,第一行包含小写字段名称。

我的当前代码:

import csv

with open('txt.tsv') as tsvfile:
    reader = csv.DictReader(tsvfile, dialect='excel-tab')
    for row in reader:
        print(row)

所有尝试都以以下错误消息结束:

'utf-8'编解码器无法解码字节位置4276处的字节0xa0:起始字节无效

我有点困惑。 有人能帮我吗?


你能让我们看看你正在使用的文件吗? - dangee1705
3
还有,这是Python 2还是3?答案非常重要,因为在Python 2中,csv模块在处理非ASCII字符时会出现问题。 - ShadowRanger
我正在使用Python 3.6.0。 - Vital
1
哦嗯...重新阅读这个错误信息后,我非常确定问题出在您的输入文件上。该错误指示它正在尝试将其读取为utf-8格式,因此您的输入文件可能不符合所描述的格式。话虽如此,您提供的文件看起来完全符合要求(就我了解的范围内它是纯ASCII码;它使用了一些不寻常的ASCII控制字符,但它们都在ASCII范围内),因此我不确定您何时会看到\xa0字节。您是否有可能在使用该文件之前意外修改了它? - ShadowRanger
2
看下 Kopytok 的回答。如果我将编码更改为“windows-1252”,它就完美运行了。 - Vital
一个小提示:在处理类似CSV的东西时,应该将newline=''传递给open。而且,在这里使用excel_tab方言是错误的;它假设行结束符是\r\n,而文件实际上是\n结尾的。基于excel_tab定义自己的方言将是一个简单的解决方案,只需子类化它并设置类级变量lineterminator = '\n'即可。 - ShadowRanger
6个回答

68

文件中的编码格式为 'windows-1252'。请使用:

open('txt.tsv', encoding='windows-1252')

1
@Vital 最好向证券交易委员会咨询。 - koPytok
@ShadowRanger 编码检测器检测到了 cp-1252 编码,结果似乎是合法的。 - koPytok
4
这可能导致产生无效的结果。CP-1252可以轻松解码任何东西(音频数据、核心转储、Zip归档),并假装这些都是有效的文本。 - tripleee
1
我的 txt.tsv 下载经过初步检查,没有在问题所示的偏移量处发现 0xa0 字符,但有大量 0xa0 字符,这些字符显然代表硬空格,以及在一个表示货币指示器的位置上的 0xac 字符,以及 0xae,这显然是 ®‎ 符号。这几乎与 CP1252 或 ISO-8859-1(当然非常相似)一致,但 0xac 不符合任何一个。也许还可以参考 https://cdn.rawgit.com/tripleee/8bit/master/encodings.html#ac *(咳咳)*。 - tripleee
在我的情况下,我有一个文本文件,其中使用的是Windows CRLF而不是Unix LF。 - TBirkulosis
显示剩余2条评论

4
如果有人处理土耳其数据,我建议使用这行代码:
df = pd.read_csv("text.txt",encoding='windows-1254')

3
ds = pd.read_csv('/Dataset/test.csv', encoding='windows-1252') 

对我来说很好用,谢谢。


2

我也遇到了同样的问题,在使用latin1编码时解决了问题,请参考示例代码应用于您的代码库。如果上述解决方法无效,请尝试使用此方法。

df=pd.read_csv("../CSV_FILE.csv",na_values=missing, encoding='latin1')

2

如果输入中有一个杂散的'\xa0',那么它就不是UTF-8编码,就这样。

是的,你必须将其重新编码为UTF-8(参见:iconvrecode命令,或许多文本编辑器和IDE都可以实现),或者使用8位编码读取它(正如所有其他答案所建议的那样)。

你应该问自己的问题是 - 这个字符到底是什么(0xa0或160)? 在许多8位编码中,它是一个不间断的空格(就像HTML中的 )。对于至少一种DOS编码,它是一个带重音的“a”字符。这就是为什么你需要查看从8位编码解码后的结果。

顺便说一句,有时人们会说“UTF-8”,他们的意思是“大部分是ASCII,我猜”。如果它是一个不间断的空格,他们并没有那么远:

In [1]: '\xa0'.encode()
Out[1]: b'\xc2\xa0'

在编程中,额外添加一个前导 '\xc2' 字节可以解决问题。


1

我在处理 .csv 文件时遇到了相同的错误信息,以下方法对我有效:

     df = pd.read_csv('Text.csv',encoding='ANSI')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接