Очень наивная поисковая система, реализованная с использованием Django-2.1.3, python3.6.
Я новичок в Django и не очень опытен в написании, поэтому этот код предназначен только для справки.
первая страница
Пагинация
Нам нужно сохранить инвертированный индекс, а также время отправки, отправителя, тему, ссылку на тему и т. д., соответствующие теме. Поэтому я разработал следующую структуру базы данных.
isIndexed
).Следует отметить, что при добавлении пары ключ-значение нельзя использовать следующий код
word . index [ doc . id ] = num
word . save ()
должен
dic = word . index
dic [ doc . id ] = num
word . index = dic
word . save ()
Ниже приведен код модели в 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 )
Первая — это домашняя страница. Ее структура следующая:
< 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 >
Есть закономерности, и их можно извлечь напрямую. Во время реализации я использовал для извлечения пакет Python BeautifulSoup.
Во время использования ключом является передача парсера. Я пробовал html, но возникла проблема с lxml. Наконец, я использовал html5lib.
Затем в таблице выше есть четвертый столбец (то есть четвертый тег td), где тег <a>
— это ссылка на веб-страницу, где находится тема. Ее также необходимо извлечь.
Поскольку время и место имеют общие закономерности, общие закономерности можно перечислить и сопоставить с помощью регулярных выражений.
Используя алгоритм textrank, я сначала сам реализовал очень простой алгоритм textrank, но эффект был очень плохим. Позже я использовал официальную версию text-rank.
Эта часть основана на принципе инвертированного индекса, сегментировании текста веб-страницы на слова, удалении знаков препинания и т. д., а затем использовании представленной выше модели базы данных для хранения инвертированного индекса.
Сначала под заголовком находится ряд параметров, которые можно отсортировать по этим полям. Затем в следующей строке находится кнопка обновления и форма отправки поиска.
Следующее содержимое — это результаты поиска, упорядоченные с помощью div
.
Каждый результат содержит заголовок, ключевые слова, время, место и краткое описание.
Здесь я сам реализовал алгоритм tf-idf
для сортировки результатов. Код выглядит следующим образом.
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 ]