Un motor de búsqueda muy ingenuo implementado con Django-2.1.3, python3.6.
Soy nuevo en Django y no soy muy competente escribiendo, por lo que este código es solo como referencia.
página delantera
Paginación
Necesitamos guardar un índice invertido, así como la hora de envío, el remitente, el asunto, el enlace del tema, etc. correspondiente a un tema. Entonces diseñé la siguiente estructura de base de datos.
isIndexed
).Cabe señalar que agregar un par clave-valor no puede usar el siguiente código
word . index [ doc . id ] = num
word . save ()
debería
dic = word . index
dic [ doc . id ] = num
word . index = dic
word . save ()
A continuación se muestra el código para el modelo en Django.
from django . db import models
class Doc ( models . Model ):
sendTime = models . DateField () # 2018-12-12 , differ from DateTimeField which can be datetime or date
sender = models . CharField ( max_length = 20 )
messageType = models . CharField ( max_length = 20 ) # Journal, conf, et al
subject = models . CharField ( max_length = 100 )
begin = models . DateField ()
deadline = models . DateField ()
subjectUrl = models . CharField ( max_length = 100 )
webpageUrl = models . CharField ( max_length = 100 )
desc = models . CharField ( max_length = 250 , default = '' )
loc = models . CharField ( max_length = 40 , default = '' )
keywords = models . CharField ( max_length = 200 , default = '' )
def __str__ ( self ):
return self . subjectUrl
import json
class Wordindex ( models . Model ):
word = models . CharField ( max_length = 45 )
# model to store a list, another way is to create a custom field
_index = models . TextField ( null = True )
@ property
def index ( self ):
return json . loads ( self . _index )
@ index . setter
def index ( self , li ):
self . _index = json . dumps ( li )
def __str__ ( self ):
return self . word
class File ( models . Model ):
doc = models . OneToOneField ( Doc , on_delete = models . CASCADE )
content = models . TextField ( null = True )
isIndexed = models . BooleanField ( default = False )
def __str__ ( self ):
return 'file: {} -> doc: {}' . format ( self . id , self . doc . id )
La primera es la página de inicio. Su estructura es la siguiente:
< TBODY >
< TR VALIGN = TOP >
< TD > 03-Jan-2019 </ TD >
< TD > conf. ann. </ TD >
< TD > marta cimitile </ TD >
< TD > < A HREF =" http://www.cs.wisc.edu/dbworld/messages/2019-01/1546520301.html " rel =" nofollow " > Call forFUZZ IEEE Special Session </ A > </ TD >
< TD > 13-Jan-2019 </ TD >
< TD > < A rel =" nofollow " HREF =" http://sites.ieee.org/fuzzieee-2019/special-sessions/ " > web page </ A > </ TD >
</ TR > </ TBODY >
Hay regularidades y se pueden extraer directamente. Durante la implementación, utilicé el paquete BeautifulSoup de Python para extraer.
Durante el uso, la clave es pasar el analizador. Probé html, pero hubo un problema con lxml. Finalmente, usé html5lib.
Luego está la cuarta columna (es decir, la cuarta etiqueta td) en la tabla anterior, donde la etiqueta <a>
es el enlace a la página web donde se encuentra el tema.
Dado que el tiempo y el lugar tienen patrones generales, los patrones comunes se pueden enumerar y relacionar mediante expresiones regulares.
Usando el algoritmo textrank, primero implementé un algoritmo textrank muy básico, pero el efecto fue muy pobre. Más tarde, usé la versión oficial de text-rank.
Esta parte se basa en el principio del índice invertido, segmentando el texto de la página web en palabras, eliminando signos de puntuación, etc., y luego utiliza el modelo de base de datos presentado anteriormente para almacenar el índice invertido.
Primero, debajo del título hay una fila de opciones, que se pueden ordenar según estos campos. Luego hay un botón de actualización en la siguiente fila y un formulario de envío de búsqueda.
El siguiente contenido son los resultados de la búsqueda organizados mediante div
.
Cada resultado contiene un título, palabras clave, hora, ubicación y resumen.
Aquí implementé el algoritmo tf-idf
para ordenar los resultados. El código es el siguiente.
def tfidf ( words ):
if not words : return docs
ct = process ( words )
weight = {}
tf = {}
for term in ct :
try :
tf [ term ] = Wordindex . objects . get ( word = term ). index
except Exception as e :
print ( e )
tf [ term ] = {}
continue
for docid in tf [ term ]:
if docid not in weight :
weight [ docid ] = 0
N = len ( weight )
for term in ct :
dic = tf [ term ]
for docid , freq in dic . items ():
w = ( 1 + log10 ( freq )) * ( log10 ( N / len ( dic ))) * ct [ term ]
if term in stopWords :
w *= 0.3
weight [ docid ] += w
ids = sorted ( weight , key = lambda k : weight [ k ], reverse = True )
if len ( ids ) < 8 : pass #???
return [ Doc . objects . get ( id = int ( i )). __dict__ for i in ids ]