图书检索工具 (Book Searcher)
面向千万级图书目录(中文370万 + 英文770万)的高性能多模式检索工具。支持五种检索方式:手动单条件检索、高级多条件组合检索、表达式检索、Excel批量检索和关键词过滤。内置ISBN哈希索引实现O(1)查找,pandas向量化文本搜索,tkinter图形界面。
何时使用
- 用户需要按书名、ISBN、作者、出版社、年份等字段检索图书
- 用户需要多条件布尔逻辑组合检索(如"书名含'数学' AND 出版社='高等教育出版社' AND 年份≥2020")
- 用户需要从Excel批量导入书单并检索
- 用户需要按关键词过滤图书目录
- 用户需要打包Python图书检索工具为Windows可执行程序
- 用户提到
book_search_tool.py或图书检索相关需求
数据获取方式
本工具的底层检索数据为中外文图书目录清单(中文370万条 + 英文770万条,共1147万条),获取方式:
- 在线申请:访问 https://www.vipslib.com/apply.html,说明需要原始中外文图书清单,用于查询图书使用
- 邮件申请:发送邮件至 vipsmart@vipslib.com,说明用途和数据需求
- PDF全文提取:检索到所需图书后,同样可通过上述地址联系批量提取图书PDF全文
项目结构
scripts/
|-- book_search_tool.py # 主程序(tkinter GUI + 高级检索 + 批量检索 + 关键词检索)
|-- batch_search.py # CLI:从Excel模板批量检索
+-- keyword_search_cn.py # CLI:关键词过滤(仅中文库)
assets/
|-- config_template.json # 配置模板(用户填写路径)
references/
+-- csv_format.md # CSV数据格式规范
架构概览
系统分三层:
- BookDataLoader — 读取配置目录下的CSV文件,合并为单个DataFrame,标记每行来源列
- SearchEngine — 核心检索逻辑:
- 构建ISBN哈希索引(
dict {isbn: [row_indices]})实现O(1)查找 - 缓存列数据为numpy数组实现零拷贝访问
search()方法:子串匹配,支持 title/author/publisher/isbn/book_id/year 多字段 + year范围筛选search_advanced()方法:多条件布尔逻辑组合检索,支持字段:标题/作者/出版社/ISBN/年份/编号,逻辑:AND/OR,年份支持 year_gte/year_lte 范围比较search_batch_fast()方法:批量检索,自动调度快速路径(ISBN哈希)和回退路径(全文扫描)
- 构建ISBN哈希索引(
- BookSearchApp — tkinter GUI,6个Tab:手动检索、高级检索、批量检索、关键词检索、加载日志、路径设置
检索策略(关键设计)
search_batch_fast() 使用两级策略:
- 有ISBN → 哈希查找:O(1)。ISBN是唯一标识,哈希命中直接返回,哈希未命中直接返回"未找到",无需回退全文扫描
- 无ISBN → 全文扫描:回退到
search(),在 title/author/publisher 列做子串匹配
此设计消除了title/副标题不一致导致不必要全表扫描的性能陷阱。
高级检索设计(v3.1新增)
高级检索提供两种模式:
- 条件构建模式:通过UI动态添加条件行,每行包含逻辑关系(AND/OR)、字段选择(T=标题/A=作者/P=出版社/I=ISBN/Y=年份/ID=编号)、关键词、匹配方式(包含/精确)。末行显示+/-按钮,出版时间范围可单独设置起止年份
- 表达式模式:直接输入布尔表达式,如
T=数学 AND P=高等教育 OR A=张三
search_advanced() 核心逻辑:
- 多条件按左结合顺序逐步合并(左折叠)
- AND → 取交集(
mask &= cond) - OR → 取并集(
mask |= cond) - year字段支持数值范围比较(year_gte/year_lte)
配置:首次使用
1. 准备数据
工具需要一个或多个CSV文件。参见 references/csv_format.md 了解列格式要求。
典型目录结构:
books/
|-- english/
| |-- en_books_part1.csv
| +-- en_books_part2.csv
+-- chinese/
|-- cn_books_0.csv
|-- cn_books_1.csv
+-- cn_books_2.csv
2. 创建 config.json
将 assets/config_template.json 复制到项目目录重命名为 config.json,编辑路径:
{
"en_dir": "D:/Data/books/english",
"cn_dir": "D:/Data/books/chinese",
"max_results": 500,
"batch_max_per": 5
}
en_dir/cn_dir:CSV目录的绝对路径(可省略任一)max_results:GUI手动检索最大显示条数batch_max_per:批量检索每条查询最大返回条数
3. 安装依赖
pip install pandas openpyxl pyinstaller
Tkinter在Windows上默认随Python附带。
使用场景
场景A:交互式GUI检索
cd <project-dir>
python scripts/book_search_tool.py
- 手动检索Tab:输入书名/ISBN/作者/出版社/年份,查看结果
- 高级检索Tab:多条件布尔组合检索或直接输入表达式
- 批量检索Tab:导入Excel模板,逐行检索
- 关键词检索Tab:输入逗号分隔关键词,全库过滤title
- 路径设置Tab:配置数据目录路径
场景B:从Excel批量检索(CLI)
python scripts/batch_search.py "<path/to/search_template.xlsx>"
Excel模板需含列:title、isbn13、author、publisher。结果输出为带时间戳的Excel文件。
场景C:关键词过滤(CLI)
python scripts/keyword_search_cn.py
编辑脚本修改 KEYWORDS 列表和目录路径。输出Excel含列:id、title、isbn13、匹配关键词标签。
场景D:打包为Windows可执行程序
- 将
book_search_tool.py从scripts/复制到项目根目录 - 在项目根目录直接打包:
pyinstaller --onedir --windowed --name "图书检索工具" ^
--hidden-import openpyxl --hidden-import pandas ^
--hidden-import tkinter --hidden-import pathlib ^
--hidden-import threading --hidden-import re ^
--hidden-import json --hidden-import time ^
book_search_tool.py
- 将
config.json复制到dist/图书检索工具/ - 将
dist/图书检索工具/目录打包为zip分发给用户
安装:解压zip到桌面任意目录,双击 图书检索工具.exe 运行。如需桌面快捷方式,手动右键 exe → 发送到桌面快捷方式。
性能参考
| 操作 | 数据规模 | 耗时 | |------|---------|------| | 加载1147万条记录 | 11,471,406行 | ~75s | | 构建ISBN哈希索引 | 9,450,000唯一ISBN | ~26s | | 批量检索(3.4万查询,99% ISBN) | 34,039条 | ~20min | | 关键词过滤(3关键词 × 370万行) | 3,720,000行 | ~1s | | 高级检索多条件组合 | 11,470,000行 | <3s |
已知限制
- 全量数据加载到内存(1147万条约8GB),推荐16GB以上内存
- GUI进度条使用tkinter
after()配合节流机制,避免队列堆积——勿移除内部去重逻辑 - ISBN哈希索引假设ISBN为唯一标识;快速路径不做title/author匹配验证——此为性能设计
- CSV使用
pd.read_csv(dtype=str)读取,确保ISBN和ID存储为字符串而非数字 - 高级检索条件行使用grid布局直接堆叠(v3.1已修复Canvas+Frame竞争bug)
- 表达式模式需严格遵循
字段=关键词 逻辑 字段=关键词格式
修改脚本指南
适配新数据集时:
- book_search_tool.py:
_build_indices()构建哈希索引,search()执行文本扫描,search_advanced()执行多条件布尔检索。CSV列名不同时修改FIELD_MAP和COLS映射 - batch_search.py:
read_template()读取Excel查询文件,调整列匹配逻辑 - keyword_search_cn.py:修改
KEYWORDS列表和目录路径
故障排除
| 症状 | 原因 | 修复 |
|------|------|------|
| 进度条卡在0% | after() 队列溢出 | 已内置节流;减小progress回调的step值 |
| TypeError: progress_cb takes 1 arg but 2 given | build_indices() 传递 (value, task) 元组 | 使用 lambda v, t="": callback(v) |
| PyInstaller: pathlib 导入错误 | spec文件hidden-import前有多余空格 | 移除空格:"pathlib" 非 " pathlib" |
| CSV编码错误 | 文件非UTF-8 | 对GBK中文文件添加 encoding='gbk' |
| ISBN匹配失败 | ISBN存储为float | 确保CSV使用 dtype=str 读取 |
| 高级检索条件行无法添加 | Canvas+Frame布局竞争 | 已在v3.1修复:改用grid布局直接堆叠 |
Scan to join WeChat group