#python #unicode #encoding #utf-8 #scrapy
#python #unicode #кодирование #utf-8 #scrapy
Вопрос:
Я просто не могу понять! : (Я удаляю данные с сайта в кодировке utf-8, ну, по крайней мере, так там написано:
Content-Type: text/html;charset=utf-8
Я получаю список обычных строк Unicode с помощью вызова XPath selector extract ():
item['city']= element.select('//div[@id="bubble_2"]/div/text()').extract()
Это список:
[u'Westbahnhofstr.xa010', u'72070xa0Txfcbingen']
Теперь я объединяю список в одну строку Unicode:
item['city']= "".join(element.select('//div[@id="bubble_2"]/div/text()').extract())
Пока все хорошо:
u'Beim Nonnenhausxa0672070xa0Txfcbingen'
Проблема возникает, когда я пытаюсь вывести эту строку Unicode либо на экран (печать), либо в файл (запись). что бы я ни пробовал, это возвращает ошибку (http://pastebin.com/51DkX2R2 ):
exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'xa0' in position 11: ordinal not in range(128)
Я, конечно, закодировал Unicode в байтовую строку перед выводом:
item['city'].encode('utf-8')
Это мой конвейер.что и как я использую для открытия и записи в свои резюме:
import csv
import items
import urlparse
import codecs
class DepostPipeline(object):
def __init__(self):
self.modelsCsv = csv.writer(codecs.open('Dees.csv', mode='w',encoding='utf-8'))
self.modelsCsv.writerow(['city'])
def process_item(self, item, spider):
if isinstance(item, items.DetailsItem):
item['city'] = item['city'].encode('utf-8')
self.modelsCsv.writerow([item['city']])
return item
Самое странное, что моя система (python в Windows) отлично обрабатывает строки unicode:
C:Console2>python
Python 2.7.6 (default, Nov 10 2013, 19:24:18) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> s=u'Beim Nonnenhausxa0672070xa0Txfcbingen'
>>> print s
Beim Nonnenhaus 672070 Tübingen
Я много читал о utf-8, unicode, кодировании и декодировании за последние 10 дней, но, похоже, я все еще что-то здесь упускаю?!
Я ценю любую помощь или совет.
Ответ №1:
Вы игнорируете результат .encode()
вызова:
item['city'].encode('utf-8')
Строки неизменяемы и не кодируются на месте. Еще лучше, что тип возвращаемого объекта отличается. Вам нужно будет присвоить возвращаемое значение обратно:
item['city'] = item['city'].encode('utf-8')
Однако вы не должны использовать codecs.open()
для файла CSV. csv
Модуль всегда будет записывать байтовые строки, а не Юникод.
При использовании codecs.open()
файлового объекта выполняется неявное декодирование для возврата к Unicode, и именно это у вас не получается; именно поэтому вы получаете UnicodeDecodeError
исключение, а не ошибку кодирования:
File "C:Python27libcodecs.py", line 351, in write
data, consumed = self.encode(object, self.errors)
exceptions.UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 11: ordinal not in range(128)
Вместо этого используйте обычный open()
вызов:
self.modelsCsv = csv.writer(open('Dees.csv', mode='wb'))
Обратите внимание на 'wb'
; csv
модуль сам обрабатывает окончания строк.
Комментарии:
1. Извините, каким-то образом я пропустил это в своем коде, это уже было на месте… Я редактирую свой пост. Спасибо за ответ.
2. @mrki: верно, это потому, что вы используете
codecs.open()
; Я пропустил это. В следующий раз было бы очень полезно включить обратную трассировку в ваш вопрос ! 🙂3. Я действительно не понял этого из отслеживания ошибки: (сейчас вы спасаете мне жизнь 🙂 Я использовал вызов open () во всех моих предыдущих сканерах. На этот раз я действительно подумал, что мне нужен файл utf-8 для хранения сведений в виде байтовых строк, а не строк unicode. Но зачем мне это нужно сейчас, если я просто могу выбрать кодировку, если мне нужно открыть свой файл для ручного редактирования. Что за беспорядок! Хотя для меня это очень хороший опыт! Спасибо Martijn!
Ответ №2:
Вы можете использовать параметр «игнорировать»:
item['city'].encode('utf-8', 'ignore')
https://docs.python.org/2/howto/unicode.html#the-unicode-type
Комментарии:
1. UTF-8 может обрабатывать все кодовые точки Unicode; здесь нечего игнорировать .