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:
-
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''
-
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