Вторая часть статьи Яна Барбера об определении языка текста с помощью PHP. Первую часть можно найти тут.
Разбить на две части пришлось из-за большого объема текста с форматированием («Some error… We know...).
К сожалению, на моем компьютере не было особо большого количества материалов для построения моделей, но для этого сгодились многоязычные словари OSX. Убрав с помощью strip_tags XML теги, я получил чистый текст.
С построенным индексом мы теперь можем протестировать большое количество текстов на различных языках, чтобы убедиться в точности распознавания. Огромное спасибо Lorenzo, Soila (который говорит на огромном количестве различных языков) и Ivo за предоставленные примеры:
Как легко можно увидеть (результат работы скрипта слегка обрезан, чтобы сократить изложение), каждый язык был корректно определен:
Аналогичную операцию можно проделать с целымим вебсайтами, удалив HTML теги с помощью strip_tag. Целью послужили сайты трех локальных офисов Ibuildings:
Похоже, что на странице в домене NL все же больше английского текста, чем датского, поэтому он определелился как английский. Однако, с итальянским все прошло отлично:
Несмотря на то, что метод триграмм очень удобен и прост, он совершенно не обязательно является лучшим для использования в каждой ситуации. Например, если вам требуется метод, который работает без предварительного обучения или с минимальными затратами памяти, можно просто собрать список коротких, часто встречающихся слов в каждом языке (вроде артиклей и предлогов) и искать в заданном тексте только их.
Точно также, поиск Unicode символов, уникальных для заданного языка, может дать вам достаточную точность его определения.
Когда мы с Лоренцо обсуждали эту проблему, он упомянул, что в библиотеку PEAR уже включен пакет для определения языка текста, хотя и в альфа-версии. Он тоже использует метод триграмм, но располагает несколько более богатыми возможностями. Как и ожидалось, он достаточно прост в использовании, поддерживает Unicode и поставляется уже с готовой базой триграмм для некоторых языков, так что почти не нуждается в обучении. Для полноты картины мы попытались определить с его помощью языки тех же фрагментов текста:
Как и ожидалось, результат оказался аналогичным. Пакет можно легко установить из PEAR, используя команду
Разбить на две части пришлось из-за большого объема текста с форматированием («Some error… We know...).
К сожалению, на моем компьютере не было особо большого количества материалов для построения моделей, но для этого сгодились многоязычные словари OSX. Убрав с помощью strip_tags XML теги, я получил чистый текст.
<?php
$lang = new LangDetector();
$dir = "/Library/Dictionaries/Apple Dictionary.dictionary/Contents/Resources/";
$dutch = strip_tags(file_get_contents($dir . "Dutch.lproj/Body.data"));
$lang->adddocument($dutch, 'dutch');
$english = strip_tags(file_get_contents($dir . "English.lproj/Body.data"));
$lang->adddocument($english, 'english');
$finnish = strip_tags(file_get_contents($dir . "fi.lproj/Body.data"));
$lang->adddocument($finnish, 'finnish');
$spanish = strip_tags(file_get_contents($dir . "Spanish.lproj/Body.data"));
$lang->adddocument($spanish, 'spanish');
$italian = strip_tags(file_get_contents($dir . "Italian.lproj/Body.data"));
$lang->adddocument($italian, 'italian');
$french = strip_tags(file_get_contents($dir . "French.lproj/Body.data"));
$lang->adddocument($french, 'french');
$swedish = strip_tags(file_get_contents($dir . "sv.lproj/Body.data"));
$lang->adddocument($swedish, 'swedish');
?>
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.
С построенным индексом мы теперь можем протестировать большое количество текстов на различных языках, чтобы убедиться в точности распознавания. Огромное спасибо Lorenzo, Soila (который говорит на огромном количестве различных языков) и Ivo за предоставленные примеры:
<?php
$italian = "
Nel mezzo del cammin di nostra vita
mi ritrovai per una selva oscura
ché la diritta via era smarrita.
";
echo $italian, "\n", "is ", $lang->detect($italian), "\n";
$finnish = "
Suomalainen on sellainen, joka vastaa kun ei kysytä,
kysyy kun ei vastata, ei vastaa kun kysytään,
sellainen, joka eksyy tieltä, huutaa rannalla
ja vastarannalla huutaa toinen samanlainen.
";
echo $finnish, "\n", "is ", $lang->detect($finnish), "\n";
$dutch = "
zoals het klokje thuis tikt, tikt het nergens
";
echo $dutch, "\n", "is ", $lang->detect($dutch), "\n";
$spanish = "
Por qué los inmensos aviones
No se pasean com sus hijos?
Cuál es el pájaro amarillo
Que llena el nido de limones?
Por qué no enseñan a sacar
Miel del sol a los helicópteros?
";
echo $spanish, "\n", "is ", $lang->detect($spanish), "\n";
$swedish = "
Och knyttet tog av skorna och suckade och sa:
hur kan det kännas sorgesamt fast allting är så bra?
Men vem ska trösta knyttet med att säga: lilla vän,
vad gör man med en snäcka om man ej får visa den?
";
echo $swedish, "\n", "is ", $lang->detect($swedish), "\n";
?>
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.
Как легко можно увидеть (результат работы скрипта слегка обрезан, чтобы сократить изложение), каждый язык был корректно определен:
Nel mezzo del cammin...
is italian
Suomalainen on sellainen...
is finnish
zoals het klokje thuis tikt, tikt het nergens
is dutch
Por que los inmensos...
is spanish
Och knyttet tog av...
is swedish
Аналогичную операцию можно проделать с целымим вебсайтами, удалив HTML теги с помощью strip_tag. Целью послужили сайты трех локальных офисов Ibuildings:
<?php
$nl = strip_tags(file_get_contents('www.ibuildings.nl'));
echo "IB NL reads as: " . $lang->detect($nl), "\n";
$uk = strip_tags(file_get_contents('www.ibuildings.co.uk'));
echo "IB Uk reads as: " . $lang->detect($uk), "\n";
$it = strip_tags(file_get_contents('www.ibuildings.it'));
echo "IB IT reads as: " . $lang->detect($it), "\n";
?>
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.
Похоже, что на странице в домене NL все же больше английского текста, чем датского, поэтому он определелился как английский. Однако, с итальянским все прошло отлично:
IB NL reads as: english
IB UK reads as: english
IB IT reads as: italian
Другие методы
Несмотря на то, что метод триграмм очень удобен и прост, он совершенно не обязательно является лучшим для использования в каждой ситуации. Например, если вам требуется метод, который работает без предварительного обучения или с минимальными затратами памяти, можно просто собрать список коротких, часто встречающихся слов в каждом языке (вроде артиклей и предлогов) и искать в заданном тексте только их.
Точно также, поиск Unicode символов, уникальных для заданного языка, может дать вам достаточную точность его определения.
PEAR: Text_LanguageDetect
Когда мы с Лоренцо обсуждали эту проблему, он упомянул, что в библиотеку PEAR уже включен пакет для определения языка текста, хотя и в альфа-версии. Он тоже использует метод триграмм, но располагает несколько более богатыми возможностями. Как и ожидалось, он достаточно прост в использовании, поддерживает Unicode и поставляется уже с готовой базой триграмм для некоторых языков, так что почти не нуждается в обучении. Для полноты картины мы попытались определить с его помощью языки тех же фрагментов текста:
<?php
require_once 'Text/LanguageDetect.php';
function detect($text, $l) {
$result = $l->detect($text, 1);
if (PEAR::isError($result)) {
return $result->getMessage();
} else {
return key($result);
}
}
$l = new Text_LanguageDetect();
$italian = "
Nel mezzo del cammin di nostra vita
mi ritrovai per una selva oscura
ché la diritta via era smarrita.
";
echo $italian, "\n", "is ", detect($italian, $l), "\n";
// ...остаток удален для краткости, но результат аналогичен
?>
Этот исходный код отформатирован с помощью FractalizeR's HabraSyntax Source Code Highlighter.
Как и ожидалось, результат оказался аналогичным. Пакет можно легко установить из PEAR, используя команду
pear -d preferred_state=alpha install Text_LanguageDetect