Определить мусорную строку юникода с помощью python

Мой скрипт считывает данные из CSV-файла, CSV-файл может содержать несколько строк английских или неанглийских слов.

Иногда в текстовом файле есть строки мусора, я хочу идентифицировать эту строку, пропустить эту строку и обработать другие.

doc = codecs.open(input_text_file, "rb",'utf_8_sig')
fob = csv.DictReader(doc)
for row, entry in enumerate(f):
    if is_valid_unicode_str(row['Name']):
         process_futher

def is_valid_unicode_str(value):
     try:
         function
         return True
     except UnicodeEncodeError:
         return false

ввод CSV:

"Name"
"袋è¢âdcx€¹Ã¤Â¸Å½Ã¦Å“‹å‹们çâ€ÂµÃ¥Â­Âå•â€"
"元大寶來證券"
"John Dove"

Я хочу дефилировать функцию is_valid_unicode_str(), которая идентифицирует строку мусора и обрабатывает только действительную.

Я пытался использовать декодирование, но это не сработало при декодировании строк мусора.

value.decode('utf8')

Ожидаемый результат - это строка с китайской и английской строками, которые необходимо обработать.

не могли бы вы подсказать мне, как я могу реализовать функцию для фильтрации действительных файлов Unicode?.


person Shashi    schedule 16.03.2015    source источник
comment
У вас есть строки Mojibake. Данные, которые в какой-то момент были закодированы в одной кодировке, а декодированы в другой. codecs.open() уже декодировал их в строки Unicode, потому что ваш файл был единообразно закодирован в UTF-8.   -  person Martijn Pieters    schedule 16.03.2015
comment
Есть вероятность, что Моджибаке можно отремонтировать, а не выбросить. Взгляните на ftfy, чтобы узнать, что он может сделать, чтобы разобраться в имеющихся у вас строках.   -  person Martijn Pieters    schedule 16.03.2015
comment
Пока что я могу получить 猫垄姑⑩dcx盲赂沤忙姑ヂ姑ぢ宦р得ヂ氓⑩ или 猫垄鈥姑⑩dcx盲赂沤忙艙鈥姑ヂ鈥姑ぢ宦р得ヂ氓鈥⑩ или 猫垄鈥姑⑩dcx盲赂沤忙艙鈥姑ヂ鈥姑ぢ宦р得ヂ氓鈥⑩ (GB2312, GBK и GB18030) из вашего моджибаке. Буду смотреть дальше.   -  person Martijn Pieters    schedule 16.03.2015
comment
К сожалению, FTFY не поддерживает кодеки серии GB*; Я подал заявку на исследование.   -  person Martijn Pieters    schedule 16.03.2015
comment
@Martijn Pieters, спасибо за информацию   -  person Shashi    schedule 16.03.2015
comment
Для будущих сообщений, можете ли вы включить вывод print repr(broken_value)? Таким образом, любые непечатаемые байты и байты, отличные от ASCII, будут включены в качестве управляющих последовательностей, что позволит нам точно воссоздать значение.   -  person Martijn Pieters    schedule 16.03.2015
comment
После разговора с разработчиками ядра ftfy стало ясно, что мое предположение о том, что у вас есть Mojibake с кодировкой GB*, может быть неверным; это также может быть двойной CP1252 - UTF8 Mojibake. Мне было бы очень интересно увидеть здесь вывод строки repr(), чтобы у нас были все байты. На данный момент мой лучший декод с этим предположением относится к 袋dcx与朋们.   -  person Martijn Pieters    schedule 16.03.2015


Ответы (2)


У вас есть строки Mojibake; текст, закодированный одним (правильным) кодеком, а затем декодированный другим.

В этом случае ваш текст был декодирован с использованием кодовой страницы Windows 1252; U+20AC EURO SIGN в тексте типичен для моджибаке CP1252. Исходная кодировка может быть одной из семейства кодировок GB* для китайского языка или кодировкой UTF с множественной передачей туда и обратно. -8 - CP1252 Моджибаке. Какой из них я не могу определить, я не могу читать по-китайски, и у меня нет ваших полных данных; CP1252 Mojibakes включает непечатаемые символы, такие как байты 0x81 и 0x8D, которые могли быть потеряны, когда вы разместили свой вопрос здесь.

Я бы установил проект ftfy; он не исправит кодировку GB * (я запросил проект добавить поддержку) , но он включает новый кодек sloppy-windows-1252, который позволит вам отменить ошибочное декодирование с помощью этого кодека:

>>> import ftfy  # registers extra codecs on import
>>> text = u'袋è¢âdcx€¹Ã¤Â¸Å½Ã¦Å“‹å‹们çâ€ÂµÃ¥Â­Âå•â€'
>>> print text.encode('sloppy-windows-1252').decode('gb2312', 'replace')
猫垄�姑�⑩dcx�盲赂沤忙��姑ヂ�姑ぢ宦�р�得ヂ�氓�⑩�
>>> print text.encode('sloppy-windows-1252').decode('gbk', 'replace')
猫垄鈥姑�⑩dcx�盲赂沤忙艙鈥姑ヂ鈥姑ぢ宦�р�得ヂ�氓鈥⑩�
>>> print text.encode('sloppy-windows-1252').decode('gb18030', 'replace')
猫垄鈥姑⑩dcx�盲赂沤忙艙鈥姑ヂ鈥姑ぢ宦р�得ヂ氓鈥⑩�
>>> print text.encode('sloppy-windows-1252').decode('utf8', 'ignore').encode('sloppy-windows-1252').decode('utf8', 'replace')
袋�dcx与朋�们���

U+FFFD REPLACEMENT CHARACTER показывает, что декодирование не было полностью успешным, но это может быть связано с тот факт, что в вашей скопированной строке здесь отсутствует что-либо, что не может быть напечатано или использует байты 0x81 или 0x8D.

Вы можете попытаться исправить свои данные таким образом; из файловых данных, попробуйте декодировать в один из кодеков GB* после кодирования в sloppy-windows-1252 или дважды выполните двустороннюю передачу из UTF-8 и посмотрите, что подходит лучше всего.

Если этого недостаточно (вы не можете исправить данные), вы можете использовать ftfy.badness.sequence_weirdness() function, чтобы попытаться обнаружить проблему:

>>> from ftfy.badness import sequence_weirdness
>>> sequence_weirdness(text)
9
>>> sequence_weirdness(u'元大寶來證券')
0
>>> sequence_weirdness(u'John Dove')
0

Моджибаке получили высокие оценки по шкале странности последовательности. Вы могли бы попытаться найти подходящий порог для ваших данных, к которому вы могли бы назвать данные, которые, скорее всего, будут повреждены.

Однако я думаю, что мы можем использовать ненулевое возвращаемое значение в качестве отправной точки для другого теста. Английский текст должен получить 0 баллов по этой шкале, как и текст на китайском языке. Китайский, смешанный с английским, по-прежнему может получить более 0 баллов, но вы не сможете затем закодировать этот китайский текст в кодек CP-1252, в то время как вы можете с поврежденным текстом:

from ftfy.badness import sequence_weirdness

def is_valid_unicode_str(text):
    if not sequence_weirdness(text):
        # nothing weird, should be okay
        return True
    try:
        text.encode('sloppy-windows-1252')
    except UnicodeEncodeError:
        # Not CP-1252 encodable, probably fine
        return True
    else:
        # Encodable as CP-1252, Mojibake alert level high
        return False
person Martijn Pieters    schedule 16.03.2015
comment
@Shashi: так что, по-видимому, кодирование-в-неаккуратно-cp1252-затем-декодирование сработало для вас? - person Martijn Pieters; 16.03.2015

(разработчик ftfy здесь)

Я понял, что текст, скорее всего, будет «袋袋与朋友们电子商». Мне пришлось угадывать символы 友, 子 и 商, потому что некоторые непечатаемые символы отсутствуют в строке вашего вопроса. При угадывании я выбирал самый распространенный символ из небольшого числа возможных. И я не знаю, куда идет "dcx" и почему он там.

Google Translate здесь не очень полезен, но, похоже, он имеет какое-то отношение к электронной коммерции.

Итак, вот все, что произошло с вашим текстом:

  1. Он был закодирован как UTF-8 и неправильно декодирован как sloppy-windows-1252, дважды
  2. Буквы «dcx» были вставлены в середину последовательности UTF-8.
  3. Символы, которых нет в Windows-1252, со значениями байтов 81, 8d, 8f, 90 и 9d, были удалены.
  4. Неразрывный пробел (значение байта a0) удален с конца

Если бы возникла только первая проблема, ftfy.fix_text_encoding смог бы ее исправить. Вполне возможно, что оставшиеся проблемы просто возникли, когда вы пытались передать строку в Stack Overflow.

Итак, вот моя рекомендация:

  • Выясните, кто продолжает неправильно декодировать данные как sloppy-windows-1252, и попросите их декодировать их как UTF-8.
  • Если вы снова получите такую ​​строку, попробуйте ftfy.fix_text_encoding на ней.
person rspeer    schedule 16.03.2015