Lingua::DetectCyrillic. Определение 7 кириллических кодировок и 2 языков |
Lingua::DetectCyrillic. Пакет определяет 7 кодировок кириллицы, а также язык - русский или английский. Использует встроенные частотные словари; обычно для правильного определения достаточно одного слова.
use Lingua::DetectCyrillic; -or (if you need translation functions) - use Lingua::DetectCyrillic qw ( &TranslateCyr &toLowerCyr &toUpperCyr );
# Новый класс Lingua::DetectCyrillic. По умолчанию анализируется не более 100 # кириллических токенов (слов); украинский язык не определяется. $CyrDetector = Lingua::DetectCyrillic ->new();
# То же самое, но: анализировать по меньшей мере 200 токенов, определять русский # и украинский. $CyrDetector = Lingua::DetectCyrillic ->new( MaxTokens => 200, DetectAllLang => 1 );
# Определить кодировку и язык my ($Coding,$Language,$CharsProcessed,$Algorithm)= $CyrDetector -> Detect( @Data );
# Вывести отчет $CyrDetector -> LogWrite(); #на STDOUT $CyrDetector -> LogWrite('report.log'); #в файл
# Перевод в нижний регистр (предполагается, что исходная кодировка - windows-1251) $s=toLowerCyr($String, 'win'); # Перевод в верхний регистр (предполагается, что исходная кодировка - windows-1251) $s=toUpperCyr($String, 'win'); # Перевод из одной кодировки в другую # Возможные варианты: win, koi, koi8u, mac, iso, dos, utf $s=TranslateCyr('win', 'koi',$String);
См. Дополнительную информацию по использованию пакета .
Данный пакет позволяет определить автоматически все "живые" кодировки кириллицы - windows-1251, koi8-r, koi8-u, iso-8859-5, utf-8, cp866, x-mac-cyrillic, а также язык - Русский или Украинский. Он применяет 3 алгоритма для определения: формальный анализ попадания в алфавит, частотный анализ слов и частотный анализ 2-буквенных сочетаний.
Пакет также имеет процедуры для конвертирования различныъ кодировок кириллических текстов, которые можно при необходимости импортировать.
Пакет позволяет определить кодировку с одного-двух слов. Естественно, в случае одного слова надежность будет низкой, особенно если все слово написано строчными или прописными буквами, так как анализ капитализации слов является важным моментом при определении кодировки. Тем не менее пакет корректно распознает кодировку сообщений, состоящих из одного слова, даже строчными буквами - "привет", "иван", "водка", "спутник". ;-)))
Украинский язык будет определен, только если в тексте имеются специфичные украинские буквы.
Производительность довольно неплохая, т.к. анализ проходит две фазы: на первой производится только быстрый формальный анализ правильности капитализации и выхода за пределы алфавита, и только если этого недостаточно, данные анализируются повторно - по частотным словарям.
Пока пакет требует Unicode::String и Unicode::Map8, которые можно загрузить с http://www.cpan.org. См. Дополнительную информацию по пакетам, которые нужно установить.
Я планирую реализовать собственную поддержку декодирования символов, так что в следующих выпусках необходимости в этих пакетах не будет.
Внимание! Этот модуль требует предварительной компиляции на C++; под Юниксом эта операция проходит гладко и не требует комментариев; но под Win32 и ActiveState Perl вы должны
ch = PerlIO_getc(f);
на
ch = getc(f);
Одним словом, нужно заменить оболочку Perl для функции Си getc на саму эту функцию. Компилятор выдает предупреждениям, но в итоге вы получаете 100% работающую DLL.
$CyrDetector = Lingua::DetectCyrillic ->new(); $CyrDetector = Lingua::DetectCyrillic ->new( MaxTokens => 100, DetectAllLang => 1 );
MaxTokens - пакет прекращает анализ данных, если достигнуто требуемое число кириллических токенов. Не нужно анализировать все 100 или 200 тысяч байт, если после первых 100 токенов кодировка и язык очевидны. По умолчанию этот аргумент равен 100.
DetectAllLang - по умолчанию пакет предполагает, что работает только с русским языком. Установка этого параметра в любое ненулевое значение приведет к анализу двух языков - русского и украинского. Это несколько уменьшает производительность (около 10%) и в редких случаях может привести к худшему определению кодировки.
my ($Coding,$Language,$CharsProcessed,$Algorithm)= $CyrDetector -> Detect( @Data );
$CyrDetector -> LogWrite(); #write to STDOUT $CyrDetector -> LogWrite('report.log'); #write to file
Если единственный аргумент не указан или равен stdout (в любом регистре), программа выводит отчет на STDOUT, иначе в файл.
Начиная программировать, я исходил из очевидного факта: человек легко определяет кодировку и язык с одного взгляда, или по меньшей мере может сказать, что текст отображается в неправильной кодировке. Дело в том, что алфавиты, т.е. буквы большинства кириллических кодировок, не совпадают, так что если мы попытаемся вывести текст на экран в неверной кодировке, то неизбежно увидим непонятные символы внутри слов, которые нельзя напечатать с русской или украинской клавиатуры обычным путем - знаки валюты, пунктуацию, буквы сербского языка, иногда - бинарные символы и т.п.
В сущности, мы имеем только один непростой случай: алфавит двух наиболее популярных кириллических кодировок - windows-1251 и koi8-r - расположен в одном диапазоне, но прописные буквы windows-1251 расположены на месте строчных букв koi8-r и наоборот, так что "Иван Петров" в одной из этих кодировок будет выглядеть как "иВАН пЕТРОВ" в другой, т.е. иметь совершенно неверную капитализацию слов, что также может быть легко установлено формальным анализом букв. А как легко догадаться, любой более-менее реальный кириллический текст должен иметь по меньшей мере одно слово, начинающееся с прописной буквы (я не рассматриваю здесь некоторых странных обитателей Интернета, которые ПИШУТ ВСЕ ПРОПИСНЫМИ БУКВАМИ ;-).
Итак, на первой стадии анализа программа последовательно предполагает, что данный текст написан в одной из 6 или 7 кириллических кодировок и подсчитывает:Этот формальный анализ проходит быстро и он достаточен в 99.9% реальных текстов. Неправильные кодировки легко отфильтровываются и мы получаем одного "абсолютного победителя". Этот метод также достаточно надежен: я с трудом могу представить нормального человека, пишущего в обратной капитализации. Но что если у нас только несколько слов и все они в верхнем или нижнем регистре?
В данном случае мы применяем частотный анализ слов и 2-буквенных сочетаний, называемые также хэшами (естественно, не в том смысле, в каком это слово употребляется в Перле).
В пакет входят словари на 300 наиболее частотных русских и украинских слов и примерно 600 русских и украинских двухбуквенных сочетаний, построенные мной самим (исходные тексты, возможно, были не очень характерными для авторов Интернета, но любой лингвист заверит, что это не очень принципиально: первые несколько сотен наиболее популярных слов в любом языке очень стабильны, не говоря уже о частотности буквенных сочетаний).
Итак, текст анализируется во второй раз (это не должно занять слишком много времени, так как мы можем попасть в данную ситуацию только в случае очень короткого текста); анализируются уже все кириллические буквы, невзирая на капитализацию. Если мы нашли хоть одно слово по словарю - кодировка определена, иначе анализируются хэши.
В некоторых редких случаях (обычно в крайне искусственной ситуации, когда у нас всего одно короткое слово, и оно написано в верхнем или нижнем регистре), статистика по нескольким кодировкам совпадает. Тогда мы предпочитаем windows-1251 кодировке mac, koi8-r - кодировке koi8-u и - если ничего не помогает - предпочитаем windows-1251 кодировке koi8-r.
Чтобы знать, какой алгоритм применялся, мы можем проанализировать 4-ю переменную, возвращаемую функцией Detect - $Algorithm. Более детальная информация - в таблице Объяснение кодов алгоритма
Имеются следующие кодировки:
Объяснение кодов алгоритма | |
---|---|
11 | Формальный анализ количества/капитализации кириллических символов; найдена только одна альтернатива |
21 | Формальный анализ количества/капитализации кириллических символов; найдены две альтернативы (koi8-r и koi8-u); выбрана koi8-r |
22 | Формальный анализ количества/капитализации кириллических символов; найдены две альтернативы (win1251 и mac); выбрана win1251 |
31 | Найдено по меньшей мере одно слово из словаря и есть только одна альтернатива |
32 | Найдено по меньшей мере одно слово из хэша и есть только одна альтернатива |
33 | Формально определена win1251 (скорее всего, на базе анализа хэша) |
34 | Формально определена koi8-r (скорее всего на базе анализа хэша) |
40 | Был выбран наиболее вероятный результат, но надежность очень невелика |
100 | Не найдено ни одного кириллического символа |
01 декабря 2002 - Добавлена полная документация на русском языке. Версия заменена на 0.02.
19 ноября 2002 - выпущена версия 0.01.
1. Собственная поддержка Unicode.
2. Возможность определять только необходимые кодировки из списка.
Что еще? Нужны ваши предложения!!
Автор: Алексей Руденко, Россия, Москва. Мой домашний телефон (095) 468-95-63
Web-site: http://www.bible.ru/DetectCyrillic/
Адрес на CPAN: http://search.cpan.org/author/RUDENKO/
Email: rudenko@bible.ru
Copyright (c) 2002 Alexei Rudenko. All rights reserved.
Lingua::DetectCyrillic. Определение 7 кириллических кодировок и 2 языков |