首页 > 代码库 > IR中python 写倒排索引与查询处理

IR中python 写倒排索引与查询处理

学习信息检索课程,老师让写一个倒排索引与查询处理的程序,于是抱着试试的心态自学python写了出来。

整个没有什么太大的算法技巧,唯一的就是查询处理那里递归函数正反两次反复查找需要多调试下。

数据结构:

#-*-coding:utf-8-*-
#!/usr/bin/python

'''
数据结构
建立索引
mydir   文档列表
onedoc  每一个文档
mydoc   当前查询的文档

mywords 建立索引的字典
myindex 0 文档下标 1 单词下标 2 次数 3...
wordcntdict中的个数 doccnt文档个数


三个字典
mywordsdictindex  单词编号 起始位置
antimywordsdict   单词编号 结束位置
mywordsdict       单词->单词编号

查询
mypos是每个的单词起始的index下标
myfindindex是每个单词的标号,
mydocs 查询到的文档号

'''
mydir=[]
mywords=[]
myindex=[]

mywordsdictindex={}
antimywordsdict={}
mywordsdict={}

wordcnt=0#dict中的个数
doccnt=0#文档个数
listcnt=0#index个数

mypos=[]
mydocs=[]
myfindindex=[]

mydoc=0
direct=0
print id(mydir)


创建索引:

#-*-coding:utf-8-*-
#!/usr/bin/python

from mydate import *
import sys
import os
import pprint
import pickle
def getmydoc(thepath,onedir):
	ans=[]
	for line in open(thepath+'/'+onedir):
		line=line.strip('\n')
		ans.append(line)
	return ans

def createindex(thepath):
	global mydir
	global mywords
	global myindex
	global mywordsdictindex
	global antimywordsdict
	global mywordsdict
	global wordcnt
	global doccnt
	global listcnt
	global mypos
	global mydocs
	global myfindindex
	global mydoc
	global direct
	mydir=os.listdir(thepath)
	for i in mydir:
		if(os.path.isdir(thepath+'/'+i)==True):
			mydir.remove(i)
	#print mydir
	mydir=['a.txt','b.txt','c.txt']
	wordcnt=0#dict中的个数
	doccnt=0#文档个数
	listcnt=0#index个数
	print id(wordcnt)
	for onedoc in mydir:
		mylist=getmydoc(thepath,onedoc)
		onedocword=0#每个词在这个文本中的位置
		docworddict={}
		for myword in mylist:
			if(myword not in mywordsdict):
				mywords.append([0]*2)
				mywords[wordcnt][0]=myword
				mywordsdict[myword]=wordcnt
				wordcnt+=1
				#print myword,mywordsdict[myword]
			if(myword not in docworddict):
				docworddict[myword]=listcnt
				listcnt+=1
				myindex.append([0]*3)
			ins=docworddict[myword]
			myindex[ins][0]=doccnt
			myindex[ins][1]=mywordsdict[myword]
			myindex[ins][2]+=1
			myindex[ins].append(onedocword)
			onedocword+=1
		doccnt+=1
	myindex.sort(key=lambda x:x[1]) #sort
	beg=0
	fin=0
	for i in range(len(mywords)):
		mywordsdictindex[mywords[i][0]]=beg
		mywords[i][1]=beg	
		while fin <len(myindex) and myindex[fin][1]==i:#python不支持逻辑短路
			fin+=1
		beg=fin
	for i in range(len(mywords)):
		mywordsdictindex[i]=mywords[i][1]
		if(i==len(mywords)-1):
			antimywordsdict[i]=len(myindex)
		else:
			antimywordsdict[i]=mywords[i+1][1]
'''
	pprint.pprint (mywords)
	pprint.pprint (myindex)
	pprint.pprint (mywordsdict)
	pprint.pprint (mywordsdictindex)
	pprint.pprint (antimywordsdict)
	
	out=open("myindex.dat","wb")
	pickle.dump(myindex,out)
	out=open("mywords.dat","wb")
	pickle.dump(mywords,out)
'''

接收查询与查询处理:

#-*-coding:utf-8-*-
#!/usr/bin/python
#得到一个文本的列表
import sys
import os
import pprint
import pickle
import pdb
from mydate import *
'''返回值三种:1 整个查询词都找到了 0 并没有同时出现在一个文本中 -1 查询完毕或不存在mydoc 查询词是否都在这个文档中direct 查询方向 direct=0 递归向下,携带标记flag若为1则表明之前一直存在。0表明并不都在一个文本中那么mydoc取过程中的最大值      当到len(mypos)的时候,决定是否将该结果放入,并将最后一个词的mypos后移 改变查询方向,并返回1      direct=1 递归返回,与0同样操作,当到第0层再改变查询方向'''def findword(loc,flag):
	global mydir
	global mywords
	global myindex
	global mywordsdictindex
	global antimywordsdict
	global mywordsdict
	global wordcnt
	global doccnt
	global listcnt
	global mypos
	global mydocs
	global myfindindex
	global mydoc
	global direct
	if(loc==len(mypos)):
		#pdb.set_trace()
		direct=1#############################
		if(flag==1):
			mydocs.append(mydoc)
			i=mypos[loc-1]+1
			#print mydocs
			if(i<antimywordsdict[myfindindex[loc-1]]):
				mydoc=myindex[i][0]
			else:
				return -1
		return 1
	i=mypos[loc]
	while i<antimywordsdict[myfindindex[loc]]:
		if(flag==-1):
			return -1
		if(loc==0 and direct==1):
			direct=0
		if( flag==1 and loc==0):
			mydocs.append(mydoc)#############################
			i+=1
			#print mydocs
			if(i<antimywordsdict[myfindindex[loc]]):
				mydoc=myindex[i][0]
			else:
				return 0		
		T=0
		while i<antimywordsdict[myfindindex[loc]] and myindex[i][0]<=mydoc:
			if(myindex[i][0]==mydoc):
				T=1
				break
			i+=1
		if(T==0):
			if(i+1==antimywordsdict[myfindindex[loc]]):
				return -1
			i+=1
			mydoc=myindex[i][0]
		mypos[loc]=i#############################
		if(flag==1 and T==1):
			pass
		else:
			T=0
		if(direct==1):
			return T
		flag=findword(loc+1,T)
	return 0

def getwords():
	global mydir
	global mywords
	global myindex
	global mywordsdictindex
	global antimywordsdict
	global mywordsdict
	global wordcnt
	global doccnt
	global listcnt
	global mypos
	global mydocs
	global myfindindex
	global mydoc
	global direct
	searchword=raw_input("find words\n")
	searchword=searchword.split(' ')
	flag=True
	for i in range(len(searchword)):
		if(searchword[i] not in mywordsdict):
			flag=False
			break
		myfindindex.append(mywordsdict[searchword[i]])#mypos是每个的单词起始的index下标,myfindindex是每个单词的标号,三个字典
		mypos.append(mywordsdictindex[searchword[i]])
		
	if(flag==False):
		print 'wrong'
		sys.exit()
	mydoc=myindex[mywordsdictindex[myfindindex[0]]][0]
	direct=0

	import pdb
	#pdb.set_trace()
	flag=findword(0,0)
	print mydocs#mydocs 查询到的文档号 返回这个数据

使用:

#-*-coding:utf-8-*-
#!/usr/bin/python
import hwf
from mydate import *
import createindex
import sys
import os
import pprint
import pickle


createindex.createindex('.')#创建索引
hwf.getwords()#查询单词



IR中python 写倒排索引与查询处理