`
zhouxi2010
  • 浏览: 50768 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

用xapian跟mmseg实现中文搜索

阅读更多

xapian是一个开源的信息检索项目,类似于lucence,官网地址:http://xapian.org/

安装:用apt-get可以在ubuntu里安装如下模块:

apt-xapian-index - maintenance tools for a Xapian index of Debian packages

libxapian15 - Search engine library

python-xapian - Xapian search engine interface for Python

如果是用django,可以安装:python-django-djapian - Search API for Django using Xapian

 

mmseg是一个国人写的中文分词模块,网址:http://pypi.python.org/pypi/mmseg/1.3.0

 

用mmseg加上xapian就可以实现中文搜索的功能了。

 

好了,在我的项目中,原始数据是保存在数据库中的,所以需要从数据库中读出数据,再来建立索引,所以建立索引的代码如下:

 

class Index(object):

    def __init__(self, DBPATH, host='localhost', user='dbuser', passwd='dbpasswd', dbname='pjname'):
        self.SEARCH_DB = xapian.WritableDatabase(DBPATH, xapian.DB_CREATE_OR_OPEN)
        self.conn = MySQLdb.connect(host=host, user=user, passwd=passwd, db=dbname, charset='utf8')
    def _add_hanzi(self, doc, data):
        if not data:
            return 
        for word, value in seg_txt_2_dict(data).iteritems():
            doc.add_term(word, value)

    def modify_data(self, data_dict):
        for k, v in data_dict.items():
            if not v:
                data_dict[k] = ''
            if isinstance(v, int):
                data_dict[k] = str(v)
            if isinstance(v, datetime.date):
                data_dict[k] = u'%04d%02d%02d' %(v.year, v.month, v.day)
            if isinstance(v, Decimal):
                data_dict[k] = str(v)
        return data_dict

    def _update_index(self, data_dict):
        data_dict = self.modify_data(data_dict)
        doc = xapian.Document()
        for k, v in data_dict.items():
            if k in ('name', 'author', 'isbn'):
                self._add_hanzi(doc, v)
        key = 'I%s'%data_dict['id']
        doc.add_term(key)
        data = simplejson.dumps(data_dict, encoding='utf8')
        doc.set_data(data)
        self.SEARCH_DB.replace_document(key, doc)

    def update_index(self):
        for row in self.get_database_value():
            self._update_index(row)
 
    def get_database_value(self):
        cursor = self.conn.cursor()
        count = 0
        keys = ['id', 'name', 'isbn', 'price', 'pulisher', 'publish_date', 'img_url', 'description', 'author']
        while True:
            cursor.execute('select bb.id as id, bb.name as name, isbn, price, publisher, publish_date, img_url, description, group_concat(ba.name) as author  from book_book as bb left join book_book_author as bba on bb.id=bba.book_id left join book_author as ba on bba.author_id=ba.id group by bb.id limit %s,%s', (count*1000, 1000))
            data = cursor.fetchall()
            count = count + 1
            if not data or count > 1000:
                break
            for value in data:
                value_d = dict(zip(keys, value))
                yield value_d

  索引建立后就可以搜索了,下面是搜索的代码(还实现了结果分页的功能):

 

class Search(object):
    def __init__(self, DBPATH):
        self.SEARCH_DB = xapian.Database(DBPATH)
        self.SEARCH_ENQUIRE = xapian.Enquire(self.SEARCH_DB)
    
    def _get_enquire_mset(self, start_offset, end_offset):
        try:
            return self.SEARCH_ENQUIRE.get_mset(start_offset, end_offset)
        except xapian.DatabaseModifiedError:
            self.SEARCH_DB.reopen()
            return self.SEARCH_ENQUIRE.get_mset(start_offset, end_offset)
            
    def _get_document_data(self, document):
        try:
            return document.get_data()
        except xapian.DatabaseModifiedError:
            self.SEARCH_DB.reopen()
            return document.get_data()
     
    def _get_hit_count(self):
        return self._get_enquire_mset(0, self.SEARCH_DB.get_doccount()).size()

    def search(self, keywords, start_offset=0, end_offset=None):
        query_list = []
        if isinstance(keywords, unicode):
            keywords = keywords.encode('utf8')
        for word, value in seg_txt_2_dict(keywords).iteritems():
            query = xapian.Query(word, value)
            query_list.append(query)
        if len(query_list) != 1:
            query = xapian.Query(xapian.Query.OP_AND, query_list)
        else:
            query = query_list[0]


        self.SEARCH_ENQUIRE.set_query(query)
        count = self.SEARCH_DB.get_doccount()
        if not end_offset:
            end_offset = count - start_offset

        matches = self._get_enquire_mset(start_offset, end_offset)
        
        results = []
        for match in matches:
            data = self._get_document_data(match.document)
            data = simplejson.loads(data, encoding='utf8')
            results.append(data)
        
        return {'count': self._get_hit_count(), 'object_list':results}

    def search_by_page(self, keywords, pagenum=1, num_per_page=20):
        if pagenum < 1:
            pagenum = 1
        start_offset = (pagenum - 1) * num_per_page
        end_offset = num_per_page
        data = self.search(keywords, start_offset, end_offset)
        data['has_previous'] = pagenum >1 and True or False
        data['previous_page_number'] = pagenum > 1 and pagenum - 1 or 1
        data['number'] = pagenum
        data['has_next'] = pagenum*num_per_page < data['count'] and True or False
        data['next_page_number'] = pagenum + 1
        data['paginator'] = {'num_pages': (data['count']+num_per_page-1) / num_per_page}
        return data

 

  在django使用搜索功能:

 

def search_book(request):
        
    search_words = request.REQUEST.get('search_words')
    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1
    if request.method == 'POST':
        page = 1
    books = SEARCH.search_by_page(search_words, page)

    t=get_template('book/search_result.html')
    c=RequestContext(request,locals())
    return HttpResponse(t.render(c))

备注:xapian是单写多读,所以最好单独做索引的建立,所以建立后不会立即写入硬盘,可以用flush完成

query的时候需要定时reopen数据库来获得最新的更新,要不然新添加的数据查不到

分享到:
评论
1 楼 ➸愛✘A'shIn信☠™ 2013-07-24  
你好,不知道在创建索引的时候效率怎么样,我创建1w条的时间大概是半小时。。。。感觉不正常。。

相关推荐

    基于Xapian站内检索的设计与实现

    为了更好地理解如何使用Xapian实现站内检索,可以考虑以下场景: - **网站文档索引**:对网站上的所有文档进行索引,包括文章、新闻、论坛帖子等。 - **查询解析**:对用户的查询请求进行分析,提取关键词汇并构建...

    基于xapian搜索引擎的设计

    以Xapian 为核心开发一个搜索程序,以13 年第一季度的新浪新闻为检索目标,自行设计文档解析程序、调用xapian 建索引并实现一般检索、以及一个特殊的修饰符搜索功能(如url 搜索、标题搜索、时间搜索等),程序运行...

    xapian的使用

    Xapian是一个强大的开源搜索引擎库,它被广泛用于全文搜索、文档检索以及相似度计算等任务。本教程将深入探讨如何使用Xapian,并通过一个实际的“writedatabase”示例帮助你理解其核心概念和操作流程。 首先,我们...

    cpp-Xapiand一个基于Xapian的RESTful搜索引擎

    **Xapiand** 是一个基于 **Xapian** 库构建的现代、快速且易于使用的 RESTful 搜索引擎。这个项目旨在提供一个轻量级、高效且高度可配置的解决方案,用于索引和搜索大量数据。它允许通过 HTTP 接口与服务器进行交互...

    python xapian 简单应用

    在这个应用中,我们将探讨如何利用Python接口(`python-xapian`)来实现对文件系统的目录进行索引和搜索。 首先,我们需要了解Xapian的基本概念。Xapian提供了文档的索引和查询功能,它通过分词和词频分析来创建...

    xapian_doxygen_win

    Xapian是一个强大的开源全文搜索引擎库,专为高效的信息检索设计。它由C++编写,提供了丰富的API供开发者在各种应用程序中集成全文搜索功能。Xapian的核心特性包括高效的倒排索引、多字段搜索、模糊匹配、同义词支持...

    基于Xapian和PHP的高性能站内搜索系统方案设计.pdf

    本文基于开源搜索引擎库Xapian,提出了一种站内搜索引擎的设计方案,并且使用PHP实现。经实际部署和应用后,该系统在性能、速度、检索精度等方面都取得了较好的表现。 一、信息检索的介绍 信息检索(Information ...

    C++开源搜索引擎xapian开发入门demo

    搜索是通过`Enquire`对象实现的,它可以设置查询条件,比如布尔查询、短语查询或者使用查询语法构造复杂的查询表达式。执行查询后,`Enquire`会返回一个`Result`迭代器,你可以遍历这个迭代器来获取匹配的文档及其...

    搜索引擎技术教程 网络搜索引擎原理-第7章 Xapian简介 共39页.pptx

    ### 搜索引擎技术教程:Xapian简介 #### 一、Xapian概述 Xapian 是一款高性能的全文搜索引擎库,它不仅适用于简单的全文索引需求,还能够处理复杂的数据库搜索任务。Xapian 的设计初衷是为了解决那些传统数据库...

    Xapian-1.2.22 windows下编译

    Xapian是一个强大的全文搜索引擎库,因其高效、可扩展和高度可定制的特性而在信息检索领域广泛应用。然而,对于Windows平台的开发者来说,Xapian的官方支持并不像在Linux或Unix系统那样完善。在这种情况下,我们需要...

    细细品味架构·基于Xapian的垂直搜索引擎的构建分析(第2期)

    1.2.1 垂直搜索的应用场景 1.2.2 垂直搜索的技术选型 1.2.3 垂直搜索的引擎架构 1.2.4 垂直搜索技术和业务细节 1.2.5 现场答疑【Q&A】 2、知识扩展 2.1 淘宝类目及标题相关性分档计算方法 2.1.1 系统预测该关键词所...

    如何使用C#在Windows上编译和使用Xapian

    在Windows平台上使用C#...通过以上步骤,你将能够在Windows上成功地使用C#编译和使用Xapian,实现高效的全文搜索功能。过程中可能会遇到各种挑战,但解决它们将有助于你深入理解和掌握C#、C++以及跨语言接口的使用。

    xapian-core-1.4.9-vs2017-x64-release.zip

    因此,这个Xapian-Core 1.4.9库同样适用于那些使用doxygen生成文档并希望在大量源代码中实现快速搜索的开发者。 总结来说,"xapian-core-1.4.9-vs2017-x64-release.zip"是一个专为64位Windows系统和Visual Studio ...

    xapian_text_index

    通过理解这个项目的实现,我们可以了解到如何使用Xapian进行文本索引和查询,包括数据库管理、文档处理、查询解析和结果展示。掌握这些技能后,你将有能力构建自己的全文搜索引擎,为大数据时代的信息检索提供高效...

    acts_as_xapian:Xapian全文搜索插件,适用于Ruby on Rails

    总的来说,acts_as_xapian是Rails开发者实现全文搜索功能的一个强大工具,它的存在使得Rails应用在处理大量数据时,依然能提供快速、准确的搜索体验。对于需要提升用户体验的Web应用,这是一个值得考虑的选择。

    xapian-bindings:元软件包可简化针对Python的xapian-bindings扩展的安装。 尚未完全发挥作用

    它根据安装的的版本确定要使用的xapian-bindings的版本。 下载并提取源代码; 然后运行./configure , make和make install 。 该项目与项目没有任何关系。安装确保在系统上安装了必要的构建和开发工具。 确保通过...

    网站搜索的进化PPT学习教案.pptx

    常见的中文分词工具有Scws(基于词频词典)、Paoding(基于Lucene)、Imdict(智能词典)和Mmseg4j(封装mmseg算法,自带Sogou词库)。这些工具帮助搜索引擎理解中文文本,提高搜索准确性。 4. Sphinx与Coreseek的...

    xapian-core-1.4.18-3.el8.x86_64.rpm

    官方离线安装包,测试可用。使用rpm -ivh [rpm完整包名] 进行安装

    03海量空间数据全文多模式检索技术研究(公开).ppt

    为了解决这一问题,姬英杰主讲的专业技术培训提出了“03海量空间数据全文多模式检索技术研究”,结合MMSEG中文分词技术和Xapian全文检索引擎,设计了一种创新的空间数据组织与检索方法。这种方法着重于提高对地理...

    xapian-rack:轻松将 Xapian 与 Rack 集成

    Xapian::机架Xapian::Rack 提供了一个机架中间件,... 要执行搜索: query = request[:query] || ""search = Xapian::Rack.get(request.env)results = Xapian::Rack.find(request.env, query, {:options =&gt; Xapian::Qu

Global site tag (gtag.js) - Google Analytics