Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
288 views
in Technique[技术] by (71.8m points)

python - Facebook JSON badly encoded

I downloaded my Facebook messenger data (in your Facebook account, go to settings, then to Your Facebook information, then Download your information, then create a file with at least the Messages box checked) to do some cool statistics

However there is a small problem with encoding. I'm not sure, but it looks like Facebook used bad encoding for this data. When I open it with text editor I see something like this: Radosu00c5u0082aw. When I try to open it with python (UTF-8) I get Rados?x82aw. However I should get: Rados?aw.

My python script:

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

I tried a few most common encodings. Example data is:

{
  "sender_name": "Radosu00c5u0082aw",
  "timestamp": 1524558089,
  "content": "No to trzeba ostatnie treningi zrobiu00c4u0087 xD",
  "type": "Generic"
}
Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I can indeed confirm that the Facebook download data is incorrectly encoded; a Mojibake. The original data is UTF-8 encoded but was decoded as Latin -1 instead. I’ll make sure to file a bug report.

In the meantime, you can repair the damage in two ways:

  1. Decode the data as JSON, then re-encode any strings as Latin-1, decode again as UTF-8:

    >>> import json
    >>> data = r'"Radosu00c5u0082aw"'
    >>> json.loads(data).encode('latin1').decode('utf8')
    'Rados?aw'
    
  2. Load the data as binary, replace all u00hh sequences with the byte the last two hex digits represent, decode as UTF-8 and then decode as 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'))
    

    From your sample data this produces:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...