Игнорировать ошибки декодирования UTF-8 в CSV - PullRequest
1 голос
/ 19 сентября 2019

У меня есть файл CSV (который я не могу контролировать).Это результат объединения нескольких файлов CSV.Большая часть файла - UTF-8, но в одном из файлов, которые вошли в него, были поля, которые закодированы в том, что выглядит как Windows-1251.

Я на самом деле беспокоюсь только об одном из полей, которое содержит URL (так что это действительно ASCII / UTF-8).

Как игнорировать ошибки декодирования в других полях CSV, если я забочусь только об одном поле, которое, как я знаю, является ASCII?В качестве альтернативы, для более полезного решения, как изменить кодировку для каждой строки файла CSV, если есть ошибка кодирования?

1 Ответ

1 голос
/ 19 сентября 2019

Откройте файл в двоичном режиме (mode="rb") и попробуйте декодировать каждую строку как UTF-8.Если вы получите UnicodeDecodeError, декодируйте его как другую кодировку.Добавьте каждую декодированную строку в список, а затем вызовите csv.reader или csv.DictReader (оба они принимают списки строк, а не только файловые объекты).

Вместо жесткого кодирования, для которого требуется резервное кодирование, может быть лучше использовать chardet.detect из библиотеки chardet , чтобы угадать кодировку каждой строки, если вы не можете декодировать ее как UTF-8

import codec

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

lines = []
with open(my_csv, "rb") as f:
    for line in f:
        detected_encoding = codec.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)

Если вы хотите жестко закодировать резервную кодировку и не хотите использовать chardet (есть веская причина, не всегда это точно), вы можете просто заменить переменную detected_encoding с "Windows-1251" в приведенном выше коде.

Вы можете установить chardet с

pip install chardet

Вы можете проверить свои предположения о том, какие строки закодированы с какой кодировкой, выполнив

from collections import Counter

with open(my_csv_file, "rb") as f:
   encodings = Counter(chardet.detect(line)["encoding"] for line in f)

print(encodings)

В моем случае запуск chardet для всего файла обнаружил неправильную кодировку.Запуск его в каждой строке обнаруживал кучу кодировок, но второй наиболее распространенной (после ascii) была правильная кодировка, которую мне нужно было использовать для чтения всего файла.


Google Chrome использует Compact Encoding Detection библиотека для определения кодировки, и она может быть более надежной, чем chardet, но она написана на C ++ вместо Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...