"" "... GB18030. Я думал, что это будет решением, потому что он читает первые несколько файлов и прекрасно их декодирует." "" Пожалуйста, объясните, что вы имеете в виду. Для меня есть ДВА критерия для успешного декодирования: во-первых, что raw_bytes.decode ('some_encoding') не потерпел неудачу, во-вторых, что результирующий юникод при отображении имеет смысл на определенном языке. Каждый файл в юниверсе пройдет первый тест при декодировании с помощью latin1
aka iso_8859_1
. Многие файлы на восточноазиатских языках проходят первый тест с gb18030
, потому что в основном часто используемые символы на китайском, японском и корейском языках кодируются с использованием одних и тех же блоков двухбайтовых последовательностей. Сколько из второго теста вы сделали?
Не пытайтесь смотреть на данные в IDE или текстовом редакторе. Посмотрите на это в веб-браузере; они обычно лучше распознают кодировки.
Откуда ты знаешь, что это персонаж евро? Глядя на экран текстового редактора, который декодирует необработанные байты, используя какую кодировку? cp1252?
Откуда вы знаете, что он содержит китайские иероглифы? Вы уверены, что это не японец? Корейский язык? Откуда ты это взял?
Китайские файлы, созданные в Гонконге, Тайване, может быть, в Макао и других местах за пределами материка, используют кодировку big5
или big5_hkscs
- попробуйте это.
В любом случае, примите совет Марка и укажите на него chardet
; chardet
обычно делает довольно хорошую работу по обнаружению используемой кодировки, если файл достаточно велик и правильно закодирован на китайском / японском / корейском - однако, если кто-то вручную редактировал файл в текстовом редакторе с использованием однобайтовой кодировки, несколько недопустимых символов могут привести к тому, что кодировка, используемая для остальных 99,9% символов, не будет обнаружена.
Вы можете сделать print repr(line)
, скажем, 5 строк из файла и отредактировать вывод в свой вопрос.
Если файл не является конфиденциальным, вы можете сделать его доступным для загрузки.
Был ли файл создан в Windows? Как вы читаете это в Python? (показать код)
Обновление после комментариев OP:
Блокнот и т. Д. Не пытайтесь угадать кодировку; «ANSI» является значением по умолчанию. Вы должны сказать ему, что делать. То, что вы называете символом евро, - это необработанный байт "\ x80", декодированный вашим редактором с использованием кодировки по умолчанию для вашей среды - обычно подозрительным является "cp1252". Не используйте такой редактор для редактирования вашего файла.
Ранее вы говорили о «первых нескольких ошибках». Теперь вы говорите, у вас всего 5 ошибок. Пожалуйста, объясните.
Если файл действительно почти правильный gb18030, вы должны иметь возможность декодировать файл построчно, и когда вы получите такую ошибку, перехватите ее, распечатайте сообщение об ошибке, извлеките смещения байтов из сообщения, напечатайте repr (two_bad_bytes) и продолжайте. Мне очень интересно, какой из двух байтов появляется \x80
. Если он вообще не появляется, «символ евро» не является частью вашей проблемы. Обратите внимание, что \x80
может корректно отображаться в файле gb18030, но только как 2-й байт двухбайтовой последовательности, начинающейся с \x81
до \xfe
.
Хорошо бы узнать, в чем ваша проблема, прежде чем пытаться ее исправить. Попытка исправить это, используя блокнот и т. Д. В режиме «ANSI», не очень хорошая идея.
Вы очень стеснялись того, как решили, что результаты декодирования gb18030 имеют смысл. В частности, я бы внимательно изучил строки, где gbk не работает, но gb18030 «работает» - там должно быть несколько очень редких китайских иероглифов, или, возможно, некоторые некитайские не-ASCII-символы ...
Вот предложение для лучшего способа осмотра повреждения: расшифруйте каждый файл с помощью raw_bytes.decode(encoding, 'replace')
и запишите результат (закодированный в utf8) в другой файл. Подсчитайте ошибки на result.count(u'\ufffd')
. Просмотрите выходной файл, используя то, что вы использовали, чтобы решить, имеет ли смысл декодирование gb18030. Символ U + FFFD должен отображаться в виде белого вопросительного знака внутри черного ромба.
Если вы решите, что некодируемые кусочки могут быть отброшены, самый простой способ - raw_bytes.decode(encoding, 'ignore')
Обновление после получения дополнительной информации
Все эти \\
сбивают с толку. Похоже, что «получение байтов» включает в себя repr(repr(bytes))
вместо просто repr(bytes)
... в интерактивном приглашении, введите либо bytes
(вы получите repr () Implict, либо print repr(bytes)
(который выиграл не получить неявное repr ())
Пустое пространство: я предполагаю, что вы имеете в виду, что '\xf8\xf8'.decode('gb18030')
- это то, что вы интерпретируете как некое пространство во всю ширину, и что интерпретация выполняется визуальным осмотром с использованием некоторого неназванного программного обеспечения для просмотра. Это правильно?
На самом деле, '\xf8\xf8'.decode('gb18030')
-> u'\e28b'
. U + E28B находится в Юникоде PUA (зона личного пользования). «Пробел», по-видимому, означает, что программное обеспечение для просмотра не имеет смысла для символа U + E28B в используемом шрифте.
Возможно, источник файлов намеренно использует PUA для символов, которых нет в стандартном gb18030, или для аннотации, или для передачи псевдосекретной информации. Если это так, вам придется прибегнуть к расшифровке бубна, ответвлению недавнего российского исследования , о котором здесь сообщается .
Альтернатива: теория cp939-HKSCS. Согласно правительству HK, код HKSCS big5 FE57 когда-то был сопоставлен с U + E28B, но теперь сопоставлен с U + 28804.
"Евро": Вы сказали "" "Из-за данных я не могу поделиться всей строкой, но то, что я называю символом евро, находится в: \ xcb \ xbe \ x80 \ x80" [Я предполагая, что \
был опущен с самого начала, а "
буквально]. «Символ евро», когда он появляется, всегда находится в том же столбце, который мне не нужен, поэтому я надеялся просто использовать «игнорировать». К сожалению, поскольку "euro char" находится рядом с кавычками в файле, иногда "ignore" избавляет как от кавычек, так и кавычек [as], что создает проблему в модуле csv для определения столбцов "" "
Было бы очень полезно, если бы вы могли показать шаблоны, в которых эти \x80
байты появляются по отношению к кавычкам и китайским символам - сохраняйте его читабельным, просто показывая гекс, и скрывайте свои конфиденциальные данные, например, используя C1 C2 для представления «двух байтов, которые, я уверен, представляют китайский символ». Например:
C1 C2 C1 C2 cb be 80 80 22 # `\x22` is the quote character
Пожалуйста, предоставьте примеры (1), где "не теряется" заменой "или" игнорировать "(2), когда цитата потеряна. В вашем единственном примере на сегодняшний день" не потеряно:
>>> '\xcb\xbe\x80\x80\x22'.decode('gb18030', 'ignore')
u'\u53f8"'
И предложение отправить вам некоторый код отладки (см. Пример выходных данных ниже) все еще открыто.
>>> import decode_debug as de
>>> def logger(s):
... sys.stderr.write('*** ' + s + '\n')
...
>>> import sys
>>> de.decode_debug('\xcb\xbe\x80\x80\x22', 'gb18030', 'replace', logger)
*** input[2:5] ('\x80\x80"') doesn't start with a plausible code sequence
*** input[3:5] ('\x80"') doesn't start with a plausible code sequence
u'\u53f8\ufffd\ufffd"'
>>> de.decode_debug('\xcb\xbe\x80\x80\x22', 'gb18030', 'ignore', logger)
*** input[2:5] ('\x80\x80"') doesn't start with a plausible code sequence
*** input[3:5] ('\x80"') doesn't start with a plausible code sequence
u'\u53f8"'
>>>
Эврика: - Вероятная причина иногда потери символа кавычки -
Похоже, есть ошибка в механизме замены / игнорирования декодера gb18030
: \x80
не является допустимым начальным байтом gb18030; когда это обнаружено, декодер должен попытаться выполнить повторную синхронизацию с байтом NEXT. Однако он, похоже, игнорирует как \x80
, так и следующий байт:
>>> '\x80abcd'.decode('gb18030', 'replace')
u'\ufffdbcd' # the 'a' is lost
>>> de.decode_debug('\x80abcd', 'gb18030', 'replace', logger)
*** input[0:4] ('\x80abc') doesn't start with a plausible code sequence
u'\ufffdabcd'
>>> '\x80\x80abcd'.decode('gb18030', 'replace')
u'\ufffdabcd' # the second '\x80' is lost
>>> de.decode_debug('\x80\x80abcd', 'gb18030', 'replace', logger)
*** input[0:4] ('\x80\x80ab') doesn't start with a plausible code sequence
*** input[1:5] ('\x80abc') doesn't start with a plausible code sequence
u'\ufffd\ufffdabcd'
>>>