Экспорт Python MySQL CSV в странную кодировку json

Я получил файл csv, экспортированный из базы данных MySQL (я думаю, что кодировка latin1, так как язык испанский). К сожалению, кодировка неверна, и я вообще не могу ее обработать. Если я использую файл:

$ file -I file.csv file.csv: text/plain; charset=unknown-8bit

Я попытался прочитать файл на python и преобразовать его в utf-8, например:

r.decode('latin-1').encode("utf-8")

или используя mysql_latin1_codec:

r.decode('mysql_latin1').encode('UTF-8')

Я пытаюсь преобразовать данные в объекты json. При сохранении файла возникает ошибка:

"UnicodeEncodeError: кодек "ascii" не может кодировать символы в позиции"

Вы знаете, как я могу преобразовать его в обычные символы utf-8? Или как я могу преобразовать данные в действительный json? Спасибо!!


person alexsc    schedule 25.10.2016    source источник
comment
не могли бы вы привести пример того, что вы пытаетесь декодировать, потому что только с ошибкой нелегко воспроизвести проблему и найти возможное решение...   -  person coder    schedule 25.10.2016
comment
конечно, в csv поля выглядят так: например. DIRECCI��N BARCELONA, vílida hasta и т. д.   -  person alexsc    schedule 25.10.2016


Ответы (3)


Я получил действительно хорошие результаты, используя фреймворк данных pandas из Continuum Analytics.

Вы можете сделать что-то вроде:

import pandas as pd
from pandas import *

con='Your database connection credentials user, password, host, database to use'
data=pd.read_sql_query('SELECT * FROM YOUR TABLE',conn=con)

Тогда вы можете сделать:

data.to_csv('path_with_file_name')

или конвертировать в JSON:

data.to_json(orient='records')

или, если вы предпочитаете настроить формат json, см. документацию здесь: http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.to_json.html

person Beatriz Kanzki    schedule 27.12.2016
comment
привет Беатрис, действительно, я использовал pandas, чтобы открыть csv и развернул их в json, используя force_ascii=True, и это сработало - person alexsc; 17.02.2017

Вы пробовали использовать модуль кодеков?:

import codecs
....
codecs.EncodedFile(r, 'latin1').reader.read()

Я помню, что некоторое время назад у меня была похожая проблема, и ответ был как-то связан с тем, как кодирование выполнялось до Python 3. Кодеки, кажется, справляются с этой проблемой относительно элегантно.

Как упомянул кодер в комментариях к вопросу, трудно точно определить проблему, не имея возможности воспроизвести ее, поэтому я могу лаять не по тому дереву.

person Adam Henderson    schedule 25.10.2016
comment
Я пробовал это и другие вещи, но безуспешно :(. Спасибо! - person alexsc; 25.10.2016

У вас, наверное, две проблемы. Но давайте отступим... Мы не можем сказать, был ли текст неправильно импортирован, неправильно экспортирован или просто отображен дурацким образом.

Во-первых, я собираюсь обсудить "импорт"...

Не пытайтесь изменить кодировку. Вместо этого живите с кодировкой. Но сначала разберитесь, что такое кодировка. Это может быть latin1 или utf8. (Или любой из множества менее вероятных кодировок.)

Узнайте шестнадцатеричный код входящего файла. В Python код для дампа шестнадцатеричного кода (и т. д.) для строки u выглядит примерно так:

for i, c in enumerate(u):
    print i, '%04x' % ord(c), unicodedata.category(c),
    print unicodedata.name(c)

Вы можете здесь просмотреть список шестнадцатеричные значения для всех символов latin1 вместе с шестнадцатеричным значением utf8. Например, ó — это latin1 F3 или utf8 C2B3.

Теперь, вооружившись знанием кодировки, сообщите об этом MySQL.

LOAD DATA INFILE ...
    ...
    CHARACTER SET utf8  -- or latin1
    ...;

Между тем, не имеет значения, что CHARACTER SET ... определяет таблица или столбец; mysql перекодирует при необходимости. Все испанские символы доступны в latin1 и utf8.

Перейдите к этим вопросам и ответам< /эм> .

Я предположил, что у вас есть две ошибки, одна из которых - упомянутый там случай «черного бриллианта»; там другое что-то другое. Но... Следуйте упомянутой "лучшей практике".

Вернемся к вопросу об "экспорте"...

Опять же, вам нужно проверить шестнадцатеричный код выходного файла. Опять же не важно, латиница1 или utf8. Однако... Если шестнадцатеричный код равен C383C2B3 для простого ó, у вас "двойное кодирование". Если у вас есть это, убедитесь, что вы удалили все вызовы функций ручного преобразования и просто сказали MySQL, что к чему.

Вот еще несколько советов по utf8+Python, которые вы может понадобиться.

Если вам нужна дополнительная помощь, следуйте тексту шаг за шагом. Покажите нам код, используемый для его перемещения/преобразования на каждом этапе, и покажите нам HEX на каждом этапе.

person Rick James    schedule 25.10.2016
comment
Привет Рик и спасибо за ваше замечательное объяснение. Я знаю о ваших советах, но, к сожалению, у меня нет доступа к MySQL. Я ограничен некоторыми файлами csv, которые уже экспортированы неправильно :(. - person alexsc; 25.10.2016
comment
Можете ли вы использовать Python для обнаружения шестнадцатеричного кода в файлах? Возможно, читать как двоичный код, а затем смотреть на шестнадцатеричный код? (Я не говорю на Python, поэтому не могу помочь с конкретным кодом.) Или, может быть, утилита для шестнадцатеричного дампа? - person Rick James; 25.10.2016
comment
Вы имеете в виду что-то вроде этого: \x89\xe3\xa2 ? - person alexsc; 25.10.2016
comment
Фу. \x89\xe3\xa2 это ‰ã¢ на латыни1; неправильно закодировано как utf8, на корейском языке (euckr) и т. д. Что должно это быть? - person Rick James; 26.10.2016
comment
Хммм... Я не вижу способа попасть между © и этим гексом 89e3a3. У вас есть пример другой строки и шестнадцатеричного кода? - person Rick James; 26.10.2016
comment
Конечно: M\xc3\x81LAGA для Малаги. - person alexsc; 28.10.2016
comment
C381 — это кодировка utf8 для Á; C3A1 — это версия в нижнем регистре. Был ли фактический текст прописным или строчным? - person Rick James; 28.10.2016
comment
Я получаю такие символы: �� - person alexsc; 30.10.2016
comment
Вероятно, это означает, что вы подключались как latin1. Смотрите мою ссылку и ищите Black Diamond. - person Rick James; 30.10.2016
comment
На какую ссылку вы ссылаетесь? - person alexsc; 01.11.2016