Usuario anónimo ¿Quieres tener tu propio blog?
Crear blog gratis en OboLog

Buscador en PHP

por obokaman
viernes, 10 de diciembre del 2004 a las 00:18
guardado en , ,

Bueeeno, aquesta nit toca post tècnic, que ja he aconseguit _quasi_ acabar una de les parts que trobo més interessant del blog: el cercador. Amb el pas del temps la quantitat d'informació enregistrada a la web ha augmentat considerablement, i sense una bona categorització i organització dels continguts, certs missatges corren el perill de caure en l'oblit. En aquest sentit, tenir un arxiu de missatges agrupats per categories o data pot ser molt útil, però perd efectivitat quan parlem de categoríes amb més de 100 missatges. Trobar un post concret es pot convertir en tota una aventura. És aqui on es posa a prova la utilitat d'un cercador eficient.

La majoria de cercadors que he pogut veure a altres llocs web es limiten a fer cerques per paraules a la base de dades, permetent fer la cerca al títol, al contingut de la web, a paraules clau, etc... i utilitzant operadors del tipus "LIKE" per trobar coincidències amb els termes de recerca. Aquest sistema presenta força limitacions, com haver de repetir la cerca per separat per cada paraula, especificar per separat tots els camps de la base de dades on s'ha de mirar, impossibilitat de donar més importància a unes paraules que d'altres, filtrar paraules de poca rellevància... És aqui on vaig descobrir la utilitat d'un tipus d'index que utilitza MySQL, anomenat "FULL TEXT". La troballa de l'any, certament. El "FULL TEXT" ens permet agrupar diversos camps en un sol índex, per poder realitzar-hi cerques conjuntes mitjançant una sola cadena de caràcters (una paraula o frase), i afegir-hi modificadors a l'estil Google. És a dir, podem utilitzar modificadors com les cometes, per agrupar paraules, els simbols < i > per especificar una major o menos rellevància de certa paraula, els simbols - o + per mostrar només resultats que contingin o no una paraula determinada... I tot això de manera automàtica, amb una consulta senzilla.

Un exemple ens ho farà més fàcil d'entendre: Imagineu que vull buscar un manual de photoshop a la web. La consulta que realitzaria a la base de dades, on prèviament he creat un índex FULL TEXT per a certs camps que m'interessen seria

SELECT * FROM posts WHERE MATCH(titulo,descripcion,contenido,contenido_ext,tipo) AGAINST ('manual de photoshop')

Llestos, així de senzill. Les cerques de FULL TEXT ens permeten, a més, conèixer la rellevància (el camp score) de les coincidències per a cada registre trobat. Així podem tambè ordenar els resultats segons s'acostin més o menys al que buscàvem. Això ho fariem de la següent manera.

SELECT *,MATCH(titulo,descripcion,contenido,contenido_ext,tipo) AGAINST ('manual de photoshop') as score FROM posts WHERE MATCH(titulo,descripcion,contenido,contenido_ext,tipo) AGAINST ('manual de photoshop') ORDER BY score desc;

Només amb això ja disposariem d'una eina força potent per trobar informació a una base de dades (els índex FULL TEXT permeten cerques molt més complexes que aquestes, això us ho deixo investigar a les pròpies especificacions de la página de MySQL). Ens trobem, però, que tan sols un llistat amb el títol dels missatges en què hem trobat continguts interessants pot no ser útil, si la cerca no és suficientment acurada, i tots sabem per experiència que afinar amb les paraules correctes no és tasca senzilla. És aqui on em vaig plantejar de implantar un sistema d'extracció de texte rellevant per la pàgina de resultats del cercador. De nou el sistema de Google que ens mostra la part de la pàgina on apareixen les paraules que estem buscant, em va semblar la millor opció. D'un sol cop d'ull pots veure si aquell missatge on apareixen els termes que busques parla realment del que volíes, ja que no necessàriament ha de ser sempre així.

El que faig es separar cada una de les paraules, eliminar les paraules massa curtes, i veure a quina posició dins del contingut del missatge es troben la resta. Després ordeno aquestes posicions i busco aquella part del texte on aquest termes es troben més aprop entre ells, per mostrar-la a mode d'extracte. Aquest seria l'exemple en PHP, que és el llenguatge en què s'ha programat obokaman.com

$busca_ace = array ("á","é","í","ó","ú","Á","É","Í","Ó","Ú","à","è","ì","ò","ù","À","È","Ì","Ò","Ù","+","<",">");
$reemplaza_ace = array ("a","e","i","o","u","A","E","I","O","U","a","e","i","o","u","A","E","I","O","U"," "," "," ");

$buscar=trim(strtolower($texto));
$buscar=str_replace($busca_ace, $reemplaza_ace, $buscar);

$texto_tmp=explode(" ",$buscar);
foreach ($texto_tmp as $valor) {

if (strlen($valor)>3) {
$texto_tmp2[]=$valor;
}else{
$texto_tmp3[]=$valor;
}

}
if (is_array($texto_tmp2)) {
$texto_incluido=implode(",",$texto_tmp2);
}
if (is_array($texto_tmp3)) {
$texto_omitido=implode(",",$texto_tmp3);
}

Ara tenim les paraules que ens interessen (les més llargues de 3 caràcters) a un array anomenat $texto_tmp2. Només caldrà recòrrer aquest array a cada missatge per cercar les coincidències, mirar la seva posició, i destacar cada paraula al texte resultant.

$text1=html_entity_decode($mensaje);
$text1=str_replace($busca_ace, $reemplaza_ace, $text1);
$text1=preg_replace('/[\n\r\t]/',' ',$text1);
if (is_array($texto_tmp2)) {//4
$posiciones= array();
foreach ($texto_tmp2 as $valor) {
$string=strtolower($text1);
$searched=strtolower($valor);
$offsets= array();
$next=0;

while(1){
$entry = strpos(
$string,
$searched,
$next+$offsets[sizeof($offsets)-1] /*juggling*/
);
if(gettype($entry)==boolean){break;};
$next=strlen($searched);
$offsets[]=$entry;
}

$posiciones=array_merge($posiciones,$offsets);
}
sort($posiciones);
for ($i=0;$i
$n=1;
while ($posiciones[($i+$n)]&&($posiciones[($i+$n)]-$posiciones[$i])<500) {
if ($n>$max) {
$max=$n;
$posicion_def=$posiciones[$i];
}
$n++;
}
}
if ($posicion_def) {
$posicion1=$posicion_def;
}else{
$posicion1=$posiciones[0];
}
if ($posicion1>60) {
$posicion1=$posicion1-60;
}else{
$posicion1=0;
}
unset($posicion_def);
unset($posiciones);
unset($offsets);
unset($max);
}
$text1 = substr(trim($text1),$posicion1,500);
if ($text1!="") {
$text1 = '[...]'.$text1.'[...]';
}
foreach ($texto_tmp2 as $valor) {
$text1 = eregi_replace("($valor)","\\1",$text1);
}

$mensaje és la variable que conté tot el text de cada post. Primer busquem les posicions de les coincidències. Després busquem la posició més alta en què les paraules es trobin més properes entre elles (al menys de 500 caràcters entre cadascuna), i finalment, utilitzem aquesta posició per fer un extracte de 500 caràcters d'aquesta porció del text, destacant cada paraula amb un . Això, a mode d'esboç, és el que fa el cercador d'obokaman per cercar i mostrar els resultats. És el millor de fer les coses a mà: que fan exactament el què tu vols. Estaré encantat de sentir les teves suggerències, crítiques, consells per millorar aquest sistema. Encara no l'has provat?

Mensajes relacionados

Comentarios

iñaki iñaki
me parece cojonuda la informacion de la pagina, sobre todo por estar en catalan, el cual muchos de nosotros (por no decir la mayoria), no entendemos, pero veo que eso en gente como los creadores de esta pagina, pasa desapercibido, pero bueno, se ve para donde tira cada uno....... sobre todo en un dominio ".com". Debe ser por la rabieta de no permitir el dominio ".cat".
Es una lástima, amigo iñaki, que no te hayas molestado en fijarte que al lado de TODOS los mensajes existe un enlace para traducir cualquiera de los posts de este blog, tanto del catalán al castellano como viceversa. Y es realmente molesto leer como hablan de ti sin tener ni puñetera idea de qué estan tratando. A qué te refieres con lo de "pero bueno, se ve para donde tira cada uno....... sobre todo en un dominio ".com". Debe ser por la rabieta de no permitir el dominio ".cat"." La verdad es que me dejas atónito... ¿Para dónde dices que tiro?
jajaja un poco mas y te manda a los grises xDD nada chaval a aprender mas php y menos codigos hechos que asi no te tienes que preocupa de leer textos en castellano xD PD: soy andaluz eee y si tiro mas pa la izquierda xDDD
anusca anusca
estoy totalmente de acuerdo con iñaki..q es esto de que ete primero en catalan?si..por la rabieta de .cat..y quien no entienda q quiere decir lo de tirar pa un lao...y lo de .cat...anda muy despistao del momento q españa esta viviendo...pero bueno...q de no ser por el catalan...la pagina esta muy bien!
Lo que hay que oir y aguantar... Con extremos como estos entiendo perfectamente que existan los opuestos... Cómo vamos a llevarnos bien?
skirlappa skirlappa
Pero haber si os enterais xDDD q la pagina esta en los dos idiomas...yo te aconsejo obokaman que el proximo manual que cuelgues sea "como darle al botoncito para traducir la pagina" xDDD y ya despues empezamos con php xDD
Marc Marc

Utilitzan el SELECT MATCH AGAINST no pots fer el que amb like seria '%paraula%'.

Exemple: busca tot el que tingui 'come' --> 'outcome' i 'comer'. aixo no es pot fer amb aquest sistema o si???

Hola Marc,

sí que ho pots fer, fent servir el wildcard "*". Fes una ullada a la referència oficial de MySQL sobre les recerques BOOLEAN amb FULL TEXT.

Deja tu comentario

Deja tu Comentario
Necesitas tener javascript activado para poder dejar comentarios

Identifícate en OboLog, o crea tu blog gratis si aún no estás registrado.

De esta forma, además, podrás mostrar tu imagen en los comentarios y no tendrás que rellenar tus datos cada vez.

Sobre esta anotación

obokaman

obokaman escribió esta anotación hace 3 años. En ella habla sobre Buscadores, Desarrollo Web y Php.

8 personas han dejado ya sus comentarios.

Tú también puedes dejar el tuyo.

Login

Comentarios

Campaña contra el abandono de animales (Anónimo)
me parese que no es muy bueno abandonar animales...(14 may)
Guiños humorísticos en CSSEdit 2 (raul)
gilipollas eso es lo que sois  vais a llorar...(07 may)
Guiños humorísticos en CSSEdit 2 (Anónimo)
DDDDDDDDDDDDDDDDDDDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD...(05 may)
Para triunfar hay que renunciar a la vida personal (Duhamel)
Yo creo que el éxito es muy relativo y pienso nadie que renuncie a su vida personal es un ...(03 may)
Realidad aumentada desde Android (obokaman)
Jajaja... pues no, no son amigos míos, pero sí que es verdad que hacen cara de nece...(02 may)

Más comentados

Disco duro para tu ps2 (500)
Conectar un disco duro a tu Playstation 2, hacer copias de seguridad de tus juegos a ese disco ...
Esa bonita canción entre anuncio y anuncio (308)
Se llaman Múm y la canción se titula Green Grass of Tunnel.
Descripción y fuentes del upload PHP + AJAX con barra de progreso (121)
Código fuente y pequeña descripción de la implementación para conseguir un upload de archivos con PHP & Ajax
Català - Valencià (94)
Sobre les discusions que genera la denominació de la nostra llengua.
Audio en tus Posts II (87)
Pequeño tutorial acerca de cómo implementar el reproductor que ayer mismo presentaba en obokaman.com

Suscripción

Suscríbete al Feed RSS XML

También puedes suscribirte directamente con alguno de los siguientes enlaces:

  • Suscríbete en Bloglines
  • Suscríbete en Google