Python y el tema de la encoding scrapy

Simplemente no puedo entender! 🙁 Estoy desechando datos de un sitio codificado en utf-8, bueno, eso es al menos lo que dice:

Content-Type: text/html;charset=utf-8 

Estoy obteniendo una lista de cadenas regulares de Unicode con XPath selector extract () call:

 item['city']= element.select('//div[@id="bubble_2"]/div/text()').extract() 

Esta es la lista:

 [u'Westbahnhofstr.\xa010', u'72070\xa0T\xfcbingen'] 

Ahora me uno a la lista en una cadena de Unicode:

 item['city']= "".join(element.select('//div[@id="bubble_2"]/div/text()').extract()) 

Hasta ahora tan bueno:

 u'Beim Nonnenhaus\xa0672070\xa0T\xfcbingen' 

El problema aparece mientras trato de enviar esta cadena Unicode a la pantalla (impresión) o a un archivo (escritura). Lo que sea que intente, devuelve un error ( http://pastebin.com/51DkX2R2 ):

 exceptions.UnicodeEncodeError: 'ascii' codec can't encode character u'\xa0' in position 11: ordinal not in range(128) 

He codificado unicode a cadena de bytes antes de la salida, por supuesto:

 item['city'].encode('utf-8') 

Este es mi pipeline.py y cómo lo uso para abrir y escribir en mi cvs:

 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 

Lo más extraño es que mi sistema (Python en Windows) maneja cadenas Unicode perfectamente:

 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 Nonnenhaus\xa0672070\xa0T\xfcbingen' >>> print s Beim Nonnenhaus 672070 Tübingen 

He estado leyendo sobre utf-8, Unicode, encoding y deencoding mucho en los últimos 10 días, pero parece que todavía me falta algo aquí. Aprecio cualquier ayuda o consejo.

Estás ignorando el resultado de la llamada .encode() :

 item['city'].encode('utf-8') 

Las cadenas son inmutables y no están codificadas en el lugar. Aún mejor, el tipo del objeto devuelto es diferente. Tendrá que volver a asignar el valor de retorno:

 item['city'] = item['city'].encode('utf-8') 

Sin embargo, no debe usar codecs.open() para el archivo CSV. El módulo csv siempre escribirá bytestrings, no Unicode.

Al usar un objeto de archivo codecs.open() , se lleva a cabo una deencoding implícita para volver a Unicode, y eso es lo que falla para usted; Es por eso que obtiene una excepción UnicodeDecodeError , no un error de encoding:

  File "C:\Python27\lib\codecs.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) 

En su lugar, use una llamada regular open() :

 self.modelsCsv = csv.writer(open('Dees.csv', mode='wb')) 

Tenga en cuenta el 'wb' ; El módulo csv maneja las terminaciones de línea.

Puedes usar el parámetro “ignorar”:

 item['city'].encode('utf-8', 'ignore') 

https://docs.python.org/2/howto/unicode.html#the-unicode-type