Поиск похожих текстов в базе данных MySQL + PHP

Один из вариантов поиска похожих статей в базе данных основан на схождении слов в двух текстах.

Данный алгоритм не обладает точным результатом, но позволяет выявить явные дубли.

Для поиска понадобится функция, которая очистит текст от html-кода, лишних слов и вернёт массив слов.

function get_minification_array($text)
{
    // Удаление экранированных спецсимволов
    $text = stripslashes($text);   
    
    // Преобразование мнемоник
    $text = html_entity_decode($text);
    $text = htmlspecialchars_decode($text, ENT_QUOTES);   
    
    // Удаление html тегов
    $text = strip_tags($text);
    
    // Все в нижний регистр
    $text = mb_strtolower($text);   
    
    // Удаление лишних символов
    $text = str_ireplace('ё', 'е', $text);
    $text = mb_eregi_replace("[^a-zа-яй0-9 ]", ' ', $text);
    
    // Удаление двойных пробелов
    $text = mb_ereg_replace('[ ]+', ' ', $text);
    
    // Преобразование текста в массив
    $words = explode(' ', $text);
    
    // Удаление дубликатов
    $words = array_unique($words);
 
    // Удаление предлогов и союзов
    $array = array(
        'без',  'близ',  'в',     'во',     'вместо', 'вне',   'для',    'до',
        'за',   'и',     'из',    'изо',    'из',     'за',    'под',    'к', 
        'ко',   'кроме', 'между', 'на',     'над',    'о',     'об',     'обо',
        'от',   'ото',   'перед', 'передо', 'пред',   'предо', 'по',     'под',
        'подо', 'при',   'про',   'ради',   'с',      'со',    'сквозь', 'среди',
        'у',    'через', 'но',    'или',    'по'
    );
 
    $words = array_diff($words, $array);
 
    // Удаление пустых значений в массиве
    $words = array_diff($words, array(''));   
 
    return $words;

}

PHP
Пример работы функции:

$array = get_minification_array('
    <p>Сегодня существует огромное множество разнообразных диет,
    отличающихся степенью строгости и результатами, которых с их
    помощью добиваются худеющие. Существует одна эффективная диета
    творог + яблоки, которая позволит легко скинуть 4 кг за 4 дня.</p>
');
 

print_r($array);

PHP
Результат:

Array
(
    [0] => сегодня
    [1] => существует
    [2] => огромное
    [3] => множество
    [4] => разнообразных
    [5] => диет
    [6] => отличающихся
    [7] => степенью
    [8] => строгости
    [10] => результатами
    [11] => которых
    [13] => их
    [14] => помощью
    [15] => добиваются
    [16] => худеющие
    [18] => одна
    [19] => эффективная
    [20] => диета
    [21] => творог
    [22] => яблоки
    [23] => которая
    [24] => позволит
    [25] => легко
    [26] => скинуть
    [27] => 4
    [28] => кг
    [31] => дня

)

Для более точного результата можно удалить из текста все стоп-слова.

Теперь, нужно получить проверяемую статью и сверить с остальными. В примере используется таблица `articles`, с полями `id`, `name`, `text`:
Пример таблицы со статьями

Поиск будет осуществляется для статьи `id` = 1, причём для теста в базе есть копия этой статьи с немного измененным текстом.

// Подключение к БД
$dbh = new PDO('mysql:dbname=db_name;host=localhost', 'логин', 'пароль');
 
// Получаем статью
$sth = $dbh->prepare("SELECT * FROM `articles` WHERE `id` = 1");
$sth->execute(array());
$article = $sth->fetch(PDO::FETCH_ASSOC);
 
// Получаем для неё массив слов
$text = get_minification_array($article['name'] . ' ' . $article['text']);
 
$count = count($text);   
$out = array();
 
// Проход по всем статьям в таблице
$sth = $dbh->prepare("SELECT * FROM `articles`");
$sth->execute();   
$list = $sth->fetchAll(PDO::FETCH_ASSOC);
 
foreach($list as $row) {
    $verifiable = get_minification_array($row['name'] . ' ' . $row['text']);
 
    $similar_counter = 0;
    foreach ($text as $text_row) {
        foreach ($verifiable as $verifiable_row){
            if($text_row == $verifiable_row) {
                $similar_counter++;
                break;
            }
        }
    }
    $out[$row['name']] = $similar_counter * 100 / $count;
}
 
// Сортировка результатов и ограничение до 15шт
arsort($out);
$out = array_slice($out, 0, 15, true);
 

print_r($out);

PHP
Результат поиска:

Array
(
    [Диета на яблоках и твороге] => 100
    [Диета на яблоках и твороге (test)] => 97,368421052632
    [Диета Ларисы Гузеевой] => 21,052631578947
    [Как похудеть в лице] => 19,736842105263
    [Соевый соус: польза и вред] => 17,105263157895
    [Сырная диета] => 14,473684210526
    [Какую обувь выбрать для сильных морозов?] => 13,157894736842
    [Какие мышцы работают на эллиптическом тренажере?] => 10,526315789474
    [Боль в коленном суставе при нагрузке] => 9,2105263157895
    [Польза и вред дыни для организма человека] => 9,2105263157895
    [Разгрузочная диета после праздников] => 9,2105263157895
    [Вредно ли загорать на солнце?] => 7,8947368421053
    [Йогуртовая диета] => 7,8947368421053
    [Как стирать пуховое одеяло?] => 7,8947368421053
    [Какие витамины в укропе] => 6,5789473684211

)

В результате видно, что статья схожа сама с собой на 100%, с тестовой статьей на 97%, с остальными не более 21%.
Источник: Перейти
Комментарии (0):
Чтобы оставить свой комментарий, необходимо пройти аутентификацию