Задать вопрос

Определение кода юникод по символу (PHP)?

Привет всему хабрасообществу!


Уже не впервый раз стыкаюсь с задачей определения кода юникода по символу. (Если более детально, то мы парсим некоторые сайты, и если там встречаються китайские крокозабли, иерогливы, то мы должны заблокировать этот материал).

Вопрос №1:

Какие есть варианты определение кода, без установки дополнительных расширений на ПХП (Используеться 5.4.9).

Пробывали использовать: pear.php.net/package/Text_LanguageDetect — совсем не подходит. Уж очень сильные погрешности.


Сейчас используем собственную утилиту:

/**
 * Util for detect unicode code by symbols
 */
class UnicodeOrdDetect
{
    /**
     * Detect code for one symbol
     *
     * @param string $char
     * @param string $encoding
     * @param bool $hex
     * @return int
     */
    public static function ord($char, $encoding = null, $hex = true)
    {
        // Default encoding
        if (null === $encoding) {
            $encoding = 'UTF-8';
        }

        if (225 >= ($ordChar = ord($char))) {
            return $hex === true ? dechex($ordChar) : $ordChar;
        }

        $char = mb_convert_encoding($char, 'UCS-4BE', $encoding);

        list (, $ordChar) = unpack('N', $char);

        return $hex === true ? dechex($ordChar) : $ordChar;
    }
}



Для теста сверяли с таблицей: unicode-table.com/ погрешности пока что не нашли.

Вопрос №2:

Корректно ли так определять код юникода, или же есть по лучше способы?


Спасибо!
  • Вопрос задан
  • 8356 просмотров
Подписаться 4 Оценить 2 комментария
Решения вопроса 1
KEKSOV
@KEKSOV
Если нужно много и часто сравнивать UTF-8 символы с UNICODE символами, то я бы поступил следующим образом в зависимости от особенностей задачи:

1. Если нужно оставить только символы рус-лат-цифры-препинания, то берем нужные нам UNICODE таблицы с этой страницы www.unicode.org/charts/

(в частности:
Некоторые символы www.unicode.org/charts/PDF/U2100.pdf
Кириллические символы www.unicode.org/charts/PDF/U0400.pdf, www.unicode.org/charts/PDF/U0500.pdf
Знаки препинания www.unicode.org/charts/PDF/U2000.pdf
И еще пунктуация www.unicode.org/charts/PDF/U0080.pdf)

И заранее пересчитываем UNICODE коды из этих таблиц в массив UTF-8 символов
Правила перекодировки UNICODE в UTF-8 можно посмотреть тут en.wikipedia.org/wiki/UTF-8

Bits	Last code point	Byte 1
  7	U+007F	0xxxxxxx

Bits	Last code point	Byte 1	Byte 2	Byte 3	Byte 4	Byte 5	Byte 6
  7	U+007F	0xxxxxxx
11	U+07FF	110xxxxx	10xxxxxx
16	U+FFFF	1110xxxx	10xxxxxx	10xxxxxx
21	U+1FFFFF	11110xxx	10xxxxxx	10xxxxxx	10xxxxxx
26	U+3FFFFFF	111110xx	10xxxxxx	10xxxxxx	10xxxxxx	10xxxxxx
31	U+7FFFFFFF	1111110x	10xxxxxx	10xxxxxx	10xxxxxx	10xxxxxx	10xxxxxx

Для тренировки можно взять Word и нажать Alt-X после символа, отобразится его UNICODE значение. Итак, для нашей буквы «Номер» UNICODE значение 2116 (Hex).
Это значение подпадает под правило (битовая маска) U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
При помощи calc преобразуем 2116 (Hex) в двоичный вид 10000100010110 (Bin).
Вставляем наши биты в маску U+FFFF 1110[0010] 10[000100] 10[010110]
Полученное число запихиваем снова в calc 111000101000010010010110 и получаем E28496 hex, это и есть искомый код нашего символа в UTF-8.


получая таким образом список желаемых символов. Далее, при обработке текста, проверяем его символы с этим набором — если символ нашелся в этом массиве, значит он нам нужен. Если не попал, то — свободен (по-началу нужно будет проверить, все ли требуемые символы мы учли)

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

Список символов нужно оформить в виде ассоциативного массива, где в качестве ключа выступает UTF-8 код, а в качестве значения true или false. В этом случае проверка очередного символа из текста будет почти мгновенной — просто проверить значение массива по ключу.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@Vampiro
а пробовали более простой метод, а-ля
iconv + preg_match('A-z|А-я|0-9|....')?
Ответ написан
@Domini
ru2.php.net/manual/en/reference.pcre.pattern.modifiers.php
u (PCRE_UTF8)
This modifier turns on additional functionality of PCRE that is incompatible with Perl. Pattern strings are treated as UTF-8. This modifier is available from PHP 4.1.0 or greater on Unix and from PHP 4.2.3 on win32. UTF-8 validity of the pattern is checked since PHP 4.3.5.
и ru2.php.net/manual/en/regexp.reference.unicode.php не то?
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы