Python实现搜索引擎-倒排索引



  • # -*- coding:utf-8 -*-
    # 作者:luting.gu@gmail.com
    # 倒排索引-搜索引擎 DEMO
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    
    # t1到t7都是待搜索的全文
    t1 = """
          在我们家族,各行各业从业者都有。从政的,从商的,人民教师的,农民的,企业职员的。从收入水平看,就目前而言,自然是从商的赚的钱稍微比其他人都多一些。但是,亲眼目睹过去几年几位兄弟从商的工作状态,我真的没有羡慕过他们收入比我高,因为,他们的那种工作强度,那种紧张忙碌,那种工作压力,是我根本承受不起的。
    """
    t2 = """
    处女座为了爱情付出的不是金钱又或者时间之类的东西,而是心态,她们的思维模式比较单一,向往平凡的爱情模式,对于金钱的向往是从来没有过的,两个人在一起开开心心就好,心愿纯真简单。但是如果遇到渣男,她就会患得患失的思考为什么会这样,会造成她经常纠结是否是自身的问题,不断否定自己,想不开,久而久之很容易得与抑郁症。
    """
    t3 = """
    狮子座天生的骄傲会自豪,随着她的恋情一步一步的消失殆尽,越来越迁就恋人,狮子认为在生命中如果没有一次奋不顾身的恋爱,是不完整的。可是一旦恋情失败,狮子会变成另一个极端的自己,越发的讨厌以前的自己,抛弃原来的自我。或许有一天,她遇见对的人,会再次重生吧。
    """
    t4 = """
    人心有真假,时间能见证,感情有冷暖,风雨能考验,时间带不走真正的朋友,岁月留不住虚幻的拥有,时光转换,体会到缘分善变,平淡无语,感受了人情冷暖,有心的人,不管你在与不在,都会惦念,无心的情,无论你好与不好,只是漠然,走过一段路,总能有一次领悟,经历一些事,才能看清一些人。
    """
    t5 = """
    总会有些不喜欢,又不得不去做的事,与其每次抱着自杀的心情去面对,不如把它们养成习惯。习惯跑步,习惯健身,习惯记录,习惯和一个人在一起。习惯能消磨一个人对事物的厌恶感,能让一个人与世界相安无事。“习惯了就好”不是无奈,而是学会了对自己体谅。—— 刘同
    """
    t6 = """
    想知道一个人爱不爱你,就给他自由。不要妄图拴住爱情,世上没有能拴得住的爱人。若是爱你,何需拴着他?若不爱你,拴住他干嘛!爱你的人,走到天涯也会回来找你。要费尽心机来挽留的,早晚有走丢的一天。
    """
    t7 = """
    我们都像小孩,胡闹是因为依赖你;懂礼貌,是因为你是外人。
    """
    
    
    def del_space(text):
        """
        去除无用的符号
        @param [in] text 待处理的字符串
        @retval 去除无用符号后的字符串
        """
        space_char = " `~!@#$%^&*()-_=+[{]}\\|\t;:'\",<.>/?……()——【】、;「」,。、"
        for c in space_char.decode('utf-8'):
            text = text.replace(c,'')
        return text
    
    def n_gram(text,n):
        """
        使用N_GRAM对全文进行分割
        @param [in] text 待分割的文本
        @param [in] n 1:uni-gram 2:bi-gram 3:tri-gram
        @return 分割后的字典列表[[词语,位置下标],......]
        """
        text = text.decode('utf-8')
        retlist = []
        for i in xrange(0,len(text)-n+1):
            short_text = ['',0]
            for j in xrange(0,n):
                short_text[0] += text[i+j]
            short_text[1] = i
            retlist.append(short_text)
        return retlist
    
    
    data = []       # 用于存储数据,将下标作为doc_id
    index = {}      # 用来记录词典及对应的倒排项
    def make_index(text):
        """
        制作倒排索引
        @param [in] text 待处理的文本
        """
        data.append(text)
        doc_id = len(data) - 1
        word_list = n_gram(del_space(text),2)
        for item in word_list:
            if not index.has_key(item[0]):
                index[item[0]] = set()
            index[item[0]].add(doc_id)
    
    
    def query(text):
        """
        查询
        @param [in] text 用于查询的短语或词语
        @return 匹配成功的文档下标doc_id
        """
        word_list = n_gram(del_space(text),2)
        doc_list = set()
        for item in word_list:
            if index.has_key(item[0]):
                if len(doc_list) == 0:
                    doc_list = index[item[0]]
                else:
                    doc_list = doc_list & index[item[0]]
        return doc_list
    
    
    if __name__ == "__main__":
        # 生成倒排索引
        make_index(t1)
        make_index(t2)
        make_index(t3)
        make_index(t4)
        make_index(t5)
        make_index(t6)
        make_index(t7)
        # 开始检索并遍历输出结果
        id_list = query("不要妄图拴住爱情")
        for item in id_list:
            print str(item)+':'+data[item]