Расшифровать неизвестную строку - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть один источник данных, который я не контролирую, и который отправляет строки с разными кодировками, и у меня нет возможности узнать кодировку заранее! Мне нужно знать формат, чтобы иметь возможность правильно декодировать и хранить правильно в формате, который я понимаю и контролирую, скажем, UTF-8.

, например:

  • " J'ai déjéxa0 un probléme, après ... je ne sais pas "

следует читать

  • " J'ai déjà un Проблема, апрель ... я не говорю "

Что я пробовал:

> stringToTest="J'ai déjÃ\xa0 un problème, après... je ne sais pas"
# there is no decode for string, directly, but one can try
> stringToTest.encode().decode()
"J'ai déjÃ\xa0 un problème, après... je ne sais pas"
# what does not help :)

Метод проб и ошибок, я обнаружил, что кодировка iso-8859-1

> stringToTest.encode('iso-8859-1').decode()
"J'ai déjà un problème, après... je ne sais pas"

Мне нужно / нужно, чтобы найти 'iso-8859-1' автоматически!

Я пытался используйте chardet!

> import chardet

> chardet.detect(stringToTest)
Traceback (most recent call last):
  File "/snap/pycharm-community/188/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/chardet/__init__.py", line 34, in detect
    '{0}'.format(type(byte_str)))
TypeError: Expected object of type bytes or bytearray, got: <class 'str'>

Но ... как это строка ... Chardet не принимает это! И мне стыдно признаться, но мне не удается преобразовать строку во что-то, что принимает chardet!

> test1=b"J'ai déjà un problème, après... je ne sais pas"
  File "<input>", line 1
SyntaxError: bytes can only contain ASCII literal characters.

# Ok str and unicode are similar things... but who knows?!?!
> test1=u"J'ai déjà un problème, après... je ne sais pas"
> chardet.detect(test1)
Traceback (most recent call last):
  File "/snap/pycharm-community/188/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/chardet/__init__.py", line 34, in detect
    '{0}'.format(type(byte_str)))
TypeError: Expected object of type bytes or bytearray, got: <class 'str'>

# NOP
> bytes(stringToTest)
Traceback (most recent call last):
  File "/snap/pycharm-community/188/plugins/python-ce/helpers/pydev/_pydevd_bundle/pydevd_exec2.py", line 3, in Exec
    exec(exp, global_vars, local_vars)
  File "<input>", line 1, in <module>
TypeError: string argument without an encoding

Почему бы не unidecode?!?

from unidecode import unidecode

from unidecode import unidecode
unidecode(stringToTest)
'J\'ai dA(c)jA un problA"me, aprA"s... je ne sais pas'

1 Ответ

1 голос
/ 10 апреля 2020

Строка

"J'ai déjÃ\xa0 un problème, après... je ne sais pas"

является примером mojibake - закодированного текста (bytes), который был декодирован с неправильной кодировкой. В этом конкретном случае строка изначально была закодирована как UTF-8; перекодирование в ISO-8859-1 (латинский-1) воссоздает байты UTF-8, а декодирование из UTF-8 (по умолчанию в Python3) дает ожидаемый результат.

Если вы получаете эти mojibake строки из внешнего источника, вы можете безопасно их кодировать, используя ISO-8859-1 для воссоздания оригинальных байтов. Байты - кодированный текст - могут быть переданы в chardet для анализа.

...