2015-08-25 4 views
0

Я загружаю файлы из S3, содержащие данные JSON (например), которые я намерен анализировать в кадре данных Pandas, используя pd.read_json.Разбор JSON с использованием Pandas - проблема с дополнительными символами escape

Моя проблема заключается в том, что файлы, сбрасываемые в ведро S3, используют форматирование «восьмеричного побега» для неанглийских символов, но объекты Python/Pandas относятся к тому факту, что также включен escape для символа \.

Примером может быть строка: "destination":"Provence-Alpes-C\\303\\264te d\'Azur"

который печатает как:

enter image description here

Если я вручную удалить один из \ символов, то Python счастливо интерпретирует строку и печатает как:

enter image description here

В этом thread есть некоторые хорошие вещи, и хотя .decode('string_escape') хорошо работает с отдельным фрагментом, когда его часть намного длинней строки содержит тысячи записей, тогда она не работает.

Я считаю, что мне нужен умный способ заменить \\ на \, но по хорошо документированным причинам .replace('\\', '\') не работает.

Для того, чтобы получить файлы работать на все, что я использовал регулярное выражение, чтобы удалить все \, за которым следует номер: re.sub(r'\\(?=[0-9])', '', g) - я имею в виду, что адаптация это может быть путь вперед, но количество должно быть динамичным как я не знаю, что это будет (то есть, используя и \2 для примера выше не будет работать ')

Помогите оценить.

+0

Спасибо Мартину, это хорошо работает. Очень редко я получаю сообщение об ошибке - chr() arg не находится в диапазоне (256). Я попытался точно определить, где это падает, хотя его жесткий, поскольку эти файлы массивны! – Jacob

+0

См. Суть, которую я связал в своем втором комментарии. –

+0

Я действительно думал о повторном открытии, потому что у вас есть восьмеричные escape-последовательности для байтов UTF-8, а не для кодов Unicode. Связано, не то же самое. –

ответ

1

Вместо того, чтобы интерпретировать Python \ooo восьмеричные экраны, отредактируйте JSON с регулярным выражением, затем проанализируйте его как JSON. Я сделал это раньше в similar circumstances

Ваши данные в UTF-8 байт бежал в восьмеричной \ooo последовательности, так что вы ищете более ограниченный диапазон значений здесь:

import re 

invalid_escape = re.compile(r'\\([1-3][0-7]{2}|[1-7][0-7]?)') # octal digits from 1 up to FF 
def replace_with_codepoint(match): 
    return chr(int(match.group(0)[1:], 8)) 

def repair(brokenjson): 
    return invalid_escape.sub(replace_with_codepoint, brokenjson) 

Демо:

>>> import json 
>>> sample = '{"destination":"Provence-Alpes-C\\303\\264te d\'Azur"}' 
>>> repair(sample) 
'{"destination":"Provence-Alpes-C\xc3\xb4te d\'Azur"}' 
>>> json.loads(repair(sample)) 
{u'destination': u"Provence-Alpes-C\xf4te d'Azur"} 
>>> print json.loads(repair(sample))['destination'] 
Provence-Alpes-Côte d'Azur 
Смежные вопросы