1 . 绪论
1.1 研究背景与意义
近年来,高校图书馆数字化转型持续深入,馆藏电子化与纸质资源并行扩张已成为普遍现象。以普通本科院校为例,年均新增纸质图书可达十万册以上,加上采购的电子书数据库,读者实际可触达的资源规模远超其浏览能力。这种"信息过载"的局面使得传统依赖分类导航和关键词检索的查找方式效率锐减,读者往往只能接触到热门或教师指定的少量文献,大量优质馆藏处于"零借阅"状态。与此同时,商业阅读平台和知识付费产品已广泛部署推荐算法,用户对内容发现工具的期待随之提高,图书馆静态的检索服务与读者日常使用的数字化产品之间形成了明显的体验落差,师生对个性化文献服务的呼声愈发突出。
学术界对图书推荐的研究由来已久,协同过滤和基于内容的推荐是两条主流技术路线,在电商和流媒体场景中已证实有效。但图书馆场景有其特殊性:借阅行为属于低频稀疏的隐式反馈,远不如评分数据稠密;用户身份更替周期固定,每年毕业生离校、新生入学都会引入显著的冷启动问题;此外,专业教材与课外读物的借阅逻辑差异巨大,单一算法难以兼顾不同阅读动机下的需求模式。现有研究多在公开数据集上验证模型,对上述实际约束条件的处理深度不足,轻量级落地方案尤其缺乏。基于此,本课题选择在实际的高校图书馆业务环境中,面对真实产生的借阅流水而非实验室数据集,探讨如何将协同过滤、关联规则挖掘和用户分类偏好分析三种机制有机融合,构建一个能在数据稀疏和冷启动条件下稳定输出的混合推荐模型。相较于前人偏重单一算法优化的思路,本研究专注于多种推荐策略的工程化组合与适配,力求在有限的系统开销下实现可感知的推荐质量提升。
从实践层面审视,混合推荐系统的引入直接对应着高校图书馆提升文献利用率和服务精细化的现实需求。当前多数高校馆仍将智能化建设聚焦于空间管理和自助设备,对用户借阅行为背后隐含的兴趣结构和潜在阅读需求缺乏系统性的挖掘工具,馆藏推荐环节长期依赖人工书单和简单的新书上架通知,覆盖面和更新效率均十分有限。本研究构建的推荐引擎可直接嵌入现有图书馆管理系统,将冷冰冰的馆藏目录转化为动态适配的个性化推荐列表,使读者更高效地发现与其学科背景和阅读偏好匹配的图书资源。这种能力对于优化文献资源配置、降低馆藏滞还率、提升读者满意度均有直接助益,也能为后续的文献采购决策提供数据支撑。
从学科角度观察,本研究是对推荐系统工程化应用的有益补充。图书馆场景的低频稀疏数据、强周期性用户更替以及专业读物与通识读物的特征差异,构成了一组有别于常规推荐基准的约束条件,在此环境下验证混合策略的有效性,能够为推荐算法从实验室走向实际业务提供参考案例。系统采用协同过滤、Apriori关联规则与时间衰减加权的分类偏好模型进行加权融合,其设计和评估过程在一定程度上丰富了"混合推荐在领域数据上的工程适配"这一研究方向的实证材料。此外,整个系统基于Flask和轻量级数据库构建,面向中小型图书馆的实际条件进行设计,这种以低成本可部署为导向的技术选型也为同类机构的智能化改造提供了可参照的落地路径。
1.2 国内外研究现状
进入信息社会,高校图书馆正面对馆藏资源迅速膨胀与读者日益增长的个性化、精准化信息需求之间的突出矛盾。传统依赖被动检索的服务模式,已难以适应当前师生对高效获取知识资源的需要。因此,运用数据挖掘技术改进图书馆服务,建立智能推荐系统,已成为提升服务效能、盘活馆藏资源、推动服务模式转型的关键途径。我国在这一方向的研究,已呈现出从问题剖析、技术探索到系统开发与实践验证的逐步深化过程,并在理论奠基、算法运用、系统构建与实践总结等方面取得了较为丰富的成果。国内研究已形成的主要认识可归纳为以下几个方面:
1.对系统建设必要性与核心作用形成共识
研究普遍指出,传统图书馆系统普遍存在图书借阅率偏低、闲置资源较多、检索效率不高、个性化服务水平有限等问题。引入智能推荐系统,被视为对传统借阅模式的有力补充,其核心作用主要体现在:主动响应用户个性化需求,提升检索效率与使用体验;提高馆藏资源利用效率,减少图书闲置现象;辅助图书馆实现科学化管理,为资源采购、排架调整、旧书剔除等工作提供数据依据;促进读者间的交流互动,借助"书友推荐"等功能构建阅读社区。
2.对主流推荐算法技术进行了较广泛探讨与实际应用
协同过滤算法是研究与应用的重点方向,可分为基于用户和基于项目两种类型。其优势在于能够发现用户的潜在兴趣,但也面临"冷启动"和"数据稀疏"等挑战。
基于内容的推荐算法主要依据图书元数据与用户历史兴趣进行匹配推荐,优点是不依赖其他用户行为数据,能够缓解新项目推荐问题,但对项目特征提取要求较高,且容易导致推荐结果多样性不足。
关联规则挖掘算法以Apriori算法为代表,用于从借阅记录中发现频繁出现的图书组合与关联规则,已成为挖掘图书间内在联系、构建推荐列表的重要基础。
为克服单一算法的局限,混合推荐策略已成为主流解决思路,常见方式包括并行混合与级联混合等。
3.对图书与用户特征建模开展了具有一定规范性的探索
"中图分类法"被广泛认可为描述中文图书内容特征的核心依据。不少研究探讨了基于中图分类树节点深度计算图书相似度的方法,将其作为衡量图书内容相关性的重要基础。此外,图书的题名关键词、作者、ISBN及用户标签等也常作为辅助特征。在用户特征方面,研究不仅关注用户的学院、专业等静态属性,更注重从历史借阅行为中提取动态的"兴趣偏好向量",一般通过分析用户所借图书的中图分类分布、提取高频题名关键词等方式实现。
4.对系统整体架构设计与实现进行了较完整阐述
相关研究提出的典型系统架构多包含以下三层:
数据层:负责从图书馆集成管理系统同步并预处理借阅记录、书目数据、用户信息等,构建数据仓库。
算法引擎层:作为核心处理部分,集成各类数据挖掘与推荐算法,完成离线计算与模型训练,生成个性化推荐列表、相关图书推荐、热门排行等内容。
应用展示层:为用户提供交互界面。当前发展趋势显示,系统载体正从传统网页端延伸至移动端,特别是基于微信公众号或小程序进行开发,以提升服务便捷性。此外,信息可视化技术被用于直观展示用户的借阅历程、兴趣分布、图书关联网络等,增强了系统的交互体验与结果可解释性。
总结而言,国内在"基于数据挖掘的高校图书馆智能推荐系统"领域已积累了较多成果,在理论认识、算法应用与系统构建等方面已形成基本完整的体系。当前研究已进入注重实践深化、细节优化并与新兴技术结合的阶段。然而,一些挑战仍然存在,例如多源异构数据的整合利用、深度学习等复杂算法的引入与效果验证、推荐系统长期效果与用户满意度的实证研究等,仍是未来需要深入探索的方向。总体来看,该领域研究仍有广阔发展空间,其持续进展将进一步推动高校图书馆向智能化、个性化与精准化的服务模式演进。
1.3 本文研究内容
本文围绕高校图书馆个性化推荐的实际需求,设计并实现了一个轻量级的混合推荐系统。在系统架构层面,采用B/S模式,后端基于Python语言的Flask框架组织业务逻辑,前端以Bootstrap实现响应式页面布局,结合ECharts完成数据可视化,数据库选用SQLite以降低部署门槛。系统按照功能拆分为用户认证、图书浏览与搜索、借阅归还、个性化推荐、用户画像展示以及管理员后台等模块,各个模块通过Blueprint注册形成松耦合结构。推荐引擎是系统的核心部分,本文为适应图书馆借阅数据低频、稀疏且用户更替频繁的特点,没有依赖单一算法,而是将协同过滤、Apriori关联规则、用户分类偏好分析和热门推荐四种策略进行加权混合。其中协同过滤通过Jaccard系数计算用户行为相似度,关联规则挖掘图书共借关系并以置信度阈值0.1过滤,分类偏好引入时间衰减权重追踪用户阅读兴趣变化,热门推荐作为补充手段应对新用户冷启动。混合时分别赋予0.4、0.3、0.2、0.1的权重系数,在保证多样性的同时兼顾准确性。
为了验证推荐效果,本文通过脚本生成了包含五千册图书、五十位用户和一千余条借阅记录的模拟数据集,并在此基础上对推荐结果进行了准确率、召回率和F1分数的离线评估,同时构建了管理后台用于实时查看借阅趋势、分类分布和推荐系统运行状态。整体方案以低计算开销为前提,着力将多种推荐机制的工程化组合落到实处,力图解决图书馆场景下数据稀疏和新用户冷启动带来的推荐质量下降问题,为中小型图书馆的智能化服务建设提供一条可直接参照的实现路径。
2 . 相关技术与理论
2.1 Web开发相关技术
2.1. 1 Flask框架
Flask是基于Python语言的一款轻量级Web应用框架,由Armin Ronacher于2010年发布。不同于Django等全栈框架,Flask核心仅保留请求路由、模板渲染和会话管理等基础功能,其他组件如数据库ORM、表单验证、用户认证等均以扩展包形式按需集成。这种微内核的设计使得开发者能够根据具体场景自由组合技术栈,避免因框架内置过多冗余模块而导致系统臃肿。
Flask的请求处理遵循WSGI规范,当客户端发起HTTP请求时,框架通过路由装饰器将URL映射到对应的视图函数。视图函数执行完毕返回响应对象,经由中间件链处理后送回客户端。Flask内置Jinja2模板引擎支持模板继承、控制流和过滤器等功能,配合静态文件分发机制可以高效地生成服务端渲染页面。
在本系统中,选用Flask的主要原因包括:项目规模适中,不需要大型框架的完整分层结构;推荐算法的核心计算全部采用Python实现,统一的语言栈减少了跨语言调用的开销;丰富的扩展生态可以满足ORM映射、登录管理和API接口等场景需求。系统通过Blueprint将认证、前台展示、管理后台和API接口拆分为独立的模块,各模块之间以请求上下文传递数据,整体结构清晰且便于后续维护。
2.1. 2 Bootstrap与ECharts
Bootstrap是由Twitter团队推出的前端框架,提供了栅格布局、预定义样式组件和响应式断点机制。开发者无需从零编写CSS即可快速搭建适配桌面端和移动端的页面结构。本系统的图书列表、推荐展示、管理后台等页面均采用Bootstrap的卡片、导航栏、表格和模态框等组件构建,外观统一且交互行为一致。
ECharts是Apache软件基金会维护的开源可视化库,底层依赖Canvas和SVG渲染引擎,支持折线图、柱状图、饼图、散点图等多种图表类型。本系统在数据统计看板和用户偏好分析页面中引入ECharts,实现了借阅趋势、分类分布等数据的动态可视化展示,直观呈现推荐效果的评估结果。
2.2 数据存储技术
2. 2 . 1 SQLite数据库
SQLite是一款嵌入式关系型数据库引擎,不需要独立的服务进程,所有数据存储于单个磁盘文件中,通过C语言库直接读写。SQLite支持SQL-92标准的绝大部分语法,包括事务、索引、触发器和视图等特性,但在并发写入方面存在局限,适用于单机小规模应用场景。
本系统选择SQLite主要基于两点考虑:其一,高校图书馆推荐系统的日均请求量有限,SQLite的读写性能完全能够满足需求;其二,嵌入式部署无需额外配置数据库服务器,降低了系统的安装和运维门槛,便于在中小型图书馆推广使用。数据表设计涵盖用户、图书、借阅记录、分类和用户偏好等实体,通过外键约束保证关联数据的完整性。
2. 2 . 2 Flask-SQLAlchemy
Flask-SQLAlchemy是SQLAlchemy针对Flask框架的专用扩展,将数据库连接管理、会话生命周期和模型声明等操作封装为Flask式的调用接口。通过继承db.Model基类定义Python类,即可自动映射为数据库表,模型的增删改查通过会话对象统一管理,底层自动生成对应的SQL语句。这种ORM方式使得开发者可以使用面向对象的思维处理数据逻辑,减少了手写SQL的出错概率,同时也方便在不同数据库引擎之间迁移。
2.3 推荐算法相关理论
2. 3 . 1 协同过滤
协同过滤是推荐系统中应用最广的技术之一,核心思想是利用群体行为数据挖掘用户或物品之间的相似关系,从而为目标用户生成推荐。协同过滤分为基于用户和基于物品两类,本系统采用基于用户的协同过滤方法。
基于用户的协同过滤假设相似用户具有相近的阅读偏好。
2. 3 . 2 关联规则
关联规则挖掘最早由Agrawal等人于1993年提出,用于从交易数据中发现物品之间的共现模式。在图书推荐场景中,关联规则可以揭示图书之间"经常一起被借阅"的关系,当读者借阅某本书时,系统自动推荐与之关联的其他图书。
Apriori算法是关联规则挖掘的经典方法,其核心是利用"频繁项集的所有子集必为频繁项集"这一先验性质,通过逐层搜索的方式生成候选集并剪枝。
支持度表示前件A和后件B同时被借阅的用户占比,置信度表示在借阅A的用户中同时借阅B的比例。本系统设置最小支持度阈值为0.01,最小置信度阈值为0.1,仅保留高于门槛值的规则纳入推荐引擎,以此过滤偶然共现带来的噪声。
2. 3 . 3 分类偏好与时间衰减
协同过滤和关联规则都依赖足够的用户行为数据,对于新用户或借阅记录稀疏的用户效果有限。分类偏好推荐通过分析用户对不同图书分类的兴趣程度提供补充。
ays表示借阅行为距今的天数,参数30为半衰期常量,含义是距今30天的借阅行为权重衰减至当期权重的二分之一。通过时间衰减机制,用户的近期阅读偏好被赋予更高权重,长期未涉足的分类兴趣逐渐降低。系统根据偏好权重排序获取用户最感兴趣的若干分类,从这些分类中选择热门图书生成推荐结果。
2.4 混合推荐策略与评估方法
单一推荐算法各有侧重,协同过滤依赖群体行为相似性但受冷启动和数据稀疏影响较大,关联规则可解释性强但计算开销随数据规模增长明显,分类偏好直观但对图书内容粒度依赖较高。混合推荐旨在综合多种算法的优势,通过加权融合弥补各自不足。
其中α=0.4、β=0.3、γ=0.2、δ=0.1,分别为协同过滤、关联规则、分类偏好和热门推荐的权重系数。权重配置综合考虑了各算法的准确性和适用场景,协同过滤作为核心策略权重最高,热门推荐作为兜底补充权重最低。
推荐效果评估采用信息检索领域常用的三项指标:准确率Precision衡量推荐列表中用户实际借阅的比例,召回率Recall衡量用户借阅记录中有多大比例被推荐列表覆盖,F1分数为两者的调和平均。
3 . 系统分析
3.1 可行性分析
经济可行性:本系统的开发成本主要集中在软件研发阶段,硬件方面利用高校图书馆现有服务器即可部署,无需额外采购专用设备。开发工具方面,Python语言、Flask框架、SQLite数据库、Bootstrap前端框架及ECharts可视化库均为开源产品,不产生商业授权费用。系统上线后的运维开支主要是服务器电力和网络带宽,成本在图书馆既有预算中即可覆盖。效益层面,系统通过个性化推荐提升图书借阅率,使馆藏资源得到更充分的利用,减少了读者查找文献的时间成本,间接服务于教学科研产出。开发周期预估为三个月,属短期投入,无需跨越预算年度即可交付使用。综上所述,系统从经济上是可行的。
技术可行性:后端采用Python语言配合Flask框架,该组合成熟稳定,社区活跃,有大量现成的扩展包支持数据库操作、用户认证和API构建等需求。SQLite作为嵌入式数据库满足单机小规模并发场景。前端采用Bootstrap和ECharts,不依赖复杂前端工具链即可实现响应式布局与数据可视化。推荐算法涉及的协同过滤、关联规则和分类偏好计算均运行于单机内存中,系统设定的数据规模为5000册图书和1000余条借阅记录,远未达到性能瓶颈。综上所述,系统从技术上是可行的。
操作可行性:系统面向三类用户:普通读者通过浏览器完成图书浏览、搜索、借阅和查看推荐等操作,页面布局参照主流电商网站设计,操作路径符合日常使用习惯;图书管理员通过后台面板完成数据查询和统计报表查看;系统管理员负责用户管理和推荐引擎维护。B/S架构免去了客户端安装环节,只要具备基本的网页浏览能力即可顺畅使用。综上所述,系统从操作上是可行的。
3.2 需求分析
3 . 2 . 1 业务流程分析
本系统的核心业务围绕个性化推荐展开,流程起点为用户进入系统浏览图书或请求推荐,终点为借阅行为完成并反馈评分数据,形成闭环的数据积累与推荐优化链路。
图书浏览与检索模块是用户接触馆藏的第一入口。读者可通过分类筛选、关键词搜索或排序条件(热门优先、最新上架、书名排序)浏览图书列表。点击某本图书进入详情页后,页面展示馆藏量、借阅次数、平均评分等元数据,同时侧栏自动呈现相似图书推荐。用户在详情页完成借阅操作后,系统记录借阅时间和应还日期,并将该行为纳入后续推荐计算的依据。该流程如图3.1所示。

图 3.1 图书浏览与检索流程
个性化推荐模块是系统的核心业务。当用户进入推荐页面,系统首先检查其借阅历史。若有足够记录,引擎并行执行协同过滤、关联规则和分类偏好三种算法,按权重混合后返回推荐列表;若用户为新注册或数据稀疏,系统自动切换至热门推荐为主的冷启动策略。推荐结果以卡片列表呈现,用户可点击查看详情并直接借阅。该流程如图3.2所示。

图 3.2 个性化推荐流程
借阅管理与反馈模块承担用户借阅记录查看和归还评分功能。读者可在"我的借阅"页面按状态筛选记录,对已归还的图书进行评分。评分数据经持久化存储后同步更新用户分类偏好,使下次推荐更贴近当前阅读兴趣。管理员可在后台查看全部借阅流水、逾期情况和评分分布。该流程如图3.3所示。

图 3.3 借阅管理与反馈流程
3 . 2 . 2 功能需求分析
系统按角色权限划分为三类用户场景,各类用户所及功能如图3.4所示。
普通读者用户的核心功能包括:浏览图书列表,支持按分类和关键词进行多条件筛选与排序;查看图书详情,获取馆藏状态、借阅统计和系统自动生成的相似图书推荐;接收个性化推荐,系统根据借阅历史采用混合算法生成推荐列表;管理个人借阅记录,按状态筛选,归还时提交评分和评论;查看个人阅读偏好画像,以可视化图表展示兴趣分类分布。图3.4(a)展示了读者用户的用例。

图3.4(a) 读者用户用例图
图书管理员用户的核心功能包括:查看系统数据概览,含用户数、图书数、借阅总量等统计卡片以及借阅趋势折线图和分类分布饼图;管理图书和借阅记录,支持按条件搜索和按状态筛选;查看推荐效果评估详情,包括各算法权重占比和采样用户的准确率、召回率、F1分数;导出借阅数据为CSV文件;重建推荐引擎以更新底层计算模型。图3.4(b)展示了管理员用户的用例。

图3.4(b) 管理员用例图
系统管理员的额外权限包括用户状态启停和角色变更,确保账户安全与权限分配的灵活性。以上功能需求覆盖了从图书发现、推荐接收到借阅反馈的完整链路,读者、管理员和系统之间的交互形成数据闭环,为后续功能模块设计和实现提供了明确的边界。
3 . 2 . 3 非 功能 性 需求分析
本系统的非功能性需求集中在以下方面。
可靠性方面,系统应保证核心业务流程(图书搜索、借阅提交、推荐生成)在正常负载下的服务连续性。当推荐引擎因数据不足无法生成个性化结果时,系统须自动降级为热门推荐,不能向用户返回错误页面或空白列表。
响应时间方面,普通页面(图书列表、详情页)服务器响应时间应控制在500毫秒以内。推荐生成操作因涉及内存中多算法并行计算,单次请求处理时间应控制在2秒以内。管理后台的统计图表渲染需在3秒内完成数据查询与前端绘制。
存储空间方面,SQLite数据库预估容量为:5000册图书记录约占2MB,50用户表可忽略,1000条借阅记录的初始数据量约300KB,加上推荐效果日志和用户偏好表,数据库文件整体不超过5MB,留有充足的扩展余量。
安全性方面,用户密码采用werkzeug提供的哈希算法存储,不保存明文。管理后台路由以装饰器校验管理员角色权限,未授权访问须重定向至首页。借阅归还操作校验用户身份,防止跨用户修改借阅记录。
4 . 系统设计
4.1 系统总体设计
本系统采用分层架构组织代码,按照数据流动方向自底向上划分为数据层、业务逻辑层和表示层。各层之间通过明确的接口传递数据,上层不直接访问下层的数据存储细节,下层也不依赖上层的视图实现。
数据层负责持久化存储和基础数据操作。该层以SQLite数据库文件为存储载体,通过Flask-SQLAlchemy提供的ORM机制将关系表映射为Python模型对象。主要模型包括用户、图书、借阅记录、分类和用户偏好等实体,模型之间通过外键约束维护引用完整性。推荐引擎的数据缓存(用户借阅字典、图书流行度计数、关联规则字典等)也驻留在本层的内存空间中,由初始化函数统一加载和周期性刷新。
业务逻辑层承担系统的核心处理任务。该层按功能域拆分为认证模块、图书管理模块、借阅管理模块和推荐引擎模块。认证模块负责密码校验和会话维护,图书管理模块处理图书列表的分页检索和多条件筛选排序,借阅管理模块执行借书库存扣减和还书状态更新并触发用户偏好重新计算。推荐引擎模块是业务逻辑层的核心,封装了协同过滤、关联规则、分类偏好和热门推荐四种算法的实现,通过混合加权函数整合各算法输出,对外提供统一的推荐接口。
表示层负责与用户交互。该层由Flask的路由调度器和Jinja2模板引擎协同工作,将HTTP请求分发至对应的视图函数,视图函数调用业务逻辑层获取数据后,交由模板引擎渲染为HTML页面或JSON响应。前端采用Bootstrap框架构建响应式布局,ECharts库用于绘制统计图表和管理后台的可视化面板。系统架构如图4.1所示。

图4.1 系统架构图
请求自顶向下穿越三层:用户在表示层触发操作,HTTP请求经路由分发进入业务逻辑层,业务逻辑层调用数据层接口完成读写后返回结果,表示层将结果渲染为最终页面呈现给用户。分层结构使得各层职责边界清晰,当需要替换推荐算法或调整前端样式时,修改局限在对应层内部,不会波及全系统。
4.2 系统功能模块设计
本系统旨在为高校图书馆读者提供个性化的图书推荐服务,同时为管理人员提供馆藏运营数据的可视化支撑。系统按角色和业务域划分为读者前台模块和管理后台模块两大组成部分。
读者前台模块面向普通用户,包含以下子模块:图书浏览与检索模块,支持按分类、关键词进行多条件筛选,并提供热门优先、最新上架、书名排序等排序维度;图书详情模块,展示馆藏状态、借阅统计和平均评分,侧栏输出相似图书推荐;个性化推荐模块,根据用户借阅历史通过混合算法生成推荐列表,新用户自动切换冷启动策略;借阅管理模块,记录读者当前借阅和归还历史,提供还书操作入口和评分反馈功能;用户画像模块,以可视化图表展示读者的分类兴趣分布和借阅行为统计。
管理后台模块面向管理员,包含以下子模块:数据概览模块,汇总用户数、图书数、借阅总量等关键指标,渲染借阅趋势折线图和分类分布饼图;用户管理模块,支持按条件搜索用户、启停账户和变更角色;图书管理模块,支持多条件检索图书列表和查看库存状态;借阅管理模块,可按状态筛选全部借阅记录并导出CSV文件;分类管理模块,展示各分类的图书数量分布;推荐系统统计模块,呈现混合权重分配和采样用户的推荐效果评估结果;推荐引擎重建模块,供管理员手动刷新底层计算模型。系统功能模块如图4.2所示。

图4.2 系统功能图
各模块之间通过共享数据库和推荐内存缓存实现数据联动。读者借阅行为的产生会更新借阅记录表,推荐引擎在下次调用时读取最新的用户借阅向量,使推荐结果持续贴近当前阅读偏好。管理后台的统计图表基于借阅表实时聚合查询,数据变更即时反映在可视化面板中。
4.3 数据库设计
4 . 3 . 1 数据关系设计
本系统采用关系型数据库SQLite存储结构化数据。核心实体包括系统用户、图书、图书分类、借阅记录、图书评分和用户分类偏好。各实体之间存在外键约束关系:借阅记录关联用户和图书,图书评分关联用户和图书,用户偏好关联用户和分类,图书关联分类。外键约束保证了引用完整性,当删除一本图书时,关联的借阅记录和评分记录同步处理,避免了孤立数据行的产生。
系统的实体关系如图4.3所示,图中标注了各实体的主键以及实体间的外键关联方向。

图4.3 系统E-R图
4 . 3 . 2 数据库表设计
本系统的数据库由users用户表、books图书表、categories分类表、borrow_records借阅记录表、book_ratings图书评分表和user_preferences用户偏好表组成,覆盖用户身份、图书元数据、借阅行为、评分反馈和兴趣画像五类信息。以下列出各表的核心字段结构。
users表记录注册用户的身份信息与档案资料。主键id为自增整数,username和email需保证唯一性,password_hash存储经哈希处理的密码密文,role字段区分普通用户和管理员,student_id、department、major和grade为可选档案字段,is_active标识账户启用状态。users表结构如表4.1所示。
表 4.1 users表
|---------------|--------------|-----|----------|------|
| 字段名 | 类型 | 允许空 | 键/约束 | 说明 |
| id | INTEGER | 否 | 主键 | 用户ID |
| username | VARCHAR(64) | 否 | 唯一索引 | 用户名 |
| email | VARCHAR(120) | 否 | 唯一索引 | 邮箱 |
| password_hash | VARCHAR(256) | 否 | | 密码哈希 |
| role | VARCHAR(20) | 是 | 默认'user' | 角色 |
| student_id | VARCHAR(20) | 是 | | 学号 |
| department | VARCHAR(100) | 是 | | 院系 |
| major | VARCHAR(100) | 是 | | 专业 |
| grade | INTEGER | 是 | | 年级 |
| is_active | BOOLEAN | 是 | 默认是 | 是否启用 |
books表记录图书的基本信息和馆藏状态。isbn为唯一标识,cate_id和cate_name分别存储分类编号和名称,total_copies表示馆藏总量,available_copies表示当前可借数量,borrow_count为累计借阅次数。books表结构如表4.2所示。
表4.2 books表
|------------------|--------------|-----|------|-------|
| 字段名 | 类型 | 允许空 | 键/约束 | 说明 |
| id | INTEGER | 否 | 主键 | 图书ID |
| isbn | VARCHAR(20) | 否 | 唯一索引 | ISBN号 |
| name | VARCHAR(200) | 否 | | 书名 |
| author | VARCHAR(200) | 是 | | 作者 |
| publisher | VARCHAR(200) | 是 | | 出版社 |
| cate_id | INTEGER | 是 | 外键 | 分类ID |
| cate_name | VARCHAR(100) | 是 | | 分类名称 |
| price | FLOAT | 是 | | 定价 |
| total_pages | INTEGER | 是 | | 页数 |
| total_copies | INTEGER | 是 | 默认1 | 馆藏数量 |
| available_copies | INTEGER | 是 | 默认1 | 可借数量 |
| borrow_count | INTEGER | 是 | 默认0 | 借阅次数 |
categories表存储图书分类体系。每条记录包含分类名称、父级分类引用和描述信息,book_count为属于该分类的图书数量统计。categories表结构如表4.3所示。
表4.3 categories表
|-------------|--------------|-----|------|--------|
| 字段名 | 类型 | 允许空 | 键/约束 | 说明 |
| id | INTEGER | 否 | 主键 | 分类ID |
| name | VARCHAR(100) | 否 | 唯一 | 分类名称 |
| parent_id | INTEGER | 是 | 外键 | 上级分类ID |
| description | TEXT | 是 | | 分类描述 |
| book_count | INTEGER | 是 | 默认0 | 图书数量 |
borrow_records表记录每一次借阅行为的完整生命周期。user_id和book_id分别关联用户表和图书表,borrow_date为借阅发起时间,due_date为应还日期,return_date为实际归还时间,status取值为borrowed、returned或overdue三种状态,rating和review字段供用户归还时填写。borrow_records表结构如表4.4所示。
表4.4 borrow_records表
|-------------|-------------|-----|--------------|------|
| 字段名 | 类型 | 允许空 | 键/约束 | 说明 |
| id | INTEGER | 否 | 主键 | 记录ID |
| user_id | INTEGER | 否 | 外键 | 用户ID |
| book_id | INTEGER | 否 | 外键 | 图书ID |
| borrow_date | DATETIME | 是 | | 借阅日期 |
| due_date | DATETIME | 是 | | 应还日期 |
| return_date | DATETIME | 是 | | 归还日期 |
| status | VARCHAR(20) | 是 | 默认'borrowed' | 借阅状态 |
| rating | INTEGER | 是 | | 评分 |
| review | TEXT | 是 | | 评论 |
book_ratings表存储用户对图书的独立评分记录,与borrow_records中的评分字段互补,用于用户画像和协同推荐的计算。user_id和book_id组合设置唯一约束,保证每条用户-图书评分记录不重复。book_ratings表结构如表4.5所示。
表4.5 book_ratings表
|-----------|----------|-----|---------|------|
| 字段名 | 类型 | 允许空 | 键/约束 | 说明 |
| id | INTEGER | 否 | 主键 | 评分ID |
| user_id | INTEGER | 否 | 外键,组合唯一 | 用户ID |
| book_id | INTEGER | 否 | 外键,组合唯一 | 图书ID |
| rating | FLOAT | 否 | | 评分值 |
| timestamp | DATETIME | 是 | | 评分时间 |
user_preferences表记录每个用户对各分类的兴趣权重。preference_score通过时间衰减函数计算,当用户产生新的借阅行为时触发权重更新。user_preferences表结构如表4.6所示。
表4.6 user_preferences表
|------------------|----------|-----|-------|------|
| 字段名 | 类型 | 允许空 | 键/约束 | 说明 |
| id | INTEGER | 否 | 主键 | 偏好ID |
| user_id | INTEGER | 否 | 外键,索引 | 用户ID |
| category_id | INTEGER | 是 | 外键 | 分类ID |
| preference_score | FLOAT | 是 | 默认0.0 | 偏好得分 |
| update_time | DATETIME | 是 | | 更新时间 |
以上六张表的外键关系与图4.3中的实体关系一一对应:borrow_records表的user_id引用users表的id,book_id引用books表的id;book_ratings表的user_id引用users表的id,book_id引用books表的id;user_preferences表的user_id引用users表的id,category_id引用categories表的id;books表的cate_id引用categories表的id。
4.4 推荐算法设计与实现
4 . 4 . 1 数据结构与初始化
推荐引擎在内存中维护四类核心数据结构,其类型与用途如表4.7所示。
表4.7 核心数据结构
|-------------------|---------------------------------|-----------|
| 数据结构 | 类型 | 用途 |
| user_borrows | Dictint, List\[int] | 用户借阅记录映射 |
| book_popularity | Dictint, int | 图书借阅频次统计 |
| category_scores | Dictint, Dict\[int, float] | 用户分类兴趣权重 |
| association_rules | DictTuple\[int,int, float] | 关联规则及其置信度 |
系统启动时调用初始化函数,从borrow_records表中筛选状态为"已归还"的记录,逐条加载至内存。对于每条借阅记录,将图书ID追加到对应用户的借阅列表中,同时增加该图书的流行度计数。若图书的分类信息存在,则对用户在该分类下的兴趣权重累加一次借阅频次。加载完成后,所有用户借阅数据驻留在内存中,后续推荐计算不再访问数据库,以保证响应速度。
关联规则在初始化阶段同步构建。遍历user_borrows中的每位用户,对其借阅列表中的每本图书统计单本出现次数,并对列表内任意两本不同图书组成的图书对累计共现次数。完成遍历后,对所有共现次数不低于2的图书对计算置信度。置信度公式如式(4.3)所示,高于阈值0.1的规则被保留在association_rules字典中,键为(前件图书ID, 后件图书ID)元组,值为置信度。
系统的实体关系如图4.3所示,图中标注了各实体的主键以及实体间的外键关联方向。
4 . 4 . 2 协同过滤推荐
协同过滤采用基于用户的Jaccard相似度方法。设目标用户u的借阅图书集合为Bᵤ,遍历系统中其他所有用户v,计算两个集合的交集大小与并集大小的比值。当并集非零且相似度大于零时,将该用户及其相似度记录到相似列表中。相似度计算如式(4.1)所示。随后按相似度降序排列,截取前20名作为相似用户集合SN。
在生成推荐时,对SN中每位相似用户v,获取其借阅列表中属于目标用户未借过的图书,将v与目标用户的相似度累加到该图书的得分上。最终按得分降序返回前N本图书,作为协同过滤的推荐序列。算法流程如图4.4所示。
4 . 4 . 3 关联规则推荐
关联规则推荐利用初始化阶段构建的association_rules字典。输入目标用户u,首先获取其借阅图书集合Bᵤ。为每一本属于Bᵤ的图书,在关联规则字典中查找以该图书为前件的所有规则。对每条规则,若后件图书不在Bᵤ中,则将该后件的累计得分加上规则对应的置信度。最终将所有后件图书按得分降序排列,截取前N本作为关联规则推荐结果。
4 . 4 . 4 分类偏好推荐
分类偏好推荐基于用户在各类别下的兴趣权重。从category_scores中取出目标用户u对应的分类得分字典,按得分降序取前三个分类ID。通过数据库查询在这三个分类中按图书借阅次数降序排列,返回前N本图书。对于无历史数据的用户,该模块直接调用热门推荐逻辑。
为反映兴趣的时效性,用户每次还书后将触发偏好更新操作。更新函数重新读取该用户所有已归还的借阅记录,对每本图书按借阅日期距今的天数计算时间衰减权重,权重计算公式如式(4.5)所示。各分类下的衰减权重累加后更新至user_preferences表,存在旧记录时保留较高分值。半衰期参数设为30天,确保近期借阅行为对分类偏好影响更大。
4 . 4 . 5 混合推荐与冷启动策略
混合推荐函数汇总上述各算法的输出。设目标用户为u,若u存在借阅历史(即user_borrows中包含该用户键且列表非空),则分别调用协同过滤、关联规则和分类偏好三路算法,各取推荐数量为N的两倍,并将各路的图书得分分别乘以权重0.4、0.3、0.2后累加至统一得分字典。随后,调用热门推荐获得全局借阅次数最高的N本图书,将其得分乘以权重0.1后同样并入得分字典。对所有候选图书的最终得分按降序排序,截取前N本即为混合推荐结果。综合评分计算如式(4.4)所示。
若目标用户无借阅历史(冷启动用户),则协同过滤、关联规则和分类偏好三路均无法生成有效推荐,此时最终得分仅由热门推荐一项组成。系统通过此设计自动完成冷启动策略切换,不需要额外的分支逻辑。当用户逐步积累借阅数据后,三路算法陆续生效,推荐由纯热门平滑过渡至个性化混合推荐。混合推荐的整体流程如图4.5所示。
通过以上设计,推荐引擎在数据稀疏和冷启动场景下均可稳定输出结果,混合加权机制兼顾了推荐的准确性与多样性。
5 . 系统开发与实现
5.1 开发环境
本系统采用B/S结构体系,基于Python语言的Flask框架开发,数据库选用SQLite嵌入式关系型数据库,前端采用Bootstrap框架和ECharts可视化库构建响应式用户界面。系统开发环境如表5.1所示。
表5.1 系统开发环境
|----------------------------------|------------------------------|
| 硬件环境 | 软件环境 |
| CPU:Intel Core i7-12700H 2.30GHz | 操作系统:Windows 11 专业版 22H2 |
| 内存:16GB DDR4 | 数据库:SQLite 3.39.0 |
| 硬盘:512GB SSD | 开发语言:Python 3.10.8 |
| | Web框架:Flask 2.3.2 |
| | ORM工具:Flask-SQLAlchemy 3.0.5 |
| | 前端框架:Bootstrap 5.3.2 |
| | 可视化库:ECharts 5.4.3 |
| | 浏览器:Google Chrome 118.0 |
| | 开发工具:Visual Studio Code 1.82 |
5.2 功能模块实现
5 . 2 . 1 图书浏览与检索功能实现
图书浏览与检索是读者访问系统的第一入口,承担着馆藏展示和多条件筛选的核心任务。前端页面采用Bootstrap栅格布局构建响应式图书卡片网格,每张卡片包含图书封面占位区域、分类标签、书名和作者信息。页面左侧设置筛选侧边栏,包含搜索输入框、分类下拉选择器和排序条件选择器三个控件,所有控件通过GET表单提交将筛选参数拼接在URL查询字符串中,便于用户通过浏览器前进后退按钮切换浏览状态。


图5.1 图书浏览与检索功能图
后端视图函数books()从request.args中获取page、search、category和sort四个参数。函数首先构建针对Book模型的SQLAlchemy查询对象,当search参数非空时,在Book.name、Book.author和Book.isbn三个字段上叠加contains模糊匹配条件,实现书名、作者和ISBN的联合搜索。当category参数非空时,通过filter_by(cate_name=category)精确匹配分类名称,利用cate_name字段的冗余存储避免了多表连接查询。排序逻辑根据sort参数值分别应用按借阅次数降序、按创建时间降序或按书名字母序排列,默认按主键id升序以保证翻页稳定性。查询对象构建完成后调用paginate方法完成分页,每页固定返回12条记录。视图函数将分页对象、当前筛选条件和全部图书分类列表一并传入模板渲染。模板引擎通过双层循环逐卡片输出图书信息,分页导航采用Jinja2迭代器遍历页码范围,当前页码高亮显示且翻页链接自动携带所有筛选参数。
5 . 2 . 2 图书详情与相似推荐功能实现
图书详情页面承载着单本图书的完整信息和关联推荐的双重职责。前端分为左右两栏,主栏依次展示封面、分类标签、书名、作者、ISBN、定价、页数等元数据,以及馆藏数量、可借数量和平均评分的统计卡片。侧栏分为相似图书推荐和借阅后还读推荐两个区域。

图5.2 图书详情与相似推荐功能图
后端book_detail()函数接收图书ID作为路径参数,调用Book.query.get_or_404获取图书对象。获取相似图书时,函数调用推荐引擎的get_similar_books方法,该方法遍历user_borrows字典,找出借阅过当前图书的所有用户,再统计这些用户借阅过的其他图书的出现次数,按频次降序返回前6本。若推荐引擎尚未初始化或返回结果为空,则退化为同分类下按借阅次数降序选取的6本图书。借阅后还读推荐通过另一条查询路径实现:先从borrow_records表中筛选借阅过当前图书且状态为"已归还"的用户ID列表,再查询这些用户借阅过的其他图书ID并按出现次数降序聚合,取前6本。两类推荐分别传入模板在侧栏渲染为列表链接。平均评分通过对book_ratings表中对应的评分字段求平均值获得,保留一位小数显示。
5 . 2 . 3 个性化推荐功能实现
个性化推荐是系统的核心功能模块。前端推荐页面顶部设置算法权重说明卡片,以四种不同颜色的Badge展示协同过滤、关联规则、分类偏好和热门推荐的比例。推荐图书以卡片网格形式展示,每张卡片结构与图书列表保持一致,用户可点击查看详情或借阅。

图5.3 个性化推荐功能图
后端recommendations()视图函数首先获取当前用户的ID和请求页码。在调用推荐引擎前,检查recommender对象中user_borrows字典是否已包含有效数据,若为空则先调用init_recommender()函数从数据库重新加载借阅记录并构建关联规则。推荐引擎的hybrid_recommend方法接收用户ID和固定参数50(取50本以支持前端分页),该方法内部首先检查用户是否存在于user_borrows字典中且列表非空。若用户有借阅记录,则并行执行三路推荐:协同过滤通过Jaccard相似度计算找到最相似的20名用户,以相似度为权重累加未读图书得分;关联规则遍历用户已借图书寻找匹配的规则前件,将规则后件的置信度累加至候选图书;分类偏好取用户权重最高的三个分类下借阅次数最多的图书。三路得分分别乘以0.4、0.3、0.2后与热门推荐的0.1倍得分求和,按总得分降序截取前N本返回图书ID列表。后端根据返回的ID列表从数据库批量查询完整图书对象,按页数和每页数量切片后传入模板渲染。若推荐引擎调用异常,视图函数捕获异常后直接降级为按借阅次数降序返回热门图书。
5 . 2 . 4 借阅管理功能实现
借阅管理模块覆盖借书、还书和借阅记录查看三项操作。借书功能由borrow_book视图函数处理,前端在图书详情页和推荐卡片上均设置借阅按钮,通过POST表单提交防止浏览器预加载触发重复借阅。后端首先校验图书可借数量是否大于零,再检查当前用户是否已有该书的未归还借阅记录,两项校验通过后创建BorrowRecord对象,borrow_date设为当前时间,due_date设为30天后的日期,status设为"borrowed"。图书的available_copies字段减一,borrow_count字段加一,两处更新在同一事务中提交以保证库存一致性。借阅成功后调用推荐引擎的update_user_preference方法更新用户分类偏好。

图5.4 借阅管理效果图
还书功能由return_book视图函数处理。前端在"我的借阅"页面的借阅中记录行提供还书按钮,点击后弹出模态框,内置五星评分交互组件和评论文本域。五星组件通过CSS监听鼠标悬停事件实时高亮,点击后将分值写入隐藏输入框。后端校验当前用户与借阅记录用户的身份一致性后,更新记录的return_date为当前时间、status为"returned",同时将评分和评论写入对应字段。图书的available_copies字段加一。借阅记录查看页面支持按全部、借阅中、已归还和逾期四种状态筛选,筛选条件通过URL查询参数传递,后端按状态过滤并分页返回。
5 . 2 . 5 管理后台功能实现
管理后台面向管理员提供数据概览和运营管理两项核心功能。dashboard视图函数首先聚合四项基本统计指标:普通用户总数、图书总数、借阅记录总数和当前借阅数量,通过SQLAlchemy的count查询逐项获取。借阅趋势数据通过遍历近30天日期,对每天进行BorrowRecord日期字段的条件聚合查询,生成日期字符串到计数的映射字典。图书分类分布则遍历所有Category记录,对每个分类统计Book表中cate_id等于该分类ID的记录数,过滤计数为零的分类后传入模板。

图5.5 数据概览图
前端dashboard模板使用ECharts库绘制两张可视化图表。借阅趋势折线图配置tooltip悬浮提示和smooth平滑曲线样式,X轴绑定30天日期数组,Y轴绑定对应借阅量数组,系列区域填充半透明蓝色渐变。分类分布饼图配置roseType为area模式,数据数组由后端传入的分类名和图书计数构成。页面顶部以四个彩色图标统计卡片并排展示核心指标,底部左右分栏分别放置热门图书TOP10表格和活跃用户排行榜,表格数据由视图函数以Book按借阅次数降序和BorrowRecord按用户分组计数降序查询获得。
用户管理页面提供搜索和角色筛选两个查询条件,支持按用户名、邮箱或学号模糊搜索。toggle_user_status视图函数接收用户ID,读取当前用户的is_active值后取反并提交更新。change_user_role视图函数从表单获取新角色值,校验其在合法角色列表中后更新用户记录。两个操作函数均通过POST方法接收参数,操作完成后重定向回用户列表页并显示flash提示信息。推荐系统统计页面调用recommender.evaluate_recommendations方法对采样用户逐一评估,计算每位用户的准确率、召回率和F1分数,汇总后计算各项指标的全量算术平均值,连同算法权重配置一并渲染至统计页面。

图5.6 用户管理图

图5.7 图书管理图

图5.8 推荐数据统计图