Como hacer lo que hace Wikipedia (PHP)

EnZo

Cuando tu te metes en un documento de wikipedia, si este documento tiene palabras que tambien se encuentran en la base de datos de wikipedia, este las subraya y te pone el enlace para ir a esa definicion.

Ami me gustaria hacer algo parecido, no se me ocurre nada que coma pocos recursos. Supongamos que tenemos miles y miles de palabras. Yo las meteria todas en un array y al imprimir el documento miraria palabra por palabra en el documento para ver si existe en el array, y si existe pues subrayo. Pero claro cuanto mas grande sea el diccionario de palabras mas recursos come. Y pueden ser bucles muy grandes cada vez que se imprima una pagina, es decir que lo veo poco optimo.

Se os ocurre alguna idea para ligerar este proceso?

Gracias.

erdanblo

Ni idea, pero siempre te puedes bajar el sistema Wiki y mirar su código fuente, que para algo es libre :]

javithelong

Si mantienes las palabras ordenadas en ese array, una busqueda binaria hace ese 'consumo' mucho menor.

Y ya si te pones a hacer heaps y movidillas guapas, el tiempo es bastante aceptable (el tiempo de acceso a un dato en una tabla hash es realmente pequeño, casi despreciable).

Vamos, no tengo ni idea de cómo lo hace, pero con estos tipos de datos y algoritmos se consiguen tiempos muy buenos de búsqueda.

cabron

La Wikipedia usa Wikimedia, que es de código abierto, puedes bajarte el código y echar un vistazo.

BlisZ

os podeis cagar para encontrar cualquier tonteria en wikimedia... lo digo por experiencia

lo unico que se me ocurre es meter cada paalbra en un array e ir recorriendo y comparando aunque supongo que sera bastante lento :S

EnZo

Tengo dos opciones bastante buenas. Una es meterlo en un array con el nombre de la palabra como indice del array:

$vocabulario['lamer'] = true;
$vocabulario['noob'] = true;
$vocabulario['pakete'] = true;
$vocabulario['lol'] = true;
$vocabulario['owned'] = true;

if ($vocabulario[$mipalabra]) {
subrayo palabra
}

Y la otra manera es usar la funcion in_array de php:
$vocabulario[0] = 'lamer';
$vocabulario[1] = 'noob';
$vocabulario[2] = 'pakete';
$vocabulario[3] = 'lol';
$vocabulario[4] = 'owned';

if (in_array($mipalabra, $vocabulario)) {
subrayo palabra
}

Pero no se que metodo comeria menos recursos.
Que opinais?

SiCk

Es tán simple como que cuando pones un [[ ]] te lo sustituye por un a href... y toa la movida :s
Si te fijas sólo comprueba la existencia de palabras con [[ ]], es decir, tu le dices [[pepe]] y el busca el documento "pepe", si existe lo pone de azul, si no, de rojo.
Es eso a lo que te refieres?

SeiYa

osea #7 que no lo hace automáticamente no ? solo si se lo indicas ?

SiCk

Claro, para linkear de un articulo a otro tienes que escribir la palabra entre [[ ]]. Y para hacer link externo solo con [Palabra URL], es decir son 'tags' para sustituir por '<a href="' etc.

De todas maneras:
http://www.mediawiki.org/wiki/MediaWiki
http://sourceforge.net/projects/wikipedia/

SeiYa

Vale, ya me parecía a mi, por que sino, llegaría un momento en el que todo el artículo fuesen links (cuando todas las palabras apareciesen xD) pero me parece más lógico que solo linken las que quieras, yo no soy el autor del post pero mira, me has resuelto una curiosidad, pues tenía curiosidad por como hacía eso la wikipedia pero como no me reconcomía por dentro nunca pregunté XD, nunca te acostarás sin saber nada nuevo XD,

javithelong

La primera opción de #6 es algo parecido a una tabla hash...

EnZo

SiCk creo que no has entendido muy bien lo que dije.

#11 He estado mirando lo de los hash, pero no entiendo muy bien su funcionamiento :/ Ni como podria aplicarlo a lo que necesito.

SiCk

No se a que te puedes referir entonces :s
Te refieres a los enlaces entre artículos? Eso lo pone el que escribe no lo hace el sistema sólo.

javithelong

#12

Las tablas hash emplean lo que llaman "orden desordenado". Digamos que no son tablas con palabras ordenadas, sino que son tablas en las que cada entrada tiene una posicion predeterminada por una funcion.

Vamos, explico con un poco de ejemplo:

La tabla hash basa su funcionamiento en una funcion determinada. Esta funcion, cuando se la aplicas a un dato (que quieres almacenar) te dará un número. Esta será la posición del array donde la insertarás.

Esta función (ejemplo: suma de los valores numéricos de las letras de la palabra) tiene que devolver siempre el mismo valor para una misma entrada.

A la hora de insertar, pasas la palabra a la funcion, e insertas la palabra en la posicion del array que te diga la función.

A la hora de buscar una palabra, buscas en la posición del array que te da la función. Para borrar, se hace igual.

El problema es cuando varios datos a insertar caen en la misma posicion de la tabla. Una solución a esto es tener en cada posicion de la tabla una lista enlazada con las palabras que ahi caen.

Con el tamaño de la tabla, consigues el beneficio que quieras. Esto es, cuanta mas pequeña sea la tabla, menos memoria requiere, pero la búsqueda (hay que recorrer una lista enlazada), se hace más lenta. Una tabla inmensamente grande, su tiempo de acceso es 0, pero ocupa memoria a saco.

No se si me he dejado algo, pero vamos, básicamente eso es una tabla hash. Saludos

ElRuso

Pues seria algo asi pienso yo.
No me acuerdo muy bien de php asi que si hay fallos no os meteis con migo :)

$vocabulario['lamer'] = "<a href='url' target='algo'>";
$vocabulario['noob'] = "<a href='url' target='
algo'>";
$vocabulario['pakete'] = "<a href='url' target='algo'>";
$vocabulario['lol'] = "<a href='url' target='
algo'>";
$vocabulario['owned'] = "<a href='url' target='_algo'>";

Luego haces un loop sobre todas las palabras que hay en el texto, ya lo pensaras como :)

Loop (algo){
if ($vocabulario[$palabra]!="") {
print $vocabulario[$palabra] ."texto </a>";
}
else
{
print "texto";
}
}

A lo mejor eso no funciona, dependiendo de como esta echa la pagina.

SiCk

Troncos, en serio, que los links NO se ponen automáticamente xD habéis escrito en la wikipedia?

EnZo

Es posible sick xq nunca he escrito nada xD

El caso esque yo quiero que sea automatico ^^

ElRuso

Tambien puedes hacer varios Hashes un hash para cada letra.

Seria algo asi

a['amote']="....";
a['aim']=".....";
.
.
b['boom']="....";
.
.
c['cabron']="....";
.
.
z['zopenco']="....";

Luego otra vez hacer un loop y comporar con el hash dependiendo de la primera letra de la palabra.

algo asi:
looop{
if (right(<$>palabra,1).[palabra]!="") {
echo ...;
}else{
echo ...;
}
}

En teoria eso tendria que reducir el timepo de busqueda

P.S. <$> ---eso quiere decir que no nesesariamente tiene que ser variable.

javithelong

#18 con eso el tiempo de búsqueda sigue siendo prácticamente nulo, y la memoria se te va a la parra...

ElRuso

Hombre eso depende del tamanyo de dicionario. :)

Si la memoria es mas importante que el tiempo de busqueda, que no creo que es el caso. Se puede meter el dicionario en un docuemnto txt o una DB (que es mejor) y mas comodo.

gF

wenas enzo, la verdad que no tengo ni idea de PHP, pero en C o C++ eso se haría de forma óptima usando una estructura de arbol para almacenar las palabras, la ocupación de memoria sería mínima y consultar si una palabra está en el árbol es rapidisimo.

Usuarios habituales

  • ElRuso
  • javithelong
  • EnZo
  • SiCk
  • SeiYa
  • cabron
  • erdanblo