Django-2.1.3, python3.6을 사용하여 구현된 매우 순진한 검색 엔진입니다.
저는 Django를 처음 접하고 글쓰기에 능숙하지 않기 때문에 이 코드는 단지 참고용입니다.
첫 페이지
쪽수 매기기
반전된 인덱스와 함께 토픽에 해당하는 전송 시간, 보낸 사람, 제목, 토픽 링크 등을 저장해야 하므로 다음과 같은 데이터베이스 구조를 설계했습니다.
isIndexed
)를 포함하는 Doc입니다.키-값 쌍을 추가하면 다음 코드를 사용할 수 없습니다 .
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 ]