2011-11-02 20 views
12

Mi código hace que obtenga algo de contenido de un sitio UserVoice. Como ya sabrá, UserVoice es una mierda de software que no puede manejar los datos correctamente; de hecho, para reducir la cantidad de texto en la página de búsqueda, cortan el texto en, digamos, 300 caracteres y luego agregan un "..." hasta el final. La cosa es, , no les importa cortar en medio de un carácter de varios bytes, lo que resulta en un "byte" utf-8 parcial: por ejemplo. para el è char, obtuve \xc3 en lugar de \xc3\xa8s.Python: maneja bytes unicode rotos al analizar cadena JSON

Por supuesto, cuando doy esta sopa horrible a json.loads, falla con UnicodeDecodeError. Entonces mi pregunta es simple: ¿cómo puedo pedirle al json.loads que ignore estos bytes incorrectos, como lo haría usando .decode('utf-8', 'ignore') si tuviera acceso a la parte interna de la función?

Gracias.

Respuesta

11

No le pidas a simplejson que los ignore. Cuando tengo un problema similar al suyo, acabo de ejecutar .decode('utf-8', 'ignore').encode('utf-8') y proceder.

+0

Ok, yo estaba escribiendo actualmente una respuesta diciendo que simplemente puede decodificar la cadena antes de pasarlo a 'json.loads'. Gracias, obviamente funciona! – zopieux

6

sólo tiene que pasar a la cadena Unicode json.loads():

>>> badstr = "qualité"[:-1]+".." 
>>> badstr 
'qualit\xc3..' 
>>> json_str = '["%s"]' % badstr 
>>> import json 
>>> json.loads(json_str) 
Traceback (most recent call last): 
... 
UnicodeDecodeError: 'utf8' codec can't decode byte 0xc3 in position 6: invalid \ 
continuation byte 
>>> json.loads(json_str.decode('utf-8','ignore')) 
[u'qualit..'] 
+0

+1 para una ilustración completa. –

+0

La respuesta de @Lucho incluye un '.encode' adicional, ¿es necesario? –

+0

@Matteo: no. El formato json se define para el texto Unicode y, por lo tanto, '.encode()' después de '.decode()' no es necesario. – jfs