html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

«Новости по теме» с помощью PHP, phpmorphy и MySQL

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




Итак, задача

Новости хранятся в 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("\r\n"," ",$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 ('[ список псевдо тэгов ]'  ) > [значение релевантности]


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

материал с habrahabr.ru

8

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • nomad.bourjois
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции