Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

«Новости по теме» с поддержкой PHP, phpmorphy и MySQL

Anna | 31.05.2014 | нет комментариев

Хочу поделиться способом определения «схожих» записей. Думаю, будет благотворно для блогов либо новостных источников.
Цель данного поста показать правило, имплементация может быть не вовсе комильфо, так как автор не проф. программист, а любитель.

Выходит, задача

Новости хранятся в MySQL таблице типа:

Небходимо для всякой новости при итоге на странице определить максимально схожие из той же таблицы.
Тут нас волнует контент полей title, lead, body. Для простоты, будем считать что создаем все с нуля и не будем рассматривать надобность обработки теснее существующих записей.

Поле tags

Добавляем поле tags (на самом деле это псевдо-тэги, но нигде на сайте они показываться не будут — это поле необходимо экстраординарно для сопоставления текстов). Тип поля укажите как VARCHAR(512) и добавьте индекс типа fulltext ( FULLTEXT (tags) ).

Генерация псевдо-тэгов

Сгенерируем псевдо-тэги из полей title, lead, body перед записью новости в базу (непринужденно перед INSERT statement). Для этого загрузите phpmorphy и словари отсель.

Для исключения малозначащих слов (стоп-слов) сотворим массив $stopwords, будем применять текстовый файл для стоп-слов (пример — сбережете как stopwords.txt ).

$stopwords=explode("n", file_get_contents("stopwords.txt"));

Дальше, подключаем phpmorphy и его словари, объединяем title,lead и body и прогоняем все слова через phpmorphy.

Генерация псевдо-тэгов


$lowercaseLetters = array("'а'", "'б'", "'в'", "'г'", "'д'", "'е'", "'ё'", "'ж'", "'з'", "'и'", "'й'", "'к'", "'л'", "'м'", "'н'", "'о'", "'п'", "'р'", "'с'", "'т'", "'у'", "'ф'", "'х'", "'ц'", "'ч'", "'ш'", "'щ'", "'ъ'", "'ы'", "'ь'", "'э'", "'ю'", "'я'");
$uppercaseLetters = array("'А'", "'Б'", "'В'", "'Г'", "'Д'", "'Е'", "'Ё'", "'Ж'", "'З'", "'И'", "'Й'", "'К'", "'Л'", "'М'", "'Н'", "'О'", "'П'", "'Р'", "'С'", "'Т'", "'У'", "'Ф'", "'Х'", "'Ц'", "'Ч'", "'Ш'", "'Щ'", "'Ъ'", "'Ы'", "'Ь'", "'Э'", "'Ю'", "'Я'");

function cyrUpper($str)
{
global $lowercaseLetters;
global $uppercaseLetters;

return str_replace("'", "", preg_replace($lowercaseLetters, $uppercaseLetters, $str));
}
function cyrLower($str)
{
global $lowercaseLetters;
global $uppercaseLetters;

return str_replace("'", "", preg_replace( $uppercaseLetters,$lowercaseLetters, $str));
}

function cleanUP ($new_string)

{ 
//$new_string=nl2br($new_string);
 $new_string= str_replace("-"," ",$new_string);
  $new_string= str_replace("rn"," ",$new_string);
  $new_string= str_replace("r"," ",$new_string);
    $new_string= str_replace("n"," ",$new_string);
  $new_string= str_replace("."," ",$new_string);
$new_string = ereg_replace("[^0-9 абвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ]", "",$new_string );
return $new_string;
}

require_once( 'morphy/src/common.php');

$text=cleanUP($_REQUEST[title]." ".$_REQUEST[lead]." ".$_REQUEST[body]." ");
$aText = explode(' ',$text);
        $aPort = array();
        $aMorph = array();

        foreach ($aText as $word)

            $aMorph[] = cyrUpper($word);//нужно в вин1251 давать не сьедение

        // set some options
        $opts = array(
            'storage' => PHPMORPHY_STORAGE_FILE,
            // Extend graminfo for getAllFormsWithGramInfo method call
            'with_gramtab' => false,
            // Enable prediction by suffix
            'predict_by_suffix' => true,
            // Enable prediction by prefix
            'predict_by_db' => true );

      $dir = 'morphy/dicts';
$lang = 'ru_RU';

        // Create descriptor for dictionary located in $dir directory with russian language
        $dict_bundle = new phpMorphy_FilesBundle($dir, 'rus');

        // Create phpMorphy instance
        try {
            $morphy = new phpMorphy($dict_bundle, $opts);
        } catch(phpMorphy_Exception $e) {
            throw new Exception('Error occured while creating stemmer instance: ' . $e->getMessage());
        }

        try {

            if($getroot==22)
                $pseudo_root = $morphy->getPseudoRoot($aMorph);//можно либо взять корни слов
            else
                $pseudo_root = $morphy->getBaseForm($aMorph);//либо базовую форму
            //для нашей задачи $getroot=TRUE

        } catch(phpMorphy_Exception $e) {
            throw new Exception('Error occured while text processing: ' . $e->getMessage());
        }

foreach ($pseudo_root as $roots){

$slovo=cyrLower($roots[0]);
if (strlen( $slovo)>3 && !in_array($slovo,$stopwords) && count($roots)==1 ) {

$tags.=$slovo." ";  }

}

}

Полученный список тэгов в переменной $tags записываем в соотв. поле таблицы. В итоге для всякой новости в этом поле будет список слов тот, что мы и будем применять для сопоставления.

Пример

Начальный текст

Компания Samsung начала производство твердотельных жестких дисков с применением трехмерной памяти V-NAND. Спецтехнология разрешает увеличить объем накопителей, а так же обеспечивает в 2 раза больше высокую скорость передачи информации и повышает безопасность устройств до 10 раз. На данный момент создаются SSD диски объемом 480 и 960 ГБ, только для корпоративных серверов. Что же касается домашних компьютеров, то определенных сроков выпуска названо не было.

Сгенерированный список слов:

устройство увеличить только спецтехнология компания твердотельный срок создаваться скорость безопасность сервер производство разрешать повышать обеспечивать передача память объем начать накопитель момент корпоративный определенный компьютер касаться применение информация грубый диск высокий выпуск трехмерный

SQL запрос

Сейчас самое увлекательное- вот такой SQL запрос будет применяться для определения схожих записей:

 SELECT * FROM news WHERE  MATCH (tags)  AGAINST ('[ список псевдо тэгов ]'  ) > [значение релевантности]

Тут, значение релевантности это и есть «похожесть» текстов — поэкспериментируйте (начните с единицы)

Источник: programmingmaster.ru

Оставить комментарий
БАЗА ЗНАНИЙ
СЛУЧАЙНАЯ СТАТЬЯ
СЛУЧАЙНЫЙ БЛОГ
СЛУЧАЙНЫЙ МОД
СЛУЧАЙНЫЙ СКИН
НОВЫЕ МОДЫ
НОВЫЕ СКИНЫ
НАКОПЛЕННЫЙ ОПЫТ
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB