【问题标题】:Make a new list in CSV without using pandas: return UnicodeDecodeError在不使用熊猫的情况下在 CSV 中创建一个新列表:返回 UnicodeDecodeError
【发布时间】:2019-07-04 06:33:42
【问题描述】:

我正在尝试在我现有的 csv 文件中创建一个新列表(不使用 pandas)。 这是我的代码:

with open ('/Users/Weindependent/Desktop/dataset/albumlist.csv','r') as case0:
    reader = csv.DictReader(case0)
    album = []
    for row in reader:
        album.append(row)
print ("Number of albums is:",len(album))

CSV 文件是从Rolling Stone's Top 500 albums data set on data.world 下载的。

我的逻辑是创建一个名为专辑的空列表,并在此列表中包含所有记录。但是for row in reader这行好像有问题。

我得到的错误信息是:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xca in position 1040: invalid continuation byte

谁能告诉我我做错了什么?

【问题讨论】:

  • 这可能会有所帮助:stackoverflow.com/questions/12752313/…
  • 您正在读取的数据文件可能不是 UTF-8 编码的。您必须使用encoding="...." 指定不同的编码。使用什么编码,我们不能告诉你,抱歉。
  • 如何判断文件编码的类型?
  • 数据集从何而来?他们可能记录了这一点吗?
  • 由于您在 CSV 中存储了 1040 个字节直到遇到解码错误,因此文件也可能使用单字节编码进行编码,其中最流行的是 cp1252。先试试看吧。

标签: python python-3.x csv encoding


【解决方案1】:

您需要以正确的编解码器打开文件; UTF-8 不是正确的。数据集没有指定,但我确定最有可能的编解码器是mac_roman

with open ('/Users/Weindependent/Desktop/dataset/albumlist.csv', 'r', encoding='mac_roman') as case0:

original Kaggle dataset 懒得记录它,使用该集合的各种内核都只是破坏了编码。它显然是一个 8 位拉丁变体(大部分数据是 ASCII,带有一些单独的 8 位代码点)。

所以我分析了数据,发现只有两个这样的代码点在 9 行中:

>>> import re
>>> eightbit = re.compile(rb'[\x80-\xff]')
>>> with open('albumlist.csv', 'rb') as bindata:
...     nonascii = [l for l in bindata if eightbit.search(l)]
...
>>> len(nonascii)
9
>>> {c for l in nonascii for c in eightbit.findall(l)}
{b'\x89', b'\xca'}

0x89 字节只出现在一行中:

>>> sum(l.count(b'\x89') for l in nonascii)
1
>>> sum(l.count(b'\xca') for l in nonascii)
22
>>> next(l for l in nonascii if b'\x89' in l)
b'359,1972,Honky Ch\x89teau,Elton John,Rock,"Pop Rock,\xcaClassic Rock"\r\n'

这显然是Elton John's 1972 Honky Château album,所以0x89 字节必须代表U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX 代码点。

0xCA 字节似乎都代表了一个替代空格字符,它们都出现在流派和子流派列中的逗号后面(有一个专辑例外):

>>> import csv
>>> for row in csv.reader((l.decode('ascii', 'backslashreplace') for l in nonascii)):
...     for col in row:
...         if '\\' in col: print(col)
...
Reggae,\xcaPop,\xcaFolk, World, & Country,\xcaStage & Screen
Reggae,\xcaRoots Reggae,\xcaRocksteady,\xcaContemporary,\xcaSoundtrack
Electronic,\xcaStage & Screen
Soundtrack,\xcaDisco
Rock,\xcaBlues
Blues Rock,\xcaElectric Blues,\xcaHarmonica Blues
Garage Rock,\xcaPsychedelic Rock
Honky Ch\x89teau
Pop Rock,\xcaClassic Rock
Funk / Soul,\xcaFolk, World, & Country
Rock,\xcaPop
Stan Getz\xca/\xcaJoao Gilberto\xcafeaturing\xcaAntonio Carlos Jobim
Bossa Nova,\xcaLatin Jazz
Lo-Fi,\xcaIndie Rock

这些 0xCA 字节几乎肯定代表U+00A0 NO-BREAK SPACE 代码点。

通过这两个映射,您可以尝试确定哪些 8 位编解码器会产生相同的映射。我没有手动尝试all Python's codecs,而是使用Tripleee's 8-bit codec mapping 来查看哪些编解码器使用这些映射。只有两个:

  • 0x89

â‎ (U+00E2): mac_arabic, mac_croatian, mac_farsi, mac_greek, mac_iceland, mac_roman, mac_romanian, mac_turkish

  • 0xca

    ‎ (U+00A0): mac_centeuro, mac_croatian, mac_cyrillic, mac_greek, mac_iceland, mac_latin2, mac_roman, mac_romanian, mac_turkish

两组中都列出了 6 种编码:

>>> set1 = set('mac_arabic, mac_croatian, mac_farsi, mac_greek, mac_iceland, mac_roman, mac_romanian, mac_turkish'.split(', '))
>>> set2 = set('mac_centeuro, mac_croatian, mac_cyrillic, mac_greek, mac_iceland, mac_latin2, mac_roman, mac_romanian, mac_turkish'.split(', '))
>>> set1 & set2
{'mac_turkish', 'mac_iceland', 'mac_romanian', 'mac_greek', 'mac_croatian', 'mac_roman'}

其中,Mac OS Roman mac_roman 编解码器可能是最有可能长期用作 Mac 版 Microsoft Excel 的used Mac Roman to create CSV files。但是,这并不重要,这 6 个中的任何一个都可以在这里工作。

如果您想拆分流派和子流派列(如果这些列来自 Discogs,则实际上是流派和 style 列),您可能需要替换那些 U+00A0 不间断空格。

【讨论】:

    猜你喜欢
    • 2021-12-12
    • 2022-12-24
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 2011-04-09
    • 2017-10-17
    相关资源
    最近更新 更多