注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

秋风扫落叶

 
 
 

日志

 
 
 
 

在django中加入搜索引擎  

2013-09-04 01:08:33|  分类: python转载 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

上周蛋疼给做的一个东西加了个搜索引擎,虽然整体来说项目数据也不会很大,但是出于DBA的职业嘛,不想用like或者mysql的fulltext(myisam表的原因),我的想法是能不让DB来实现的就不让DB来实现。所以就开始找python相关的。下面来说下。

首先找了个中文分词词库,jieba,https://github.com/fxsjy/jieba

用法很简单:

#!/usr/bin/env python #-*- coding: utf-8 -*- import jieba s = jieba.cut('网易杭州研究院') print ', '.join(s)

结果如下:

Building Trie... loading model from cache loading model cost 0.877662181854 seconds. Trie has been built succesfully. 网易, 杭州, 研究院

总体来说,效果还是可以的,初期用用就够了。 接下来说说whoosh,http://packages.python.org/Whoosh/ whoosh的话,没有深入研究过,主要是根据正则表达式来匹配,纯python实现,架构参考了Lucene。但是对于中文支持不好的,所以加入了jieba。

最后来说django-haystack,这是重点了。http://haystacksearch.org/
ps:安装haystack的时候,最好别用pip的,pip下载下来的是1.2+版本的,因为文档里用的HAYSTACK_CONNECTIONS是针对2.0+版本的,所以从github里clone新版本比较好。https://github.com/toastdriven/django-haystack
heystack的好处就是接口统一,支持Solr, Elasticsearch, Whoosh and Xapian之类的搜索引擎,而且不用换代码去适应的。 目前我用的是django-heystack+whoosh,效果其实也就一般,后续会考虑切换成solr,等我弄好了再总结solr。
首先在/Library/Python/2.7/site-packages/haystack/backends下增加个文件,为了让whoosh支持中文分词的。
ChineseAnalyzer.py

import jieba from whoosh.analysis import RegexAnalyzer from whoosh.analysis import Tokenizer,Token class ChineseTokenizer(Tokenizer): def __call__(self, value, positions=False, chars=False, keeporiginal=False, removestops=True, start_pos=0, start_char=0, mode='', **kwargs): #assert isinstance(value, text_type), "%r is not unicode" % value t = Token(positions, chars, removestops=removestops, mode=mode, **kwargs) seglist=jieba.cut(value,cut_all=True) for w in seglist: t.original = t.text = w t.boost = 1.0 if positions: t.pos=start_pos+value.find(w) if chars: .startchar=start_char+value.find(w) t.endchar=start_char+value.find(w)+len(w) yield t def ChineseAnalyzer(): return ChineseTokenizer()

然后修改whoosh_backend.py为whoosh_cn_backend.py: 在import中加:

from ChineseAnalyzer import ChineseAnalyzer

将其中的schemafields[fieldclass.indexfieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer(), fieldboost=field_class.boost)句修改为:

schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(), field_boost=field_class.boost)

然后新建个django来试试的.例子url:http://django-haystack.readthedocs.org/en/latest/tutorial.html settings.py:

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', # Added. **'haystack',** # Then your usual apps... 'blog', ] <!-- lang: python --> import os HAYSTACK_CONNECTIONS = { 'default': { 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine', 'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'), }, }

models.py:

from django.db import models
from django.contrib.auth.models import User

class Note(models.Model):
    user = models.ForeignKey(User)
    pub_date = models.DateTimeField()
    title = models.CharField(max_length=200)
    body = models.TextField()

def __unicode__(self):
    return self.title
然后针对note写search_indexes.py:
import datetime
from haystack import indexes
from blog.models import Note

class NoteIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    author = indexes.CharField(model_attr='user')
    pub_date = indexes.DateTimeField(model_attr='pub_date')

    def get_model(self):
        return Note

    def index_queryset(self):
    """Used when the entire index for model is updated."""
        return self.get_model().objects.filter(pub_date__lte=datetime.datetime.now())

 这里补充说明下,我在实际应用中index_queryset中一般写的是:

return self.get_model().objects.all()

接着在/templates/search/indexes/blog下新建note_text.txt:

{{ object.title }} {{ object.user.get_full_name }} {{ object.body }}

注意的是,文件名要以models中的一个class名字开头。 最后在/templates/search/新建个search.html:

<h2>Search</h2> <form method="get" action="."> <table> {{ form.as_table }} <tr> <td>&nbsp;</td> <td> <input type="submit" value="Search"> </td> </tr> </table> {% if query %} <h3>Results</h3> {% for result in page.object_list %} <p> <a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}</a> </p> {% empty %} <p>No results found.</p> {% endfor %} {% if page.has_previous or page.has_next %} <div> {% if page.has_previous %}<a href="?q={{ query }}&amp;page={{ page.previous_page_number }}">{% endif %}&laquo; Previous{% if page.has_previous %}</a>{% endif %} | {% if page.has_next %}<a href="?q={{ query }}&amp;page={{ page.next_page_number }}">{% endif %}Next &raquo;{% if page.has_next %}</a>{% endif %} </div> {% endif %} {% else %} {# Show some example queries to run, maybe query syntax, something else? #} {% endif %} </form>

完了后,修改urls.py: 加入一句:

url(r'^search/', include('haystack.urls')),

最后重建索引, python manage.py rebuild_index

这样的话,就算大功告成了。输入http://localhost:8000/search/就可以搜索了。

search.html什么之类的都可以根据自己需求修改,本篇用的是官方文档的例子。

写的比较乱,估计错误很多的,改天改成solr后好好重新整理下的。

另外,参考如下:

http://blog.csdn.net/Java2King/article/details/5308326

  评论这张
 
阅读(2555)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017