Проблема с данными в кодировке Unicode в Python

Привет, сообщество StackOverflow.

Я довольно новый пользователь Python, поэтому заранее извините за глупость этого вопроса! Но я пытался исправить это часами, но до сих пор не понял.

Я пытаюсь импортировать большой набор данных текста, чтобы манипулировать им в Python.

Этот набор данных находится в формате .csv, и у меня возникли проблемы с его чтением из-за проблем с кодировкой.

Я пытался закодировать его в тексте UTF-8 с помощью notepad++. Я пробовал модуль csv.reader в Python.

Вот пример моего кода:

import csv
with open('twitter_test_python.csv') as csvfile:
    #for file5 in csvfile:
    #    file5.readline()
    #csvfile = csvfile.encode('utf-8')
    spamreader = csv.reader(csvfile, delimiter=str(','), quotechar=str('|')
    for row in spamreader:
        row = " ".join(row)
        row2= str.split(row)
    listsw = []
    for mots in row2:
        if mots not in sw:
            del mots
    print row2

Но когда я импортирую свои данные в Python, у меня все еще возникают проблемы с кодировкой (акценты и т. д.), независимо от того, какой метод я использую.

Как я могу закодировать свои данные, чтобы их можно было правильно прочитать с помощью Python?

Спасибо !


person Nahid O.    schedule 21.03.2016    source источник
comment
У меня все еще есть проблемы с кодировкой, это ровно ничего не значит! Скажите, что именно происходит и что ожидается.   -  person Serge Ballesta    schedule 21.03.2016
comment
Вот пример списка из моих данных: [uEn vrai j'en ai marre j'ai une poste \xe0 3min de chez moi et le postier il d\xe9cide de mettre mon colis dans une poste que je connais pas] .   -  person Nahid O.    schedule 21.03.2016
comment
Я хочу иметь это: [En vrai j'en ai marre j'ai une poste à 3min de chez moi et le postier il décide de mettre mon colis dans une poste que je connais pas]   -  person Nahid O.    schedule 21.03.2016
comment
Затем, pas de problème. Когда я набираю print u"En vrai j'en ai marre j'ai une poste \xe0 3min de chez moi et le postier il d\xe9cide de mettre mon colis dans une poste que je connais pas" в IDLE, я правильно получаю En vrai j'en ai marre j'ai une poste à 3min de chez moi et le postier il décide de mettre mon colis dans une poste que je connais pas. Это означает, что ваши данные представляют собой правильную строку юникода, содержащую правильные символы с акцентом юникода. Другими словами, у вас нет проблем с кодировкой при чтении данных, но они могут возникнуть при их отображении.   -  person Serge Ballesta    schedule 21.03.2016


Ответы (2)


csv документация содержит пример работы с юникодом:

import csv,codecs,cStringIO

class UTF8Recoder:
    def __init__(self, f, encoding):
        self.reader = codecs.getreader(encoding)(f)
    def __iter__(self):
        return self
    def next(self):
        return self.reader.next().encode("utf-8")

class UnicodeReader:
    def __init__(self, f, dialect=csv.excel, encoding="utf-8-sig", **kwds):
        f = UTF8Recoder(f, encoding)
        self.reader = csv.reader(f, dialect=dialect, **kwds)
    def next(self):
        '''next() -> unicode
        This function reads and returns the next line as a Unicode string.
        '''
        row = self.reader.next()
        return [unicode(s, "utf-8") for s in row]
    def __iter__(self):
        return self

class UnicodeWriter:
    def __init__(self, f, dialect=csv.excel, encoding="utf-8-sig", **kwds):
        self.queue = cStringIO.StringIO()
        self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
        self.stream = f
        self.encoder = codecs.getincrementalencoder(encoding)()
    def writerow(self, row):
        '''writerow(unicode) -> None
        This function takes a Unicode string and encodes it to the output.
        '''
        self.writer.writerow([s.encode("utf-8") for s in row])
        data = self.queue.getvalue()
        data = data.decode("utf-8")
        data = self.encoder.encode(data)
        self.stream.write(data)
        self.queue.truncate(0)

    def writerows(self, rows):
        for row in rows:
            self.writerow(row)

with open('twitter_test_python.csv','rb') as spamreader:
    reader = UnicodeReader(fin)
    for line in reader:
        #do stuff
        print line
person Alexey Smirnov    schedule 21.03.2016

Ответ Алексея Смирнова элегантен, но может быть немного сложен для новичка. Итак, позвольте мне привести пример ближе к коду в вопросе.

Когда вы читаете файлы с помощью Python 2, вы получаете содержимое как str, а не unicode. Вероятно, вы хотите преобразовать его как можно скорее. Однако в документации модуля csv говорится: "Эта версия модуля csv не поддерживает ввод Unicode». Таким образом, вы должны кодировать вывод csv.reader, а не ввод. Вставка его в ваш код приводит к:

import csv
with open('twitter_test_python.csv') as csvfile:
    spamreader = csv.reader(csvfile, delimiter=str(','), quotechar=str('|'))
    for row in spamreader:
        row = " ".join(row)
        row = unicode(row, encoding="utf-8")
        row2 = row.split()

Однако вы можете подумать, действительно ли вам нужно объединение ячеек только для того, чтобы снова разделить их. Без этого код выглядел бы следующим образом. Результат будет другим, если элементы списка содержат пробелы.

import csv
with open('twitter_test_python.csv') as csvfile:
    spamreader = csv.reader(csvfile, delimiter=str(','), quotechar=str('|'))
    for row in spamreader:
        row2 = list(unicode(cell, encoding="utf-8") for cell in row)

Если вы хотите записать что-то обратно в файл, вы должны сначала преобразовать unicode обратно в str, например unicode.encode("utf-8").

person jakun    schedule 21.03.2016
comment
Спасибо за ответ. Значит ли это, что я могу работать с данными, даже если они не очень хорошо выглядят в Python? - person Nahid O.; 21.03.2016
comment
Да, вы можете обрабатывать юникод с помощью python. Учитывая ваши новые комментарии, я предполагаю, что вы имеете в виду вывод print. Вас могут заинтересовать различия между str() и repr(). print использует str-представление. list использует для своего str-представления repr-представление своих элементов. Чтобы получить желаемый результат, используйте print "[" + ", ".join(row2) + "]". - person jakun; 21.03.2016