Django没有内置全文检索功能,这方面的资料也很少。
有搜到两篇,一篇是使用
还有一篇是使用Whoosh的,看这里
其中whoosh是原生唯一的python写的全文搜索引擎,虽然有说whoosh性能比不上sphinx,xapian等。
不过whoosh本身很小,安装后才2.61M,非常容易集成到django/python里面,而我们的需求又不大
一般小站完全够用了,因此决定使用whoosh来进行全文检索。
安装whoosh非常简单:
pip install whoosh
搞定!!
whoosh国内搜索到一段代码,如下:
#一个完整的演示
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
from whoosh.index import create_in
from whoosh.fields import *
from whoosh.analysis import RegexAnalyzer
analyzer = RegexAnalyzer(ur”([\u4e00-\u9fa5])|(\w+(\.?\w+)*)”)
schema = Schema(title=TEXT(stored=True), path=ID(stored=True), content=TEXT(stored=True, analyzer=analyzer))
ix = create_in(“indexdir”, schema)
writer = ix.writer()
writer.add_document(title=u”First document”, path=u”/a”,
content=u”This is the first document we’ve added!”)
writer.add_document(title=u”Second document”, path=u”/b”,
content=u”The second one 你 中文测试中文 is even more interesting!”)
writer.commit()
searcher = ix.searcher()
results = searcher.find(“content”, u”first”)
print results[0]
results = searcher.find(“content”, u”你”)
print results[0]
results = searcher.find(“content”, u”测试”)
print results[0]
whoosh默认是基于正则表达式进行分词的,这对一般的英文来说不是问题。
上述代码,将中文的的正则表达式加入到analyzer = RegexAnalyzer(ur”([\u4e00-\u9fa5])|(\w+(\.?\w+)*)”)
这样就可以支持对中文进行检索了。
不过问题远不会就如何简单,上述的analyzer分析器(可以理解为分词器)是按单个中文进行分词的,因此效果很糟。
举个例子:
writer.add_document(title=u"学习", path=u"/a",content=u"先生说我们都是好学生!")
writer.commit()
searcher = ix.searcher()
results = searcher.find("content",u"学生")
for hit in results:
print hit.highlights("content")
先生说我们都是好学生
原因就在于,RegexAnalyzer将学生按一个字一个字进行分词,然后再搜索,这样导到输出的结果也是单个的。
很明显这样在中文搜索中效率很糟,很容易搜索出一些岐义的单词。
因此,在全文搜索方面不可避免地要引入中文分词技术,简单地说中文分词就要说一个中文字子分割成一个个具有意义的字词。
如上述
先生说我们都是好学生
可能会被分割成:
先生 说 我们 都是 好 学生
这样检索引擎就可以根据这些词来做索引,最后检索到的结果也就会相对准确得多了。
显然要做好中文分词是做中文搜索引擎的一个最基础的工作,如果我们做中文全文检索
那也必须有一个中文分词库。
中文分词要达到智能、准确并不是一件容易的事,目前国内有不少商业的分词库。
也有一些免费的中文分词库可以用,比如:结巴中文分词库号称要做最好的Python中文分词组件。
好了,废话这么多,我们就引入中文分词技术,来改造上述的代码:
首先我们要写一个analyzer分析器,代码如下:
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=False) #使用结巴分词库进行分词
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 #通过生成器返回每个分词的结果token
def ChineseAnalyzer():
return ChineseTokenizer()
#重点在这里,将原先的RegexAnalyzer(ur”([\u4e00-\u9fa5])|(\w+(\.?\w+)*)”),改成这句,用中文分词器代替原先的正则表达式解释器。
analyzer=ChineseAnalyzer()
上述代码,先写一个ChineseTokenizer,这就是用来进行分词的.
最后的运行结果如下:
先生说我们都是好学生
这样我们就基本达到了用whoosh进行中文索引和检索的要求了。
最后,我不得不说,中文分词库的效果会决定检索的准确性,结巴中文分库在某些分词效果上
还是存在不足的,在默认模式如下:
我们要树立科学发展观
我们 要 树立 科学 发展观
我 我们 们 要 树 树立 立 科 科学 科学发展 学 发 发展 发展观 展 观
那么,如何将whoosh集成到Django呢,推荐使用django-haystack,这一款同时支持whoosh,solr,Xapian,Elasticsearc四种全文检索引擎
的第三方app,使用了非常友好地方式来为你的Django应用集成全文检索功能。
下一篇介绍django-haystack+Whoosh在Django中的使用