python python-3.x unicode mojibake

python - Facebook JSON mal codificado



python-3.x unicode (2)

De hecho, puedo confirmar que los datos de descarga de Facebook están codificados incorrectamente; un Mojibake . Los datos originales están codificados en UTF-8, pero en su lugar se decodificaron como Latin -1. Me aseguraré de presentar un informe de error.

Mientras tanto, puedes reparar el daño de dos maneras:

  1. Decodifique los datos como JSON, luego vuelva a codificar las cadenas como Latin-1, decodifique nuevamente como UTF-8:

    >>> import json >>> data = r''"Rados/u00c5/u0082aw"'' >>> json.loads(data).encode(''latin1'').decode(''utf8'') ''Radosław''

  2. Cargue los datos como binarios, reemplace todas las secuencias /u00hh con el byte que representan los últimos dos dígitos hexadecimales, decodifique como UTF-8 y luego decodifique como JSON:

    import re from functools import partial fix_mojibake_escapes = partial( re.compile(rb''//u00([/da-f]{2})'').sub, lambda m: bytes.fromhex(m.group(1).decode())) with open(os.path.join(subdir, file), ''rb'') as binary_data: repaired = fix_mojibake_escapes(binary_data.read()) data = json.loads(repaired.decode(''utf8''))

    A partir de sus datos de muestra esto produce:

    {''content'': ''No to trzeba ostatnie treningi zrobić xD'', ''sender_name'': ''Radosław'', ''timestamp'': 1524558089, ''type'': ''Generic''}

Descargué mis datos de Facebook Messenger (en su cuenta de Facebook, vaya a la configuración, luego a la información de su Facebook , luego descargue su información , luego cree un archivo con al menos la casilla de Mensajes marcada) para hacer algunas estadísticas interesantes.

Sin embargo, hay un pequeño problema con la codificación. No estoy seguro, pero parece que Facebook utilizó una codificación incorrecta para estos datos. Cuando lo abro con el editor de texto veo algo como esto: Rados/u00c5/u0082aw . Cuando intento abrirlo con python (UTF-8) obtengo RadosÅ/x82aw . Sin embargo debería obtener: Radosław .

Mi script en python:

text = open(os.path.join(subdir, file), encoding=''utf-8'') conversations.append(json.load(text))

Probé algunas de las codificaciones más comunes. Ejemplo de datos es:

{ "sender_name": "Rados/u00c5/u0082aw", "timestamp": 1524558089, "content": "No to trzeba ostatnie treningi zrobi/u00c4/u0087 xD", "type": "Generic" }


Mi solución para analizar objetos utiliza la devolución de llamada parse_hook en la función de carga / carga :

import json def parse_obj(dct): for key in dct: dct[key] = dct[key].encode(''latin_1'').decode(''utf-8'') pass return dct data = ''{"msg": "Ahoj sv/u00c4/u009bte"}'' # String json.loads(data) # Out: {''msg'': ''Ahoj svÄ/x9bte''} json.loads(data, object_hook=parse_obj) # Out: {''msg'': ''Ahoj světe''} # File with open(''/path/to/file.json'') as f: json.load(f, object_hook=parse_obj) # Out: {''msg'': ''Ahoj světe''} pass

Actualizar:

La solución para analizar la lista con cadenas no funciona. Así que aquí está la solución actualizada:

import json def parse_obj(obj): for key in obj: if isinstance(obj[key], str): obj[key] = obj[key].encode(''latin_1'').decode(''utf-8'') elif isinstance(obj[key], list): obj[key] = list(map(lambda x: x if type(x) != str else x.encode(''latin_1'').decode(''utf-8''), obj[key])) pass return obj