科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道在Linux环境用Python下开发全文索引 (2)

在Linux环境用Python下开发全文索引 (2)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

随着信息量的增长,高效地定位特定信息变得越来越重要。本专栏将探讨全文索引领域,并集中讨论作者的公共域 indexer 模块。

作者:yiaring 来源:赛迪网技术社区 2007年10月20日

关键字: 操作系统 索引 python Linux

  • 评论
  • 分享微博
  • 分享邮件
 

关于 indexer

indexer 使用出现的词语的数据库。版本 0.1X (alpha 测试版)只能搜索全文单词结构固定的文档。作为可选项,搜索能将符合条件的文档按照搜索词语的出现频率并且对比文档长度来排列。 indexer 能以不同方式进行扩展,某些扩展方式逻辑化而直接,其它则更为复杂。

布尔能力很简单而且也已经在按计划实施。由于 indexer 跟踪哪些文档中包含哪些单词(和出现次数),因此如果要在规则中加入逻辑或者根据搜索词语出现或不出现来包括文件是很容易实现的。实际上,目前的功能本质上默认为在每个查找词语中间加 AND。(我的直觉是大多数现行的搜索都是这种 "x AND y AND z" 方式的搜索。)

规则表达式几乎无法加入到 indexer 中,据我所知没有一个数据库搜索系统具有哪些文件包含符合哪些规则表达的内容的列表。实用起见,规则表达式需要以特殊方式处理 -- 为此我们使用 grep。

短语和近似搜索现在并未实行,但实施并不困难。基本上,除了每个文件中的每个词语的出现频率,还必须收集每个文件中词语出现的偏移列表。根据该列表,我们能推论短语和近似度。然而,我认为这样做会大幅增加数据库的大小和搜索时间。

概念上,词干和探测法搜索可能已在现有的基本框架之中,但其需要花费很大的工作量。这种方法的确能减小数据库大小,因为只需存储正则形式而不必存储变化形式,但词语转换需要消耗外部类属词典和变化规则形态。

indexer 编程

建议读者下载 indexer 源代码 (请参阅本文后的参考资料)。它只有一个文件,而且有详尽的注解,相当于一本编程书籍。

以下是有关程序结构的备注。请注意文档是编号的,每个文档都关联一个整数 "fileid"。 indexer 有一个 Python 词典,其关键字为词语,其值本身又是词典,这个词典的关键字为 "fileid",其值为 "fileid" 指定的词语在文件中的出现次数。Python 词典的查找效率很高,而且连结 "fileid" 和实际文件名的附加工作相对很少。

从大体上说,indexer 包含一个被称为 GenericIndexer 的抽象类。在 GenericIndexer 中定义的最重要的方法为 add_files() 和 find()。如果存储机制需要最终化(大部分都需要)的话, save_index() 方法也很重要。

使 GenericIndexer 抽象的原因是它不能被实例化;而其子类只要完成进一步的工作后就能被实例化。术语"抽象"来源于 C++,在 C++ 中它可以是类的正规声明。在 Python 中并没有该正规声明,而类的“抽象”只是类的开发者给其用户的建议。Python 是这样处理的 -- 不强制数据隐藏、成员可见、继承需求和类似的做法,而是遵从在何时完成的规范。然而, GenericIndexer 能很好的强制执行其建议,因为它的许多方法由 "raise NotImplementedError" 行组成。特别是 __init__() 调用 "NotImplemented" 的方法之一的 load_index()。

GenericIndexer 的派生在实际存储索引中有不同的实现方法。其中最实用的是 ZPickleIndexer,将 zlib 和 cPickle 合并,存储压缩的词典。一方面为了兴趣,一方面又由于令人吃惊的性能测试结果(请参阅基准测试模块),我创建了许多其它 SomethingIndexer 类。如果愿意,shelve、XML、flat-file 和 cPickle 的类都已经具备。创建 NullIndexer 派生,高效地将每个索引存放到 /dev/null 是可能的(虽然有些无意义),而且每次开始搜索时都需要重新索引。

在提供 load_index() 和 save_index() 实现的同时,具体的(与“抽象”相反) SomethingIndexer 类从“mixin 类”中继承 SomethingSplitter。目前,这样的类只有 TextSplitter,但是其他相似的类会不断出现。SomethingSplitter 提供非常重要的 splitter() 方法,它获得一个文本字符串并把它分割成组成其的单词。这种方法比想象的要难得 多;区分是或者不是一个单词是非常微妙的。以后,我希望创建 TextSplitter 的派生,比如 XMLSplitter、TeXSplitter、PDFSplitter 和相似的类。因而现在我们可以试图以相对原始的方法查找文本单词。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章