在django中加入搜索引擎

2019-03-27 01:20|来源: 网路

上周蛋疼给做的一个东西加了个搜索引擎,虽然整体来说项目数据也不会很大,但是出于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

将其中的schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer(), field_boost=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


转自:http://my.oschina.net/zhuf/blog/95020

相关问答

更多
  • “西林街”、“盘搜一下”这两个网盘搜索速度快,资源丰富,我所钟爱用的。
  • 全文搜索 MATCH() 函数 全文索引在 MySQL 中是一个 FULLTEXT 类型索引。FULLTEXT 索引用于 MyISAM 表,可以在 CREATE TABLE 时或之后使用 ALTER TABLE 或 CREATE INDEX 在 CHAR、VARCHAR 或 TEXT 列上创建。对于大的数据库,将数据装载到一个没有 FULLTEXT 索引的表中,然后再使用 ALTER TABLE (或 CREATE INDEX) 创建索引,这将是非常快的。将数据装载到一个已经有 FULLTEXT 索引的表中 ...
  • 首先要弄清楚是自己的站内检索,还是对网络的检索?如果仅仅检索自己本站里面的东西很简单,在apache上把lucene下载下来,里面有个很好的例子,再去找找相关资料就行了,如果想对中文分词做好点,去看看庖丁分词法.
  • 1、首先,到域名查询中心,比如万网、新网或者能查询域名所有者的地方去查询域名的注册信息,是否以前被注册过(就是我们常用的Whois查询)。如果域名曾经被注册过,我们就需要关心一下这个域名是否有过不良记录。 2、通过在Google中(site:域名),看下是否有记录,然后查看下反向链接,利用(link:域名)或者(domain:域名)可以到一些提供查询反向连接的网站去查询或者自己到搜索引擎利用命令查询。如果存在反向连接,而没有该站点被搜索引擎收录,那么这个域名很有可能被K过了,也就是存在不良记录。 3、直接输 ...
  • 在浩如烟海的Internet上,特别是其上的Web(World Wide Web万维网)上,不会搜索,就不会上网。网虫朋友们,你了解搜索引擎吗?它们是怎么工作的?你都使用哪些搜索引擎?今天我就和大家聊聊搜索引擎的话题。 一、搜索引擎的分类 获得网站网页资料,能够建立数据库并提供查询的系统,我们都可以把它叫做搜索引擎。按照工作原理的不同,可以把它们分为两个基本类别:全文搜索引擎(FullText Search Engine)和分类目录Directory)。 全文搜索引擎的数据库是依靠一个叫“网络机器人(Spi ...
  • 这方面的书还是比较多的,我所看过的有《搜索引擎技术》、《个性化搜索引擎原理与技术》、《搜索引擎原理、实践与应用》。此外还有很多基于开源软件如Lucene、nutch的开发搜索引擎的书籍,其中也介绍了不少关于原理方面的东西,而且更加面向应用。
  • 全文搜索 MATCH() 函数 全文索引在 MySQL 中是一个 FULLTEXT 类型索引。FULLTEXT 索引用于 MyISAM 表,可以在 CREATE TABLE 时或之后使用 ALTER TABLE 或 CREATE INDEX 在 CHAR、VARCHAR 或 TEXT 列上创建。对于大的数据库,将数据装载到一个没有 FULLTEXT 索引的表中,然后再使用 ALTER TABLE (或 CREATE INDEX) 创建索引,这将是非常快的。将数据装载到一个已经有 FULLTEXT 索引的表中 ...
  • lucene的效率没有问题,你可以100W条记录的索引放在一台机器上,用nutch分开检索的算法,或者用hadoop存储索引,自己写一个indexsearcher,但是需要注意各个机器上的结果是本地最优不是全局最优的结果,如果想全局最优的结果还得采用全局频率计数(Nutch现在有没有我不清楚),或者放开各个机器返回结果的数量,从算法理论的角度上最大可能的获得最优解。100W记录的响应我测试过,应该可以满足要求。等你遇到什么问题,可以再联系,lucene后面的基准测试你也可以看看。 老吴
  • http://baike.baidu.com/view/371811.htm lucene是一款开源的搜索引擎工具,你可以用这个!
  • haystack_static_pages就是为此目的而制作的。 该应用程序旨在抓取和索引您自己的网站上指定的渲染页面。 您配置网址或网址名称,然后使用管理命令来抓取您的网站。 值得注意的是关于这方面的一些事情。 Haystack与Django ORM紧密耦合,因此haystack_static_pages所做的是为静态内容添加模型,然后将已爬网内容作为索引的先驱转储到模型中。 它也似乎是围绕Haystack的1.x版本设计的。 haystack_static_pages is made just for ...