2016-01-14 2 views
-1

Я хочу сохранить строку в новом txt-файле.Почему я не могу сохранить файл в формате utf-8

Кодирование строки является «UTF-8» (я так думаю), и он содержит китайский иероглиф

Но файл является GB2312

вот мой код, я опускаю некоторые из них:

# -*- coding:utf-8 -*- 
# Python 3.4 window 7 

def getUrl(self, url, coding='utf-8'): 
    self.__reCompile = {} 
    req = request.Request(url) 
    req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 UBrowser/5.5.9703.2 Safari/537.36') 
    with request.urlopen(req) as response: 
     return response.read().decode(coding) 

def saveText(self,filename,content,mode='w'): 
    self._checkPath(filename) 
    with open(filename,mode) as f: 
     f.write(content) 

joke= self.getUrl(pageUrl) 
#some re transform such as re.sub('<br>','\r\n',joke) 
self.saveText(filepath+'.txt',joke,'a') 

Иногда есть UnicodeEncodeError: enter image description here

ответ

3

Ваше исключение в «saveText», но я не могу видеть, как вы реализовали его, так что я постараюсь воспроизвести ошибку и дать предложение на исправление.

В 'getUrl' вы возвращаете декодированную строку (.decode ('utf-8')), и я предполагаю, что в 'saveText' вы забудете ее кодировать перед записью в файл.

воспроизводящих ошибку

Попытка воспроизвести ошибку, я сделал это:

# String with unicode chars, decoded like in you example 
s = 'æøå'.decode('utf-8') 

# How saveText could be: 
# Encode before write 
f = open('test', mode='w') 
f.write(s) 
f.close() 

это дает аналогичное исключение:

--------------------------------------------------------------------------- 
UnicodeEncodeError      Traceback (most recent call last) 
<ipython-input-36-1309da3ad975> in <module>() 
     5 # Encode before write 
     6 f = open('test', mode='w') 
----> 7 f.write(s) 
     8 f.close() 

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128) 

Два способа крепления

Вы можете сделать что-либо:

# String with unicode chars, decoded like in you example 
s = 'æøå'.decode('utf-8') 

# How saveText could be: 
# Encode before write 
f = open('test', mode='w') 
f.write(s.encode('utf-8')) 
f.close() 

или вы можете попробовать записать файл с помощью модуля 'кодеки':

import codecs 

# String with unicode chars, decoded like in you example 
s = 'æøå'.decode('utf-8') 

# How saveText could be: 
f = codecs.open('test', encoding='utf-8', mode='w') 
f.write(s) 
f.close() 

Надеется, что это помогает.

+0

'encode' one returns 'должен быть строкой, а не байтами. Но 'codecs' работает, спасибо большое! –

1

Я думаю, что кодировка, используемая вашим терминалом, не поддерживает этот символ. Python обрабатывает его просто отлично, я думаю, что это ваша кодировка вывода, которая не может справиться с этим.

Смотрите также this question

+1

Имеет ли значение терминал? Я не выдаю символ –

2

The encoding of the string is 'utf-8'(I think so) and it contains some Chinese character

Вы декодировали ответ с удаленного сервера с использованием UTF-8. Как только он декодируется в строку Python, он больше не закодирован и не сохраняется эффективно, как Юникод указывает в памяти.

Ошибка, которую вы получаете, потому что Python пытается использовать вашу кодовую страницу для преобразования строки в байты. Из-за настроек вашего региона Windows выбран GBK, который не поддерживает все символы Unicode.

Чтобы сохранить, вам просто нужно, чтобы открыть выходной файл с заданной кодировкой, используя encoding аргумент open() (Python 3. В Python 2, используйте io.open()). В вашем случае «UTF-8» может быть подходящей кодировкой для использования.

Ваш метод saveText() должен обновлена:

def saveText(self,filename,content,mode='w',encoding="utf-8"): 
    self._checkPath(filename) 
    with open(filename,mode,encoding) as f: 
     f.write(content) 

Вы можете столкнуться с вопросом с вашими данными HTTP. Вы предполагаете, что удаленный контент UTF-8 при декодировании ответа. Это не всегда так. Вы можете проанализировать заголовки ответов HTTP, чтобы получить правильную кодировку или использовать библиотеку Requests, которая делает это за вас. Ваш URL-адрес получателя будет выглядеть так:

def getUrl(url): 
    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.157 UBrowser/5.5.9703.2 Safari/537.36'} 
    response = requests.get(url, headers=headers) 
    response.raise_for_status() # Throw an exception on errors 
    return response.text 
Смежные вопросы