Вопрос

Я хотел бы обнаружить кодирование некоторых текста (с использованием PHP). Для этой цели я использую функцию MB_DETECT_ENCODING ().

Проблема в том, что функция возвращает разные результаты, если я изменил порядок возможных кодировков с функцией MB_DETETECT_ORDER ().

Рассмотрим следующий пример

$html = <<< STR
ちょっとのアクセスで落ちてしまったり、サーバー障害が多いレンタルサーバーを選ぶとあなたのビジネス等にかなりの影響がでてしまう可能性があります。特に商売をされている個人の方、法人の方は気をつけるようにしてください
STR;
mb_detect_order(array('UTF-8','EUC-JP', 'SJIS', 'eucJP-win', 'SJIS-win', 'JIS', 'ISO-2022-JP','ISO-8859-1','ISO-8859-2'));
$originalEncoding = mb_detect_encoding($str);
die($originalEncoding); // $originalEncoding = 'UTF-8'

Однако, если вы измените порядок кодировщиков в MB_DETECT_ORDER (), результаты будут разными:

mb_detect_order(array('EUC-JP','UTF-8', 'SJIS', 'eucJP-win', 'SJIS-win', 'JIS', 'ISO-2022-JP','ISO-8859-1','ISO-8859-2'));        
die($originalEncoding); // $originalEncoding = 'EUC-JP'



Так что мои вопросы:
Почему это происходит?
Есть ли путь в PHP, чтобы правильно и однозначно обнаружить кодирование текста?

Это было полезно?

Решение

Это то, что я ожидал произойти.

Алгоритм обнаружения, вероятно, просто продолжает пытаться, в порядке, кодировки, которые вы указали в mb_detect_order а затем возвращает первый, при котором Bytestream будет действительным.

Нечто более интеллектуальное требует статистических методов (я думаю, что машинное обучение обычно используется).

Редактировать: см., Например, эта статья Для более интеллектуальных методов.

Благодаря его важности, автоматическое обнаружение Charset уже реализуется в крупных интернет-приложениях, таких как Mozilla или Internet Explorer. Они очень точны и быстро, но реализация применяет множество конкретных знаний домена в каждом конкретном случае. В отличие от их методов, мы нацелены на простой алгоритм, который можно равномерно применить к каждому челюсти, а алгоритм основан на хорошо установленных стандартных методах обучения машины. Мы также изучали взаимосвязь между языковым и шарным обнаружением и сравнивали байтовые алгоритмы и алгоритмы на основе характеров. Мы использовали Naive Bayes (NB) и поддерживать векторную машину (SVM).

Другие советы

Не совсем. Различные кодировки часто имеют большие области перекрытия, и если ваша строка, которую вы тестируете, существует полностью внутри этого перекрытия, то оба кодировки приемлемы.

Например, UTF-8 и ISO-8859-1 одинаковы для букв AZ. Строка «Hello» будет иметь одинаковую последовательность байтов в обоих кодировках.

Это именно поэтому есть mb_detect_order() Функция в первую очередь, как это позволяет вам сказать, что вы бы предпочли произойти, когда эти столкновения случаются. Хотите «Привет», чтобы быть UTF-8 или ISO-8859-1?

Иметь ввиду mb_detect_encoding() Не знает, что кодирует данные. Вы можете увидеть строку, но сама функция только видит поток байтов. Имеясь этим, ему необходимо угадать, какая кодировка - например, ASCII, если бы байты только в диапазоне 0-127, UTF-8 было бы, если есть байты ASCII и 128+ байтов, которые существуют только в парах или более, и так далее.

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

Нравиться рихк сказал, что это то, что mb_detect_order() Функция предназначена для - вы в основном предоставляете свои наилучшие догадки, какие данные могут быть. Вы часто работаете с файлами UTF-8? Тогда шансы - это ваши вещи, которые не могут быть UTF-16, даже если mb_detect_encoding() мог догадаться так, как это.

Вы могли бы также захотеть проверить Artefacto.С. связь для более глубокого взгляда.

Пример случаи: Internet Explorer Использует некоторые интересные угадывания кодирования, если ничего не указано (@Link, раздел: «Для автоматического обнаружения языка веб-сайта» вызвало странное поведение на веб-сайтах, которые приняли кодировку как должное в прошлом. Возможно, вы можете найти несколько забавных вещей на этом, если у вас есть гугл. Это делает для хорошего шоу-случая, насколько даже статистические методы могут углубиться, и почему угадывание кодирования в целом проблематично.

MB_DETECT_ENCODING смотрит на первую запись Charset в вашем MB_DETECT_ORDER (), а затем с помощью вашего входа $ HTML сопоставившаяся символ по характеру, используя ли этот символ в пределах действительного набора символов для Charset. Если каждый символ совпадает, то он возвращает true; Если какой-либо символ не удается, он перемещается на следующую черт в MB_DETECT_ORDER () и снова пытается.

Список Charsets Wikipedia это хорошее место, чтобы увидеть персонажей, которые составляют каждую характеристику.

Поскольку эти значения Charset перекрываются (CHAR X8FA1EF существует в обоих «UTF-8», так и в «EUC-JP»), это будет рассмотрено совпадение, даже если это совершенно другой символ в каждом наборе символов. Поэтому, если ни одно из значений символов не существует в одном уровне, но не в другом, то Mb_detect_Encoding не может определить, какой из Charsets недействителен; И вернет первую черт из вашего списка массива, который может быть действительным.

Насколько я знаю, нет уверенного способа идентификации Чарта. МЕТОД «BEST HEBST» PHP может помочь, если у вас есть разумное представление о том, какие Charsets вы, вероятно, столкнулись, и соответственно заказывайте свой список на основе зазоров (недопустимые символы) в каждом уровне задачи. Лучшее решение - «знать» ЧПУ. Если вы соскабливаете HTML с другой страницы, ищите идентификатор Charset в заголовке этой страницы.

Если вы действительно хотите быть умным, вы можете попробовать идентифицировать язык, в котором записан HTML, возможно, используя триграммы или N-граммы или аналогичные, как описано в эта статья на PHP / IR.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top