Определяем язык текста с помощью cld2+python+php

cld2 (Compact Language Detection)  библиотека от компании google, написанная на С. Как заявляет google, со второй версии она стала быстрее и детектит большее количество языков. Библиотека может задетектить более 80 языков. Определяет до 3-х языков, использованных в тексте. Например, 800 байт - английский, 200 байт - французский и т.д.

Библиотека cld2 используется в популярном браузере Chrome (Chromium) для определения языка, с которого нужно перевести сайт.

Для определения языка по входной строке нам понадобится: cld2, python, php для удобства.

Установка и сборка cld2 на debian сервере

aptitude install python2.7-dev mercurial git-svn g++
cd /opt
git svn clone http://cld2.googlecode.com/svn/trunk/ cld2
cd /opt/cld2/internal
sudo ./compile.sh
sudo ./compile_full.sh
sudo ./compile_libs.sh

cd /opt
hg clone https://code.google.com/p/chromium-compact-language-detector/
cd /opt/chromium-compact-language-detector/
sudo ln -s /opt/cld2/internal/libcld2* /usr/lib/
sudo LD_LIBRARY_PATH=/usr/lib ./setup.py build
sudo LD_LIBRARY_PATH=/usr/lib python ./setup_full.py build
sudo python setup.py install

На этом сборка либы окончена.

Можно посмотреть описание метода detect у класса cld2 в python в консоли:

python -c "import cld2; help(cld2.detect)"

Использование cld2

Создаём файл detect_language.py. Файл будет непосредственно взаимодействовать с библиотекой cld2 и выводить результат - язык текста (русский, английский, французский, китайский и т.д.). Содержимое файла detect_language.py

from optparse import OptionParser
import cld2full

def main():
    parser = OptionParser("usage: %prog [options] text")
    parser.add_option("-l", "--hint-language", dest="hint_language", default=None)
    parser.add_option("-d", "--hint-domain", dest="hint_domain", default=None)

    (options, args) = parser.parse_args()

    if len(args) != 1:
        parser.error("Incorrect number of arguments")

    text = args[0]

    result = cld2full.detect(utf8Bytes=text, hintTopLevelDomain=options.hint_domain, hintLanguage=options.hint_language)
    isReliable, textBytesFound, details = result

    print details[0][1]

if __name__ == "__main__":
    main()

Обратите внимание, что этот python-код возвращает только один основной язык, используемый в строке (print details[0][1]).

Я на Питоне не пишу, а пишу на php, поэтому выполнять файл detect_language.py будем из-под php. Т.е. мои парсеры все на php. Пишем php-класс (парсер), который будет запускать через exec python-код и далее работать с результатом.

Класс назовём Language_Detector_CLD2.

Исходный код файла Language/Detector/CLD2.php
<?php

/**
 * Language detector via Chromium Compact Language Detector v2.0 (CLD)
 *
 * CLD sources: https://code.google.com/p/cld2/source/checkout
 *              http://cld2.googlecode.com/svn/trunk/
 * This class depends on python cli script detect_language.py
 */
class Language_Detector_CLD2
{
	/**
	 * Extracted from CLD source. Any other value will cause a error
	 *
	 * @var array
	 */
	private $supportedLanguageHints = array(
		'ab', 'aa', 'af', 'ak', 'sq', 'am', 'ar', 'hy', 'as', 'ay',
		'az', 'ba', 'eu', 'be', 'bn', 'bh', 'bi', 'bs', 'br', 'bg',
		'my', 'ca', 'ceb', 'chr', 'ny', 'co', 'hr', 'cs', 'zh', 'zh-Hant',
		'da', 'dv', 'nl', 'dz', 'en', 'eo', 'et', 'ee', 'fo', 'fj',
		'fi', 'fr', 'fy', 'gaa', 'gl', 'lg', 'ka', 'de', 'el', 'kl',
		'gn', 'gu', 'ht', 'ha', 'haw', 'iw', 'hi', 'hmn', 'hu', 'is',
		'ig', 'id', 'ia', 'ie', 'iu', 'ik', 'ga', 'it', 'xxx', 'jw',
		'ja', 'kn', 'ks', 'kk', 'kha', 'km', 'rw', 'kri', 'ku', 'ky',
		'ko', 'lo', 'la', 'lv', 'lif', 'ln', 'lt', 'loz', 'lua', 'luo',
		'lb', 'mk', 'mg', 'ms', 'ml', 'mt', 'gv', 'mi', 'mr', 'mfe',
		'ro', 'mn', 'sr-ME', 'na', 'nr', 'ne', 'new', 'no', 'nn', 'oc',
		'or', 'om', 'os', 'pam', 'ps', 'nso', 'fa', 'pl', 'pt', 'pa',
		'qu', 'raj', 'rm', 'rn', 'ru', 'sm', 'sg', 'sa', 'sco', 'gd',
		'sr', 'crs', 'st', 'sn', 'sd', 'si', 'ss', 'sk', 'sl', 'so',
		'es', 'su', 'sw', 'sv', 'syr', 'tl', 'tg', 'ta', 'tt', 'te',
		'th', 'bo', 'ti', 'to', 'ts', 'tn', 'tum', 'tr', 'tk', 'tw',
		'ug', 'uk', 'ur', 'uz', 've', 'vi', 'vo', 'war', 'cy', 'wo',
		'xh', 'xx-Arab', 'xx-Armn', 'xx-Avst', 'zzb', 'xx-Bali', 'xx-Bamu', 'xx-Batk', 'xx-Beng',
		'xx-Bopo', 'xx-Brah', 'xx-Brai', 'xx-Bugi', 'xx-Buhd', 'xx-Cans', 'xx-Cari', 'xx-Cakm',
		'xx-Cham', 'xx-Cher', 'xx-Zyyy', 'xx-Copt', 'xx-Xsux', 'xx-Cprt', 'xx-Cyrl', 'xx-Dsrt',
		'xx-Deva', 'zze', 'xx-Egyp', 'xx-Ethi', 'xx-Geor', 'xx-Glag', 'xx-Goth', 'xx-Grek',
		'xx-Gujr', 'xx-Guru', 'zzh', 'xx-Hani', 'xx-Hang', 'xx-Hano', 'xx-Hebr', 'xx-Hira',
		'xx-Armi', 'xx-Qaai', 'xx-Phli', 'xx-Prti', 'xx-Java', 'tlh', 'xx-Kthi', 'xx-Knda',
		'xx-Kana', 'xx-Kali', 'xx-Khar', 'xx-Khmr', 'xx-Laoo', 'xx-Latn', 'xx-Lepc', 'xx-Limb',
		'xx-Linb', 'xx-Lisu', 'xx-Lyci', 'xx-Lydi', 'xx-Mlym', 'xx-Mand', 'xx-Mtei', 'xx-Merc',
		'xx-Mero', 'xx-Plrd', 'xx-Mong', 'xx-Mymr', 'xx-Talu', 'xx-Nkoo', 'xx-Ogam', 'xx-Olck',
		'xx-Ital', 'xx-Xpeo', 'xx-Sarb', 'xx-Orkh', 'xx-Orya', 'xx-Osma', 'zzp', 'xx-Phag',
		'xx-Phnx', 'xx-Rjng', 'xx-Runr', 'xx-Samr', 'xx-Saur', 'xx-Shrd', 'xx-Shaw', 'xx-Sinh',
		'xx-Sora', 'xx-Sund', 'xx-Sylo', 'xx-Syrc', 'xx-Tglg', 'xx-Tagb', 'xx-Tale', 'xx-Lana',
		'xx-Tavt', 'xx-Takr', 'xx-Taml', 'xx-Telu', 'xx-Thaa', 'xx-Thai', 'xx-Tibt', 'xx-Tfng',
		'xx-Ugar', 'xx-Vaii', 'xx-Yiii', 'yi', 'yo', 'za', 'zu'
	);

	private $notDetectedCodes = array('un', 'xx', 'xx', '??');

	/**
	 * Detect language
	 *
	 * @param $text
	 * @param string $languageHint ISO code. See list of supported codes above.
	 * @param string $domainHint top level domain hint
	 * @return string ISO code
	 */
	public function detect($text, $languageHint = null, $domainHint = null)
	{
		if (!in_array($languageHint, $this->supportedLanguageHints)) {
			$languageHint = null;
		}

		// Remove dashes cause it may confuse OptionParser
		$text = preg_replace('/-/', ' ', $text);

		$textArg = escapeshellarg($text);
		$command = 'python detect_language.py ' . $textArg;

		if ($languageHint) {
			$command .= ' -l ' . $languageHint;
		}
		if ($domainHint) {
			$command .= ' -d ' . $domainHint;
		}

		$code = trim(`$command`);

		if (!in_array($code, $this->notDetectedCodes)) {
			return $code;
		}

		return '00';
	}
}

Распознаём язык строки

$parser = new Language_Detector_CLD2();

$parser->detect('to recognize the text language', 'ru'); //en

$parser->detect('Распознать русский текст. Привет, медвед.'); //ru

Для более качественного распознавания коротких строк можно передавать второй и третий параметры - $languageHint и $domainHint.

Например, если вы распознаете язык определенного сайта, то $languageHint - предполагаемый язык можно взять из мета-тегов сайта или хедера accept-charset или accept-encoding. А $domainHint - это tld домена.

 
 
 
 

icon Комментарии 0

Ваш комментарий к статье.. (для авторизованных)

ctrl+enter

icon Вход в систему

зарегистрироваться
НОВЫЕ ПОЛЬЗОВАТЕЛИ