Файл содержит \ u00c2 \ u00a0, конвертировать в символы - PullRequest
1 голос
/ 09 июля 2019

У меня есть JSON-файл, который содержит такой текст

 .....wax, and voila!\u00c2\u00a0At the moment you can't use our ...

Мой простой вопрос: как конвертировать (а не удалять) эти \ u коды в пробелы, апострофы и т. Д.?

Ввод: текстовый файл с .....wax, and voila!\u00c2\u00a0At the moment you can't use our ...

Выход: .....wax, and voila!(converted to the line break)At the moment you can't use our ...

Код Python

def TEST():
        export= requests.get('https://sample.uk/', auth=('user', 'pass')).text

        with open("TEST.json",'w') as file:
            file.write(export.decode('utf8'))

То, что я пробовал:

  • Использование .json ()
  • любых различных способов объединения .encode (). Decode () и т. Д.

Редактировать 1

Когда я загружаю этот файл в BigQuery, у меня - Â символ

Большой образец:

{
    "xxxx1": "...You don\u2019t nee...",
    "xxxx2": "...Gu\u00e9rer...",
    "xxxx3": "...boost.\u00a0Sit back an....",
    "xxxx4": "\" \u306f\u3058\u3081\u307e\u3057\u3066\"",
    "xxxx5": "\u00a0\n\u00a0",
    "xxxx6": "It was Christmas Eve babe\u2026",
    "xxxx7": "It\u2019s xxx xxx\u2026"
}

Код Python:

import json
import re
import codecs


def load():
    epos_export = r'{"xxxx1": "...You don\u2019t nee...","xxxx2": "...Gu\u00e9rer...","xxxx3": "...boost.\u00a0Sit back an....","xxxx4": "\" \u306f\u3058\u3081\u307e\u3057\u3066\"","xxxx5": "\u00a0\n\u00a0","xxxx6": "It was Christmas Eve babe\u2026","xxxx7": "It\u2019s xxx xxx\u2026"}'
    x = json.loads(re.sub(r"(?i)(?:\\u00[0-9a-f]{2})+", unmangle_utf8, epos_export))

    with open("TEST.json", "w") as file:
        json.dump(x,file)

def unmangle_utf8(match):
    escaped = match.group(0)                   # '\\u00e2\\u0082\\u00ac'
    hexstr = escaped.replace(r'\u00', '')      # 'e282ac'
    buffer = codecs.decode(hexstr, "hex")      # b'\xe2\x82\xac'

    try:
        return buffer.decode('utf8')           # '€'
    except UnicodeDecodeError:
        print("Could not decode buffer: %s" % buffer)



if __name__ == '__main__':
    load()

Ответы [ 3 ]

2 голосов
/ 10 июля 2019

Я сделал этот грубый UTF-8 unmangler, который, кажется, решает вашу запутанную ситуацию кодирования:

import codecs
import re
import json

def unmangle_utf8(match):
    escaped = match.group(0)                   # '\\u00e2\\u0082\\u00ac'
    hexstr = escaped.replace(r'\u00', '')      # 'e282ac'
    buffer = codecs.decode(hexstr, "hex")      # b'\xe2\x82\xac'

    try:
        return buffer.decode('utf8')           # '€'
    except UnicodeDecodeError:
        print("Could not decode buffer: %s" % buffer)

Использование:

broken_json = '{"some_key": "... \\u00e2\\u0080\\u0099 w\\u0061x, and voila!\\u00c2\\u00a0\\u00c2\\u00a0At the moment you can\'t use our \\u00e2\\u0082\\u00ac ..."}'
print("Broken JSON\n", broken_json)

converted = re.sub(r"(?i)(?:\\u00[0-9a-f]{2})+", unmangle_utf8, broken_json)
print("Fixed JSON\n", converted)

data = json.loads(converted)
print("Parsed data\n", data)
print("Single value\n", data['some_key'])

Используется регулярное выражение для подборашестнадцатеричные последовательности из вашей строки, преобразует их в отдельные байты и декодирует их как UTF-8.

Для приведенной выше примерной строки (я включил 3-байтовый символ в качестве теста), это печатает:

Broken JSON
 {"some_key": "... \u00e2\u0080\u0099 w\u0061x, and voila!\u00c2\u00a0\u00c2\u00a0At the moment you can't use our \u00e2\u0082\u00ac ..."}
Fixed JSON
 {"some_key": "... ’ wax, and voila!  At the moment you can't use our € ..."}
Parsed data
 {'some_key': "... ’ wax, and voila!\xa0\xa0At the moment you can't use our € ..."}
Single value
 ... ’ wax, and voila!  At the moment you can't use our € ...

* * * * * * * * *1012* * * * * * * * * * * * * * * * * * * * \xa0 в "Разобранных данных" вызвано тем, как Python выводит данные на консоль, это все еще фактический неразрывный пробел.

2 голосов
/ 10 июля 2019

Хакерский подход заключается в удалении внешнего уровня кодирования:

import re
# Assume export is a bytes-like object
export = re.sub(b'\\\u00([89a-f][0-9a-f])', lambda m: bytes.fromhex(m.group(1).decode()), export, flags=re.IGNORECASE)

Соответствует экранированным байтам UTF-8 и заменяет их действительными байтами UTF-8. Запись получающегося байтовоподобного объекта на диск (без дальнейшей расшифровки!) Должна привести к созданию корректного файла JSON UTF-8.

Конечно, это сломается, если файл содержит подлинные экранированные символы Юникода в диапазоне UTF-8, например \u00e9 для акцентированного "e".

1 голос
/ 10 июля 2019

Когда вы попытаетесь записать это в файл с именем TEST.json, я буду предполагать, что эта строка является частью большей строки json.

Позвольте мне использовать полный пример:

js = '''{"a": "and voila!\\u00c2\\u00a0At the moment you can't use our"}'''
print(js)

{"a": "and voila!\u00c2\u00a0At the moment you can't use our"}

Сначала я загрузил бы это с помощью json:

x = json.loads(js)
print(x)

{'a': "and voila!Â\xa0At the moment you can't use our"}

Хорошо, теперь это выглядит как строка utf-8, которая была неправильно декодирована как Latin1.Давайте сделаем обратную операцию:

x['a'] = x['a'].encode('latin1').decode('utf8')
print(x)
print(x['a'])

{'a': "and voila!\xa0At the moment you can't use our"}
and voila! At the moment you can't use our

Хорошо, теперь все в порядке, и мы можем преобразовать ее обратно в правильную строку json:

print(json.dumps(x))

{"a": "and voila!\\u00a0At the moment you can\'t use our"}

, что означает правильно закодированный NO-BREAKПРОБЕЛ (U + 00A0)

TL / DR: что вы должны сделать, это:

# load the string as json:
js = json.loads(request)

# identify the string values in the json - you probably know how but I don't...
...

# convert the strings:
js[...] = js[...].encode('latin1').decode('utf8')

# convert back to a json string
request = json.dumps(js)
...