忽略 CSV 中的 UTF-8 解码错误

问题描述 投票:0回答:2

我有一个 CSV 文件(我无法控制)。这是连接多个 CSV 文件的结果。该文件的大部分内容都是 UTF-8,但其中一个文件的字段的编码格式类似于 Windows-1251。

我实际上只关心包含 URL 的字段之一(因此它是有效的 ASCII/UTF-8)。

如果我只关心一个我知道是 ASCII 的字段,如何忽略其他 CSV 字段中的解码错误?或者,对于更有用的解决方案,如果存在编码错误,如何更改 CSV 文件每一行的编码?

python utf-8 character-encoding
2个回答
1
投票

csv.reader
csv.DictReader
将字符串列表(行列表)作为输入,而不仅仅是文件对象。

因此,以二进制模式打开文件 (

mode="rb"
),找出每一行的编码,使用该编码解码该行并将其附加到列表中,然后在该列表上调用
csv.reader

一个简单的启发式方法是尝试将每一行读取为 UTF-8,如果得到

UnicodeDecodeError
,请尝试将其解码为其他编码。如果您无法将其解码为 UTF-8,我们可以通过使用
chardet
(使用
pip install chardet
安装它)来猜测每行的编码,从而使其更加通用,而不是硬编码要回退的编码上:

import codec

my_csv = "some/path/to/your_file.csv"

lines = []
with open(my_csv, "rb") as f:
    for line in f:
        detected_encoding = chardet.detect(line)["encoding"]
        try:
            line = line.decode("utf-8")
        except UnicodeDecodeError as e:
            line = line.decode(detected_encoding)
        lines.append(line)

reader = csv.DictReader(lines)
for row in reader:
    do_stuff(row)

如果您do只想对后备编码进行硬编码并且不想使用

chardet
(有充分的理由不这样做,它并不总是准确的),您可以将变量
detected_encoding
替换为
"Windows-1251"
或者在上面的代码中任何你想要的编码。

这当然并不完美,因为仅仅因为一行使用某种编码成功解码并不意味着它实际上正在使用该编码。如果您不需要多次执行此操作,最好执行一些操作,例如打印出每一行及其检测到的编码,并尝试手动找出一种编码的开始位置和另一种编码的结束位置。最终,这里追求的正确策略可能是尝试逆转导致输入损坏的步骤(连接文件),然后正确地重新执行(通过在连接之前将它们标准化为相同的编码)。

在我的例子中,我计算了有多少行被检测为哪种编码

import chardet from collections import Counter my_csv_file = "some_file.csv" with open(my_csv_file, "rb") as f: encodings = Counter(chardet.detect(line)["encoding"] for line in f) print(encodings)
并意识到我的整个文件实际上是用其他第三种编码进行编码的。在整个文件上运行 

chardet

 检测到错误的编码,但在每一行上运行它检测到一堆编码,第二个最常见的编码(在 
ascii
 之后)是我需要用来读取整个文件的正确编码。所以最终我需要的是

with open(my_csv, encoding="latin_1") as f: reader = csv.DictReader(f) for row in reader: do_stuff(row)


您可以尝试使用

紧凑编码检测库而不是chardet

。 Google Chrome 就是使用的,所以也许它会工作得更好,但它是用 C++ 而不是 Python 编写的。


0
投票
我找到了更短的解决方案,只需使用正确的编码和

errors='ignore'

打开文件,有效地丢弃无法解码的字符:

csv_file = open(sys.argv[2], encoding='utf-8', errors='ignore') csv_reader = csv.reader(csv_file, delimiter=',')
    
© www.soinside.com 2019 - 2024. All rights reserved.