使CSV一个新的列表,而无需使用熊猫:返回的UnicodeDecodeError

问题描述 投票:1回答:1

我试图做一个新的列表在我现有的csv文件(不使用熊猫)。这里是我的代码:

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

任何人都可以让我知道我做错了什么?

python python-3.x csv encoding
1个回答
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编解码器可能是最有可能被用来作为Microsoft Excel中的Mac used Mac Roman to create CSV files很长一段时间。然而,这并不重要,任何的6都会在这里工作。

你可能想,如果你想打出风格和体裁列(真正的流派和风格的柱子,如果这些是从Discogs拍摄),以取代那些U + 00A0非换空间。

© www.soinside.com 2019 - 2024. All rights reserved.