本地全文搜索工具

Python 倒排索引 + 命令行交互,在文档目录里秒级检索关键词。

场景:本地文档检索 技术栈:Python 来源:GitHub 参考

在线演示

0文档数
0词项数
0命中文档
0 ms检索耗时

等待操作:载入示例语料或粘贴自己的文档集,先“构建索引”,再输入查询词“搜索”。

项目简介

当文件散落在多个目录、用资源管理器翻到眼花时,一个本地全文搜索工具就能解决。本页实现基于倒排索引的迷你搜索引擎:首次扫描建索引,之后关键词查询 O(1) 定位文档;纯 Python 标准库,无第三方依赖。

代码示例:倒排索引构建

py
import re
import json
from pathlib import Path

TOKEN = re.compile(r"[\u4e00-\u9fff]|[a-zA-Z0-9_]+")

def tokenize(text: str) -> list[str]:
    # 中文按单字索引、英文按词索引,兼顾检索与内存
    return [t.lower() for t in TOKEN.findall(text)]

def build_index(root: Path) -> dict[str, list[int]]:
    index: dict[str, list[int]] = {}
    docs: list[str] = []
    for p in sorted(root.rglob("*")):
        if not p.is_file() or p.suffix.lower() in {".pyc", ".png", ".jpg"}:
            continue
        try:
            text = p.read_text(encoding="utf-8", errors="ignore")
        except OSError:
            continue
        doc_id = len(docs)
        docs.append(str(p))
        seen: set[str] = set()
        for tok in tokenize(text):
            if tok not in seen:
                seen.add(tok)
                index.setdefault(tok, []).append(doc_id)
    return index, docs

def save(index: dict, docs: list[str], out: Path) -> None:
    out.write_text(json.dumps({"index": index, "docs": docs}, ensure_ascii=False), encoding="utf-8")

代码示例:查询与命令行入口

py
import sys

def search(index: dict, docs: list[str], query: str) -> list[str]:
    toks = tokenize(query)
    if not toks:
        return []
    hits: set[int] | None = None
    for t in toks:
        ids = set(index.get(t, []))
        hits = ids if hits is None else (hits & ids)  # 全部关键词命中
    return [docs[i] for i in sorted(hits)] if hits else []

def main() -> int:
    if len(sys.argv) < 2:
        print("usage: local_search.py <keyword> [root_dir]")
        return 1
    root = Path(sys.argv[2]) if len(sys.argv) > 2 else Path.cwd()
    index_path = root / ".search_index.json"
    if not index_path.exists():
        print("building index...")
        index, docs = build_index(root)
        save(index, docs, index_path)
    data = json.loads(index_path.read_text(encoding="utf-8"))
    for hit in search(data["index"], data["docs"], sys.argv[1])[:20]:
        print(hit)
    return 0

if __name__ == "__main__":
    raise SystemExit(main())

操作步骤

  1. 首次运行 python local_search.py 关键词 目录 会自动扫描目录并生成 .search_index.json。
  2. 之后同目录查询直接命中索引,秒级返回文件路径列表。
  3. 文档更新后可重建索引文件,或自行实现增量更新(记录 mtime)。

完整可运行工程

来源参考