Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум PHP

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Помогите написать скрипт проверки текста на уникальность)
 
 автор: gfddrg   (09.06.2013 в 08:27)   письмо автору
 
 

Всем привет, очень слаб в пхп и по этому несколько недель уже бьюсь над написанием скрипта.
Вот что у меня получилось:
<?php

$db
=mysql_connect("localhost""mysql""mysql");
mysql_select_db("test"$db);
$res=mysql_query("SELECT * FROM data"$db);
$re=mysql_query("SELECT * FROM data"$db);
$r=mysql_query("SELECT * FROM data"$db);


$d=mysql_fetch_array($res);
$c=mysql_fetch_array($re);
do
{
$ce=$c['title'];
preg_match_all("/([а-б-в-г-д-е-ё-ж-з-и-й-к-л-м-н-о-п-р-с-т-у-ф-х-ц-ч-ш-щ-ъ-ы-ь-э-ю-я]+)/"$ce$out); //разбиваю текс на отдельные слова
$i 0;
while (
$i<count($out[0])) 
{

$ic=$i++;
//echo "<font color=\"#f01313\">".$out[0][$ic]."</font>"; //вывожу все части текста




$de=$d['title'];
preg_match_all("/([а-б-в-г-д-е-ё-ж-з-и-й-к-л-м-н-о-п-р-с-т-у-ф-х-ц-ч-ш-щ-ъ-ы-ь-э-ю-я]+)/"$de$ou); //разбиваю большое количество текстов на отдельные слова
$id 0;
while (
$id<count($ou[0])) 
{
$ide=$id++;
echo 
"<font color=\"#f01313\">".$out[0][$ic]."</font>"
echo 
"<font color=\"#536f46\">".$ou[0][$ide]."</font><br />";
}
}

}
while(
$d=mysql_fetch_array($res));



?>


Код выводит и может сравнивать один текст со всеми текстами что есть в базе. Я не могу следующее, есть много текстов в базе которые нужно между собой проверить на уникальность, я могу только по одному, тексту проверять, как сделать в автоматическом режиме проверку всех текстов? Может кто подсказать? Буду рад любой помощи)

  Ответить  
 
 автор: DangerBay   (09.06.2013 в 17:20)   письмо автору
 
   для: gfddrg   (09.06.2013 в 08:27)
 

сравнивать один текст со всеми текстами что есть в базе

Зачем и по какому критерию вообще можно сравнивать 2 разных текста?
Каким образом идет сравнение разных текстов в приведенном куске кода? Этого там просто нет.

  Ответить  
 
 автор: gfddrg   (10.06.2013 в 03:59)   письмо автору
 
   для: DangerBay   (09.06.2013 в 17:20)
 

Если добавить

<?php
$u
=$out[0][$ic];
$o=$ou[0][$ide];
if(
$u==$o)echo"есть совпадения"; else echo"совпадений нет";
?>

То скрипт будет искать похожие слова.
Я делаю этот скрипт для парсинга анекдотов, я парсю с разных сайтов, и естественно на разных сайтах попадаются одинаковые или слегка похожие анекдоты, чтоб они не добавлялись мне нужно сравнивать их с теми что у меня уже есть в базе, либо добавлять все без разбору и уже потом сортировать скриптом, чтоб парсинг проходил более легко.

  Ответить  
 
 автор: DangerBay   (10.06.2013 в 04:39)   письмо автору
 
   для: gfddrg   (10.06.2013 в 03:59)
 

Это бред. А если слова переставлены местами или нет пары слов, а всё остальное одинаковое?
В вашем случае лучше воспользоваться готовым решением.
http://utext.rikuz.com/
Там описано как это работает и исходный код даже есть.
Имеет смысл определять уникальность по проценту схожести. Если, скажем, больше 30% с матрицей по 1-му слову (1 шингл там называют), то 2 текста уже не уникальны.

Получаете все тексты из БД одним запросом.
В цикле каждый текст прогонять через этот алгоритм со всеми остальными текстами и удалять из БД неуникальный.
Может выйти ресурсоёмкая операция, если анекдотов очень много, а ресурсы хостинга ограничены. Поэтому лучше вести лог провереных текстов, чтоб при прерывании работы скрипта не пришлось всё заново прогонять.

  Ответить  
 
 автор: gfddrg   (10.06.2013 в 05:20)   письмо автору
 
   для: DangerBay   (10.06.2013 в 04:39)
 

Скрипт выводит слова примерно по такому принципу:
1анекдото1слово 2анекдот1слово
1анекдото1слово 2анекдот2слово
1анекдото1слово 2анекдот3слово

1анекдото2слово 2анекдот1слово
1анекдото2слово 2анекдот2слово
1анекдото2слово 2анекдот3слово

1анекдото3слово 2анекдот1слово
1анекдото3слово 2анекдот2слово
1анекдото3слово 2анекдот3слово

По этому все слова проверяются между собой. Этот скрипт не доделан, конечно будет процентное вычисление. Если будут совпадения, у анекдотов, то в таблицу запишутся ид анекдотов в которых нашлось совпадение и количество слов в них, каждое совпадение будет соответствовать одной строке. В базе данных будут такие записи

ид первого анекдота [1] | ид второго анекдота [2] | слов в первом анекдоте [3] | слов во втором анекдоте [3]

Сколько совпадений столько и строк будет записываться у пары проверяющихся анекдотов, допустим у 1 и 2 анекдота два одинаковых слова,тогда будет записано две строки в базу:

ид первого анекдота [1] | ид второго анекдота [2] | слов в первом анекдоте [3] | слов во втором анекдоте [3]
ид первого анекдота [1] | ид второго анекдота [2] | слов в первом анекдоте [3] | слов во втором анекдоте [3]

Дальше производится расчёт процентов, который у меня пока не совсем точен, слаживаем количество слов первого и второго анекдота(3+3), подсчитываем количество строку у пары анекдотов 1 и 2 их получилось 2 строки, эти две строки мы умножаем на 100% и делим на общее количество слов, у нас их 6, в итоге получаем процент совпадений, который как я уже писал не совсем точный.

  Ответить  
 
 автор: Deed   (10.06.2013 в 16:40)   письмо автору
 
   для: gfddrg   (10.06.2013 в 05:20)
 

Есть одна идея... Ща, проработаю ее, оформлю и поделюсь.

  Ответить  
 
 автор: gfddrg   (10.06.2013 в 18:30)   письмо автору
 
   для: Deed   (10.06.2013 в 16:40)
 

Ждёмс с нетерпением :)

  Ответить  
 
 автор: Deed   (10.06.2013 в 18:43)   письмо автору
 
   для: gfddrg   (10.06.2013 в 18:30)
 

Вот: http://phpfiddle.org/main/code/kga-esd
phpfiddle.org работает по-умолчанию с UTF-8, поэтому для windows-1251 поменяйте подсчет символов в элементе массива (ф-ция lazy()) c mb_strlen() на strlen().

  Ответить  
 
 автор: Deed   (10.06.2013 в 19:01)   письмо автору
 
   для: Deed   (10.06.2013 в 18:43)
 

То есть, чтобы уменьшить количество хранимой информации, мы каждое слово анекдота (если в нем более одной буквы) преобразовываем к виду: первая буква и количество символов, типа "Офигеть" -> "o7".
Затем мы сравниваем два анекдота и получаем массив со всеми совпадениями из первого.
Подсчитываем количество совпадений и, если их более 30% сообщаем, что анекдот "с бородой".

После прогона анекдота через rich(), можно преобразовать массив в строку (она не будет большой) с каким-то разделителем и хранить ее в базе вместе с текстом.
При поступлении нового анекдота мы делаем explode () с ней по нашему разделителю и проверяем этот новый текст, предварительно прогнав его через всю ту же ф-цию rich().

  Ответить  
 
 автор: gfddrg   (10.06.2013 в 19:06)   письмо автору
 
   для: Deed   (10.06.2013 в 18:43)
 

Вот тут я нашёл что то новое для себя и не совсем понимаю как это работает, чисто так на интуиции понимаю, попытался изменить один из анекдотов, сделал их полностью разными, но всё равно пишет что очень много совпадений, где-то, кто-то сильно перемудрил :) Но я всё очень рад что вы мне помогаете) Все помогаете) Возможно я возьму другие функции и по другому напишу скрипт, но пока мне надо просто узнать как циклично выводить данные из базы данных. Пример:
первый текст -> все тексты что есть в базе
второй текст -> все тексты что есть в базе
третий текст -> все тексты что есть в базе
и так далее.

  Ответить  
 
 автор: Deed   (10.06.2013 в 19:24)   письмо автору
 
   для: gfddrg   (10.06.2013 в 19:06)
 

Та ну.
Можно упростить lazy(), (http://phpfiddle.org/main/code/9uz-2u0) если не жалко места, или, что лучше, увеличить порог $check>30 до 60%-70%
$check>70.

  Ответить  
 
 автор: gfddrg   (10.06.2013 в 19:33)   письмо автору
 
   для: Deed   (10.06.2013 в 19:24)
 

Я пока увольняюсь, более подробно надо узнать как работает кое-что из написанного вами, так как я не всё знаю)

  Ответить  
 
 автор: Deed   (10.06.2013 в 19:38)   письмо автору
 
   для: gfddrg   (10.06.2013 в 19:33)
 

Там ошибка была:
Не $check=$cnt1/$cnt_intersect*100;
А $check=$cnt_intersect/$cnt1*100;
http://phpfiddle.org/main/code/0py-bvh

  Ответить  
 
 автор: confirm   (10.06.2013 в 18:09)   письмо автору
 
   для: gfddrg   (09.06.2013 в 08:27)
 

Чтобы разбить текст на отдельные слова, достаточно:

1) Разбит строку на массив по пробелу, функцией array_map() с вызовом функции trim() очистить пустые элементы, удалив их затем функцией array_diff(). Функцией array_count_values() узнать сколько раз каждое слово встречается в тексте.

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

  Ответить  
 
 автор: gfddrg   (10.06.2013 в 18:29)   письмо автору
 
   для: confirm   (10.06.2013 в 18:09)
 

Как я понял по данному примеру, подсчитывается просто количество слов в том или ином тексте, затем необходимо произвести сравнение с другим текстом, получится мне кажется намного сложнее, или я ошибаюсь? К стати, таким способом я хотел более точно подсчитывать процент совпадения, так как он получается не точным только благодаря тому что в словах могут по несколько раз встречаться одинаковые слова и они дают гораздо больше совпадений, в итоге может получится что процент совпадений будет намного больше чем есть на самом деле.

  Ответить  
 
 автор: confirm   (10.06.2013 в 18:51)   письмо автору
 
   для: gfddrg   (10.06.2013 в 18:29)
 

А вы что делаете - бьете текст на слова, а затем уже... Вот только делаете вы это ужасным способом.
А что такое вообще уникальность? Можно ли считать два текста уникальными, если их содержание идентично, но написаны они разными словами? Вряд ли. Уникальность, это неповторимость, и просто сравнением одни только слов вы ничего не узнаете, как бы вы их не получали.

  Ответить  
 
 автор: gfddrg   (10.06.2013 в 18:58)   письмо автору
 
   для: confirm   (10.06.2013 в 18:51)
 

Сори, я чёт не правильно пишу вроде, мне нужно найти совпадающие анекдоты, для того чтоб не пропустить их базу данных, уникальность текстов мне не нужна. Я делаю сайт для людей, нужно просто много не повторяющихся анекдотов и всё.

  Ответить  
 
 автор: confirm   (10.06.2013 в 19:07)   письмо автору
 
   для: gfddrg   (10.06.2013 в 18:58)
 

Ну а что вы делаете для этого? Разбиваете на слова, а затем высчитываете проценты вхождения. А я вам что пишу? Тоже самое, если вы не догадываетесь как потом из массива числа вхождений найти их проценты в тексте, то какие проблемы:
<?
$wrd 
array_map(function($v) use($wrd) {
    return 
round($v/array_sum($wrd)*1001); 
}, 
$wrd);
Сравнивайте. Некая схожесть, это уже иное, но ведь и тут подводные камни. Почему нельзя допустить, что слова в двух текстах могут иметь близкие проценты, а по сути тексты разные будут?

  Ответить  
 
 автор: gfddrg   (10.06.2013 в 19:30)   письмо автору
 
   для: confirm   (10.06.2013 в 19:07)
 

Нельзя физически получить результат чтоб у двух текстов было совпадений в словах 50% и чтоб они по значению были разными, такого не бывает в природе, по крайней мере я так думаю)

  Ответить  
 
 автор: confirm   (10.06.2013 в 20:02)   письмо автору
 
   для: gfddrg   (10.06.2013 в 19:30)
 

Думаете вы или нет, но процентное сравнение все равно будет давать ошибку.

У вас есть текст А1, который нужно сравнить с новым текстом А2.

Вышепоказанным способом вы получаете массивы этих текстов M1 и M2, ключами которых являются слова в них, а значениями процент вхождения в текст.

M3 = array_intersect_key(M1, M2) - получаете массив пересечения этих слов. Если число элементов полученного массива равно числу элементов массива M1, то в обеих этих текстах имеются одни и те же слова. То есть совпадение самих слов 100%. Естественно можно просчитать и процент схожести вхождения слов между M1 и M3 (count(M1)/count(M3)*100), и уже опираясь на эту величину решаете, производить ли сравнение процентов вхождения каждого из совпадающих слов этих текстов (ключей M3) в текстах (значениях M1 и M2). А уже на их сравнении (доли) решаете.

Но русский язык таков, что слова переставь и смысл иной, или просто знак препинания - казнить, нельзя помиловать и казнить нельзя, помиловать. То есть ошибки все равно неизбежны.

  Ответить  
 
 автор: gfddrg   (11.06.2013 в 04:54)   письмо автору
 
   для: confirm   (10.06.2013 в 20:02)
 

Спасибо большое, я приму всё к сведению. Скоро выложу изменённый скрипт, посмотрите на него и дадите свою оценку)

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования