前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[702]python全文搜索库Whoosh

[702]python全文搜索库Whoosh

作者头像
周小董
发布2020-01-13 17:35:11
1.3K0
发布2020-01-13 17:35:11
举报
文章被收录于专栏:python前行者

官方文档:https://whoosh.readthedocs.io/en/stable/ pypi:https://pypi.python.org/pypi/Whoosh/#downloads

安装

代码语言:javascript
复制
pip install Whoosh

Whoosh是一个纯python的全文搜索库

Whoosh官方文档介绍如下,

Whoosh is a library of classes and functions for indexing text and then searching the index. It allows you to develop custom search engines for your content. For example, if you were creating blogging software, you could use Whoosh to add a search function to allow users to search blog entries.

大意:Whoosh是索引文本及搜索文本的类和函数库。它能让你开发出一个个性化的经典搜索引擎。 例如,如果你在写博客选择(或者说博客搜索)程序,你可以用Whoosh添加一个让用户搜索博客条目的函数

因为做的是中文的全文检索需要导入jieba工具包以及whoosh工具包

Schema 有两个field, 标题title & 内容content

代码语言:javascript
复制
from whoosh.fields import Schema, TEXT
 
schema = Schema(title=TEXT, content=TEXT)

如果你不需要给任何field type传值,你可以只给类名 ,whoosh会为你初始化该对象

代码语言:javascript
复制
from whoosh.fields import Schema, STORED, ID, KEYWORD, TEXT
 
schema = Schema(title=TEXT(stored=True), content=TEXT,
                path=ID(stored=True), tags=KEYWORD, icon=STORED)

关于 schema的设计的更多信息 有了schema,你可以用create_in函数创建index

代码语言:javascript
复制
import os.path
from whoosh.index import create_in
 
if not os.path.exists("index"):
    os.mkdir("index")
ix = create_in("index", schema)

在底层,这将创建一个 Storage 对象来包含这个索引。一个Storage 对象 代表了索引将被存储在哪个媒介上。一般这将会是用来存储文件夹内一系列文件的索引FileStorage。

当你创建好索引后,你可以用open_dir打开它

代码语言:javascript
复制
from whoosh.index import open_dir
 
ix = open_dir("index")

IndexWriter对象

既然我们已经知道Index对象了,我们可以开始添加文档了。 Index对象的writer() 方法可以让你把文档加到索引上。 IndexWriter的add_document(**kwargs) 方法接受一个field name被映射到一个值的关键词参数:

代码语言:javascript
复制
writer = ix.writer()
writer.add_document(title=u"My document", content=u"This is my document!",
                    path=u"/a", tags=u"first short", icon=u"/icons/star.png")
writer.add_document(title=u"Second try", content=u"This is the second example.",
                    path=u"/b", tags=u"second short", icon=u"/icons/sheep.png")
writer.add_document(title=u"Third time's the charm", content=u"Examples are many.",
                    path=u"/c", tags=u"short", icon=u"/icons/book.png")
writer.commit()

Searcher 对象

为了开始搜索Index,我们需要 一个 search 对象

代码语言:javascript
复制
searcher = ix.searcher()

你将经常想用一个with 语句打开searcher因为当你使用完毕时它会自动关闭。(searcher对象代表一系列打开的文件,所以你不明确的关掉他们,整个系统像蜗牛一样,你可能会用尽文件句柄):

代码语言:javascript
复制
with ix.searcher() as searcher:
    ...

当然这与下面的的代码等价:

代码语言:javascript
复制
try:
    searcher = ix.searcher()
    ...
finally:
    searcher.close()

Searcher的 search() 方法需要一个Query对象。你可以直接构造一个查询对象或者用一个查询分析器来分析每一个查询字符串。 例如,这个查询将会在内容field 中匹配同时包含  “apple” 和 “bear” 的文档:

代码语言:javascript
复制
# Construct query objects directly
from whoosh.query import *
myquery = And([Term("content", u"apple"), Term("content", "bear")])

你可以用一个在qparse模块中默认的分析器来分析一个查询字符串。 QueryParser的构造函数的第一个参数是默认要搜索的field。 这通常是 “body text” field,第二个可选参数是用来理解如何分析该field的schema:

代码语言:javascript
复制
# Parse a query string
from whoosh.qparser import QueryParser
parser = QueryParser("content", ix.schema)
myquery = parser.parse(querystring)

一旦你有一个Searcher 和一个 查询对象,你可以用 Search的 search方法来跑一个查询,并获取一个Results 对象:

代码语言:javascript
复制
>>> results = searcher.search(myquery)
>>> print(len(results))
1
>>> print(results[0])
{"title": "Second try", "path": "/b", "icon": "/icons/sheep.png"}

默认的  QueryParser 实现了一个与Lucene的查询语言很类似的语言。它让你用 AND 和 OR  将 terms 连接起来,用NOT 消除 terms,用括号将terms组成句子,做一些范围(range)、前缀(prefix)、通配符(wildcard)查询,明确搜索的不同field。默认情况下,经常与AND 合用(所以默认情况下, 你举出的所有terms 必须在文档中,以让文本匹配):

代码语言:javascript
复制
>>> print(parser.parse(u"render shade animate"))
And([Term("content", "render"), Term("content", "shade"), Term("content", "animate")])
 
>>> print(parser.parse(u"render OR (title:shade keyword:animate)"))
Or([Term("content", "render"), And([Term("title", "shade"), Term("keyword", "animate")])])
 
>>> print(parser.parse(u"rend*"))
Prefix("content", "rend")

代码语言:javascript
复制
# -*- coding:utf-8 -*-
import os,json
from whoosh.qparser import QueryParser
from whoosh.index import create_in,open_dir
from whoosh.sorting import FieldFacet
from whoosh.fields import *
from whoosh.filedb.filestore import FileStorage
from jieba.analyse import ChineseAnalyzer
from IPython.core.display import display, HTML


# 导入中文分词工具
analyzer = ChineseAnalyzer()
# 创建索引结构  stored为True表示能够被检索
schema = Schema(
    title=TEXT(stored=True, analyzer=analyzer),
    path=ID(stored=False),
    content=TEXT(stored=True, analyzer=analyzer),
    phone_name=TEXT(stored=True, analyzer=analyzer),
    price=NUMERIC(stored=True),
    phoneid=ID(stored=True)
)
# 存储schema信息至'indexdir'目录下
ix_path = 'indexdir/'
ix_name = 'test_index_name'
if not os.path.exists(ix_path):
    os.mkdir(ix_path)
# ---------------------------------创建索引-------------------------------------
# ix_path 为索引创建的地址,indexname为索引名称
ix = create_in(ix_path, schema=schema, indexname=ix_name)
writer = ix.writer()
writer.add_document(phone_name='name', price="price", phoneid="id")  # 此处为添加的内容
print("建立完成一个索引")
writer.commit()
# -----------------------------增加索引 -----------------------------------------
# 增加索引   操作索引的行为,类似读写文件,需要用完close,或者使用with语句。
storage = FileStorage(ix_path)  # idx_path 为索引路径
ix = storage.open_index(indexname=ix_name)
# 按照schema定义信息,增加需要建立索引的文档,注意:字符串格式需要为unicode格式
with ix.writer() as w:
    # from whoosh.writing import AsyncWriter
    # writer = AsyncWriter(ix,delay=0.25)
    w.add_document(title=u"第一篇文档", path=u"/a", content=u"这是我们增加,的第一篇文档")
    w.add_document(title=u"第二篇文档,呵呵", path=u"/b", content=u"这是我们增加的第二篇文档,哈哈")
    w.add_document(title=u"帅哥,呵呵", path=u"/b", content=u"帅哥,哈哈")
    # w.update_document()
    # w.delete_document()

# ix.close()
#---------------------------------检索展示-----------------------------------------------
with storage.open_index(indexname=ix_name).searcher() as searcher:
    # 检索标题中出现'文档'的文档
    results = searcher.find(u"content", u"文档")
    # 检索出来的第一个结果,数据格式为dict{'title':.., 'content':...}
    for r in results:
        display(HTML('<h3>' + r.get('title') + '</h3>'))
        display(HTML(r.highlights("content")))  # 高亮标题中的检索词
        print(r.score)  # 分数
        print(r.docnum)

        doc = r.fields()
        jsondoc = json.dumps(doc, ensure_ascii=False)
        display(jsondoc)  # 打印出检索出的文档全部内容

#--------------------------------------------------------------------------------
new_list = []
index = open_dir(dirname=ix_path, indexname=ix_name)  # 读取建立好的索引
with index.searcher() as searcher:
    parser = QueryParser("要搜索的项目,比如“phone_name", index.schema)
    myquery = parser.parse("搜索的关键字")
    facet = FieldFacet("price", reverse=True)  # 按序排列搜索结果
    # limit为搜索结果的限制,默认为10
    results = searcher.search(myquery, limit=None, sortedby=facet)
    for result1 in results:
        print(dict(result1))
        new_list.append(dict(result1))

Whoosh 有一些很有用的预定义 field types,你也可以很easy的创建你自己的。

  • whoosh.fields.ID 这个类型简单地将field的值索引为一个独立单元(这意味着,他不被分成单独的单词)。这对于文件路径、URL、时间、类别等field很有益处。
  • whoosh.fields.STORED 这个类型和文档存储在一起,但没有被索引。这个field type不可搜索。这对于你想在搜索结果中展示给用户的文档信息很有用。
  • whoosh.fields.KEYWORD 这个类型针对于空格或逗号间隔的关键词设计。可索引可搜索(部分存储)。为减少空间,不支持短语搜索。
  • whoosh.fields.TEXT 这个类型针对文档主体。存储文本及term的位置以允许短语搜索。
  • whoosh.fields.NUMERIC 这个类型专为数字设计,你可以存储整数或浮点数。
  • whoosh.fields.BOOLEAN 这个类型存储bool型
  • whoosh.fields.DATETIME 这个类型为 datetime object而设计更多详细信息
  • whoosh.fields.NGRAM 和 whoosh.fields.NGRAMWORDS 这些类型将fiel文本和单独的term分成N-grams(更多Indexing & Searching N-grams的信息)

参考:https://blog.csdn.net/u012387575/article/details/52187920 https://blog.csdn.net/u012387575/article/details/52188054 https://www.cnblogs.com/muty/p/8540711.html https://cloud.tencent.com/developer/article/1374967 https://www.bbsmax.com/A/B0zq6V0rJv/

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/11/23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
Elasticsearch Service
腾讯云 Elasticsearch Service(ES)是云端全托管海量数据检索分析服务,拥有高性能自研内核,集成X-Pack。ES 支持通过自治索引、存算分离、集群巡检等特性轻松管理集群,也支持免运维、自动弹性、按需使用的 Serverless 模式。使用 ES 您可以高效构建信息检索、日志分析、运维监控等服务,它独特的向量检索还可助您构建基于语义、图像的AI深度应用。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档