Python Django,全文检索,haystack框架,whoosh搜索引擎
- haystack:一种专门设计的全文检索架构,在多个搜索引擎之间提供兼容性支持。
- whoosh:一种基于Python开发的开源全文搜索引擎,在性能上略逊色于sphinx、Xapian和Elasticsearch等主流产品。尽管它不依赖二进制包运行(避免程序在无依赖情况下崩溃),但对于小型网站而言已经足够满足基本需求。
- jieba:一款经过验证的免费中文分词工具(如果觉得不够好还可以选择付费版本)。

安装需要的包:
pip3 install django-haystack
pip3 install whoosh
pip3 install jieba
项目名/settings.py(配置设置,在该文件中进行注册并安装HAYSTACK应用程序,并对WHOOSH搜索引擎进行配置):
INSTALLED_APPS = (
# ...
'haystack', # 安装应用haystack
)
# 配置搜索引擎
HAYSTACK_CONNECTIONS = {
'default': {
# 使用whoosh引擎
# 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine', # 对应whoost安装的路径
'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine', # 使用jieba中文分词器
# 索引文件路径
'PATH': os.path.join(BASE_DIR, 'whoosh_index'), # 索引文件的保存路径
}
}
# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# 指定搜索结果每页显示的条数 (默认20)
HAYSTACK_SEARCH_RESULTS_PER_PAGE=15
项目名/urls.py(项目路由,配置全文检索的路由):
from django.conf.urls import include, url
urlpatterns = [
# ...
url(r'^search', include('haystack.urls')), # 将对应url请求交给全文检索框架。 ("/search"对应前端模板的搜索url)
]
建立索引
应用名/search_indexes.py(定义索引类,py文件名固定):
from haystack import indexes
from 应用名.models import GoodsSKU # 导入模型类 (要建立索引的模型类)
# 定义索引类
# 指定对于某个类的某些数据建立索引
# 索引类名格式:模型类名+Index
class GoodsSKUIndex(indexes.SearchIndex, indexes.Indexable):
# text是一个索引字段。 use_template=True指定根据表中的哪些字段建立索引文件(使用下方创建的txt文件)
text = indexes.CharField(document=True, use_template=True)
def get_model(self):
# 返回模型类
return GoodsSKU
# 建立索引的数据 (对哪些数据建立索引)
def index_queryset(self, using=None):
return self.get_model().objects.all()
templates/search/indexes/{ApplicationName}/{goodssku}_text.txt(配置该模型的小写字号文件中的字段到索引;指定目录为固定位置):
# 指定根据模型中的哪些字段建立索引数据
{{ object.name }} # 根据商品的名称建立索引
{{ object.desc }} # 根据商品的简介建立索引
{{ object.goods.detail }} # 根据商品的详情建立索引
创建索引文件: $ python manage.py rebuild_index # 该命令会在settings.py中指定的配置下生成索引文件。
使用索引
templates/demo.html(模板页,搜索框):
<!-- 。。。 -->
<form method="get" action="/search"> <!-- 必须是get请求。 "/search"对应urls.py中配置的全文检索路由 -->
<input type="text" name="q" placeholder="搜索商品"> <!-- name属性值必须是q。 q参数是关键字,page参数是第几页(haystack会自动分页) -->
<input type="submit" value="搜索">
</form>
在haystack系统中, 检索结果会被自动地传递到templates/search/search.html 模板中进行处理。
传递的模板变量如下:
query: 关键词
page: 当前页的对象(自动分段) –> 遍历 page 对象时会得到 SearchResult 类的具体实例,并且只有在 object 属性处才能找到对应的模型类实例。
paginator: 分页 paginator 实例用于分割页面内容
templates/search/search.html(模板,haystack自动返回的模板):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>检索结果</title>
</head>
<body>
搜索的关键字:{{ query }}<br/>
当前页的Page对象:{{ page }}<br/>
<ul>
{% for item in page %}
<li>{{ item.object }}</li>
{% endfor %}
</ul>
分页paginator对象:{{ paginator }}<br/>
</body>
</html>
使用中文分词,jieba分词
jieba分词: $ pip3 install jieba # 安装jieba分词模块
demo.py(jieba分词器使用示例):
import jieba
str = '要被分析的中文内容'
res = jieba.cut(str, cut_all=True)
for val in res:
print(val) # 要 被 分析 的 中文 内容
定位 haystack 安装的位置为 /home/用户名/.virtualenvs/虚拟环境名/lib/python3.5/site-packages/haystack/backends/
该目录下新建 ChineseAnalyzer.py 文件,内容如下:
import jieba
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):
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:
t.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。
修改 whoosh_cn_backend.py 中的内容:
# ...
from .ChineseAnalyzer import ChineseAnalyzer # 导入ChineseAnalyzer类
# 查找
# analyzer = StemmingAnalyzer()
# 改为
# analyzer = ChineseAnalyzer()
# ...
项目名/settings.py(项目配置,搜索引擎使用whoosh_cn_backend):
# 配置搜索引擎
HAYSTACK_CONNECTIONS = {
'default': {
# 使用whoosh引擎 (对应whoost安装的路径)
# 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine', # whoost默认引擎
'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine', # 使用jieba中文分词器
# 索引文件路径
'PATH': os.path.join(BASE_DIR, 'whoosh_index'), # 索引文件的保存路径
}
}
**重新生成索引文件: $ python manage.py rebuild_index **
