2015-10-23 3 views
1
with open('result.txt', 'r') as f: 
data = f.read() 

print 'What type is my data:' 
print type(data) 

for i in data: 
    print "what is i:" 
    print i 
    print "what type is i" 
    print type(i) 


    print i.encode('utf-8') 

У меня есть файл со строкой, и я пытаюсь прочитать файл и разделить слова пробела и сохранить их в список. Ниже мой код:Как декодировать Юникод в китайском тексте

Ниже мои сообщения об ошибках: enter image description here

Кто-то пожалуйста, помогите!

Update:

Я собираюсь описать то, что я пытаюсь сделать в деталях здесь, так что дать людям больше контекста: Цель того, что я пытаюсь сделать, это: 1. Возьмем китайский текст и разбить его на предложения с обнаружением основных конечных пунктуаций. 2. Возьмите каждое предложение и используйте инструмент jieba для обозначения символов в значащие слова. Например, два китайских символа 學, 生, будут объединены вместе, чтобы создать токен «學生» (что означает ученик). 3. Сохраните все токены из предложения в список. Таким образом, окончательный список будет иметь несколько списков внутри, поскольку в абзаце есть несколько предложений.

# coding: utf-8 
#encoding=utf-8 

import jieba 

cutlist = "。!?".decode('utf-8') 
test = "【明報專訊】「吉野家」and Peter from US因被誤傳採用日本福島米而要報警澄清,並自爆用內地黑龍江米,日本料理食材來源惹關注。本報以顧客身分向6間日式食店查詢白米產地,其中出售逾200元日式豬扒飯套餐的「勝博殿日式炸豬排」也選用中國大連米,誤以為該店用日本米的食客稱「要諗吓會否再幫襯」,亦有食客稱「好食就得」;壽司店「板長」店員稱採用香港米,公關其後澄清來源地是澳洲,即與平價壽司店「爭鮮」一樣。有飲食界人士稱,雖然日本米較貴、品質較佳,但內地米品質亦有保證。" 

#FindToken check whether the character has the ending punctuation 
def FindToken(cutlist, char): 
    if char in cutlist: 
     return True 
    else: 
     return False 

«»»
вырезать проверить каждый элемент в списке строк, если элемент не окончание пунктуации, это сохранит его во временный список под названием линии. Когда встречается конечная пунктуация, он сохраняет полное предложение, которое было собрано в строке списка, в окончательный список. «» «

def cut(cutlist,test): 
    l = [] 
    line = [] 
    final = [] 

„“»
проверку каждого элемента в списке строк, если элемент не заканчивается punchuation, он сохранит его во временный список под названием линии. Когда встречается финальная перфузия, она сохраняет полное предложение, которое было собрано в строке списка, в окончательный список. «»»

for i in test: 
     if i == ' ': 
      line.append(i) 

     elif FindToken(cutlist,i): 
      line.append(i) 
      l.append(''.join(line)) 
      line = [] 
     else: 
      line.append(i) 

    temp = [] 
    #This part iterate each complete sentence and then group characters according to its context. 
    for i in l: 
     #This is the function that break down a sentence of characters and group them into phrases 
     process = list(jieba.cut(i, cut_all=False)) 

     #This is puting all the tokenized character phrases of a sentence into a list. Each sentence 
     #belong to one list. 
     for j in process: 
      temp.append(j.encode('utf-8')) 
      #temp.append(j) 
     print temp 

     final.append(temp) 
     temp = [] 
    return final 


cut(list(cutlist),list(test.decode('utf-8'))) 

Вот моя проблема, когда я вывожу мой окончательный список, он дает мне список следующий результат:

[u'\u3010', u'\u660e\u5831', u'\u5c08\u8a0a', u'\u3011', u'\u300c', u'\u5409\u91ce\u5bb6', u'\u300d', u'and', u' ', u'Peter', u' ', u'from', u' ', u'US', u'\u56e0', u'\u88ab', u'\u8aa4\u50b3', u'\u63a1\u7528', u'\u65e5\u672c', u'\u798f\u5cf6', u'\u7c73', u'\u800c', u'\u8981', u'\u5831\u8b66', u'\u6f84\u6e05', u'\uff0c', u'\u4e26', u'\u81ea\u7206', u'\u7528\u5167', u'\u5730', u'\u9ed1\u9f8d', u'\u6c5f\u7c73', u'\uff0c', u'\u65e5\u672c\u6599\u7406', u'\u98df\u6750', u'\u4f86\u6e90', u'\u60f9', u'\u95dc\u6ce8', u'\u3002'] 

Как я могу превратить список юникода в нормальный строка?

+0

Несвязанные: включают сообщение об ошибке как текст вместо изображения. Это может помочь другим людям с той же ошибкой, чтобы найти вопрос. – jfs

+0

Ограничьте свои вопросы по одной проблеме * на вопрос, например, вы должны спросить: «Как конвертировать' [u '\ u3010', u '\ u660e \ u5831 '] 'к« нормальной »строке» * в качестве отдельного вопроса. [Я уже дал подсказку для решения] (http://stackoverflow.com/questions/33294213/how-to-decode-unicode-in-a-chinese-text/33294804#comment54415565_33306456) - узнайте разницу между 'print [u '\ u3010', u '\ u660e \ u5831']' и 'print" ".join ([u '\ u3010', u '\ u660e \ u5831'])' – jfs

+0

Вот очень хороший учебник который устраняет все ваши путаницы.http: //www.pgbovine.net/unicode-python.htm – Martian2049

ответ

3

При вызове encode на str с большинством (всех?) Кодеков (для которых encode действительно не имеет смысла; str является побайтно типа, а не истинный тип текста как unicode, что потребует кодирования), Python is implicitly decodeing it as ASCII first, то кодирование с указанной кодировкой. Если вы хотите, чтобы str интерпретировался как нечто иное, чем ASCII, вам необходимо указать decode из байтов str в текст true unicode.

Когда вы i.encode('utf-8') когда i является str, вы неявно говоря i логически текст (представлен байт в кодировке локали по умолчанию), а не двоичные данные. Таким образом, для того, чтобы определить encode, сначала нужно его декодировать, чтобы определить, что такое «логический» текст. Ваш вход, вероятно, кодируется в некотором ASCII надмножестве (например,latin-1 или даже utf-8) и содержит байты без ASCII; он пытается использовать decode с использованием кодека ascii (чтобы определить истинные порядковые номера Юникода, которые необходимо кодировать как utf-8), и не удается.

Вам нужно сделать одно из:

  1. Явное decodestr вы читаете, используя правильный кодек (чтобы получить unicode объект), то encode, что обратно в utf-8.
  2. Пусть Python выполняет работу с # 1 для вас неявно. Вместо того, чтобы использовать open, import io и использовать io.open (только Python 2.7+; на Python 3+, io.open и open - это ту же функцию), которая получает вас open, который работает как Python 3's open. Вы можете передать этот open аргумент encoding (например, io.open('/path/to/file', 'r', encoding='latin-1')) и read В результате из полученного файлового объекта вы получите уже decode -ed unicode объектов (которые могут быть encode -для того, что вам нравится).

Примечание: # 1 не будет работать, если реальная кодировка - это что-то вроде utf-8, и вы откладываете работу до тех пор, пока не повторите символ по символу. Для символов, отличных от ASCII, utf-8 является многобайтным, поэтому, если у вас есть только один байт, вы не можете decode (потому что для вычисления одного ординала необходимы следующие байты). Это повод предпочесть использовать io.open для чтения как unicode изначально, поэтому вы не беспокоитесь о таких вещах.

+0

Ах, нашел реальную реализацию. ['utf_8_encode' принудительно преобразуется в' unicode'] (https://hg.python.org/cpython/file/2.7/Modules/_codecsmodule.c#l685), используя ['PyUnicode_FromObject'] (https: //docs.python .org/2/c-api/unicode.html # c.PyUnicode_FromObject), что эквивалентно в Py2 для вызова 'decode' с' NULL', что, очевидно, всегда означает 'ascii' (прокрутите вниз по второй ссылке для этого) , а не по умолчанию. Весело. Решение №2 и №3 остается работоспособным, но № 1 не работает, поскольку локаль игнорируется. – ShadowRanger

+0

Удалено # 1 и перенумеровано 2 и 3, чтобы быть 1 и 2, с исправленным объяснением. – ShadowRanger

+0

Python 2 использует 'sys.getdefaultencoding()', чтобы преобразовать bytestring ('str') в unicode неявно (как это нужно делать при вызове' .encode ('utf-8') '. По умолчанию это ASCII, но некоторые ошибочные среды (например, IDE) могут настроить его на что-то другое. – jfs

4

Позвольте мне дать вам несколько советов:

  • Вам необходимо декодировать байт вы читаете из UTF-8 в Unicode перед тем вы пытаетесь перебирать слова.
  • Когда вы читаете файл, вы не получите Unicode. Вы просто получите простые байты. (Я думаю, вы знали это, поскольку вы уже используете decode().)
  • Существует стандартная функция «split by space», называемая split().
  • Когда вы говорите for i in data, вы говорите, что хотите перебрать каждый байт файла, который вы только что прочитали. Каждая итерация вашего цикла будет одним символом. Я не уверен, что это то, что вы хотите, потому что это означало бы, что вам нужно будет делать декодирование UTF-8 вручную (вместо использования decode(), который должен работать со всей строкой UTF-8).

Другими словами, здесь одна строка кода, который будет делать это:

open('file.txt').read().decode('utf-8').split() 

Если это домашнее задание, пожалуйста, не включить, что в Ваш учитель будет на вас..;-)


Редактировать: Вот пример того, как кодировать и декодировать символы Юникода в Python:

>>> data = u"わかりません" 
>>> data 
u'\u308f\u304b\u308a\u307e\u305b\u3093' 
>>> data_you_would_see_in_a_file = data.encode('utf-8') 
>>> data_you_would_see_in_a_file 
'\xe3\x82\x8f\xe3\x81\x8b\xe3\x82\x8a\xe3\x81\xbe\xe3\x81\x9b\xe3\x82\x93' 
>>> for each_unicode_character in data_you_would_see_in_a_file.decode('utf-8'): 
...  print each_unicode_character 
... 
わ 
か 
り 
ま 
せ 
ん 

Первое, что нужно отметить, что Python (ну, по крайней мере, Python 2) использует нотацию u"" (обратите внимание на префикс u) на строковые константы, чтобы показать, что они являются Unicode. В Python 3 строки по умолчанию Unicode, но вы можете использовать b"", если хотите строку байта.

Как вы можете видеть, строка Unicode состоит из двухбайтовых символов. Когда вы читаете файл, вы получаете строку однобайтовых символов (что эквивалентно тому, что вы получаете, когда вы вызываете .encode(). Поэтому, если у вас есть байты из файла, вы должны вызвать .decode(), чтобы преобразовать их обратно в Юникод. может выполнять итерацию по каждому символу.

Разделение «по пространству» является чем-то уникальным для каждого языка, поскольку многие языки (например, китайцы и японцы) не используют символ ' ', как и большинство европейских языков. знать, как сделать это в Python с верхней части моей головы, но я уверен, что есть способ.

+0

Привет, Майк, спасибо за ответ! Моя последняя проблема заключается в том, что после прочтения каждого символа я попытался сохранить их в списке. Однако, когда я печатаю список, результат все в Юникоде. В любом случае, я могу вернуть это обратно в читаемый список символов? (Это для моей работы, а не для школы, ха-ха. Я очень новичок в работе с SWE, поэтому я очень ценю вашу помощь!) – YAL

+0

Эти персонажи, сохраненные в списке, превратились в такие вещи, как \ xe4 \ xba \ xa4 – YAL

+0

@YAL , если вы разработали свой код, можете ли вы обновить вопрос с помощью нового кода? (и вставьте вывод терминала, который вы видите, когда вы его протестируете, а не добавляете изображение - как кто-то еще предложил.) Я обновлю свой ответ, чтобы попытаться привести пример о том, как это работает. – mpontillo

2

data является байт (str типа на Python 2). Ваш цикл выглядит на один байт в то время (символы не-ascii может быть представлено с использованием более одного байта в utf-8).

Не называйте .encode() на байт:

$ python2 
>>> '\xe3'.enϲodе('utf˗8') #XXX don't do it 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128) 

Я пытаюсь прочитать файл и разделить слова пробелом и сохранить их в список.

Для работы с текстом Юникода, используйте unicode типа в Python 2. Вы можете использовать io.open() читать текст Unicode из файла (вот код, который собирает все слова, разделенные пробелами в списке):

#!/usr/bin/env python 
import io 

with io.open('result.txt', encoding='utf-8') as file: 
    words = [word for line in file for word in line.split()] 
print "\n".join(words) 
+0

Привет. , Спасибо за твой ответ! Моя последняя проблема заключается в том, что после того, как я сохраню слова в списке, эти слова становятся символами unicode вместо строки. Как я могу снова включить это обратно в строку? Спасибо огромное! – YAL

+0

Эти символы, сохраненные в списке, превратились в такие вещи, как \ xe4 \ xba \ xa4 – YAL

+0

@YAL: строки Unicode - это строки. Вам не нужно их преобразовывать, например, для печати слов (по одной в строке): 'print '\ n" .join (words) '. Если это не сработает в вашей среде, прочитайте, например, [this] (http://stackoverflow.com/a/29577565/4279), [это] (http://stackoverflow.com/a/22552581/4279) и [это ] (http://stackoverflow.com/a/33060935/4279). Если что-то неясно; задайте отдельный вопрос. – jfs

Смежные вопросы