ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Python Flask构建图书数据分析可视化系统:从爬虫到智能Agent的完整实践

Python Flask构建图书数据分析可视化系统:从爬虫到智能Agent的完整实践 如果你是一名计算机专业的学生正在为毕业设计选题而焦虑或者是一名刚入行的开发者想找一个能串联起Python、Web开发、数据分析和可视化等多个热门技能的综合项目来练手那么这篇文章就是为你准备的。“图书数据分析可视化系统”听起来像是一个典型的课程设计题目但很多人会把它做成一个简单的“数据库增删改查几个静态图表”的作业。这其实浪费了这个选题真正的价值。一个真正有竞争力的毕业设计或项目作品其核心不在于功能有多全而在于你是否清晰地展示了从数据获取到价值呈现的完整技术链条以及你是否能讲清楚每个技术选型背后的“为什么”。本文将带你拆解一个基于Python Flask框架的图书数据分析可视化系统。我们不会止步于功能的罗列而是会深入探讨为什么用Flask而不是Django爬虫数据如何合规清洗可视化图表如何选择才能有效传达信息以及如何引入“智能体Agent”思想让系统从“展示数据”升级为“推荐洞察”通过这个项目你不仅能完成一个高完成度的作品更能掌握一套解决实际数据问题的工程化思维。1. 这个项目真正要解决什么问题一个图书数据分析系统表面上是管理书籍、生成图表。但作为开发者我们需要看到更深层的需求。这个项目本质上是在解决三个核心问题数据从哪来手动录入几百上千本书籍信息是不现实的。我们需要从互联网如豆瓣读书、京东图书自动、持续、合规地获取数据。这就是“爬虫”部分要解决的数据源问题。数据如何变“活”原始数据书名、作者、评分、评论数是孤立的。我们需要通过分析如评分分布、作者产量趋势、题材关联和挖掘如基于用户行为的协同过滤推荐将数据转化为洞察。这是“数据分析与挖掘”部分的价值。洞察如何有效传达分析结果如果只是一堆数字或冗长的报告价值大打折扣。通过Web界面进行交互式可视化图表、地图、仪表盘让任何业务人员都能快速理解这是“Flask可视化系统”承担的呈现层任务。而“Agent”智能体的引入则是为了提升系统的智能化和自动化水平。例如一个“监控Agent”可以定时运行爬虫任务更新数据一个“分析Agent”可以在数据更新后自动运行预定义的分析脚本更新图表一个“推荐Agent”可以根据用户的浏览历史实时计算并推送可能感兴趣的书籍。这使系统从一个静态的“数据看板”进化成一个动态的“数据决策辅助系统”。对于毕业生或求职者来说完成这样一个项目并向面试官清晰地阐述上述设计思路远比罗列一堆技术名词更有说服力。2. 技术栈选型与核心概念解读为什么是Python Flask ECharts ...每一个选择都有其考量。Python: 几乎是数据科学领域的“普通话”。在爬虫Requests, Scrapy、数据分析Pandas, NumPy、数据挖掘Scikit-learn和可视化Matplotlib, Pyecharts方面都有极其成熟和统一的生态库学习成本和开发效率最优。Flask (vs Django): 对于这个项目Flask是更合适的选择。Django是“大而全”的框架自带ORM、Admin后台等但略显笨重。Flask是“微框架”轻量、灵活。我们的系统核心是数据分析和可视化Web部分主要是提供API和渲染模板业务逻辑并不复杂。Flask允许我们“按需装配”比如用Flask-SQLAlchemy处理数据库用Flask-Login处理用户认证结构更清晰也更适合初学者理解Web请求的完整生命周期。爬虫库 (Requests BeautifulSoup4 / Scrapy):Requests: 用于发送HTTP请求获取网页内容。简单易用适合中小规模、页面结构不复杂的爬取任务。BeautifulSoup4 (bs4): 用于解析HTML/XML文档从网页中提取结构化数据如书名、评分。Scrapy: 工业级爬虫框架。如果需要爬取大量数据、处理反爬机制、设计复杂的抓取流程Scrapy是更好的选择。对于毕业设计从Requestsbs4入手更简单。数据分析与处理 (Pandas NumPy):Pandas的DataFrame是处理表格数据的核心数据结构能轻松完成数据清洗、转换、聚合和统计分析。NumPy提供高效的数值计算基础。数据挖掘 (Scikit-learn): 用于实现简单的推荐算法。例如可以使用基于物品的协同过滤算法通过计算书籍之间的相似度来实现“看了这本书的人 also viewed...”的功能。可视化 (Pyecharts / Plotly): 这是前端图表库的Python封装。Pyecharts: 封装了百度开源的ECharts图表类型丰富交互性强与Flask集成方便生成的图表美观。Plotly: 另一个强大的交互式可视化库图表同样精美并且支持Dash框架构建更复杂的分析应用。数据库 (SQLite / MySQL): 初期开发或轻量级应用可以用SQLite零配置。考虑到毕业设计的完整性和演示性使用MySQL更显专业。通过PyMySQL或SQLAlchemy进行连接。“Agent”概念: 在此项目中它不是一个复杂的AI模型而是一种自动化任务的设计模式。你可以将其理解为一个个后台的“机器人程序”或“定时任务脚本”。例如使用Python的APScheduler库可以轻松创建定时爬虫Agent、定时分析Agent。3. 系统架构设计与模块划分在动手写代码前清晰的架构能避免后期混乱。我们采用典型的分层架构图书数据分析可视化系统 ├── 数据层 (Data Layer) │ ├── 爬虫模块 (Crawler) - 从目标网站抓取原始数据 │ ├── 数据清洗模块 (Data Cleaning) - 清洗、去重、格式化原始数据 │ └── 数据库模块 (Database) - 使用SQLAlchemy ORM管理MySQL存储清洗后的数据 ├── 业务逻辑层 (Business Logic Layer) │ ├── 分析引擎 (Analysis Engine) - 使用Pandas进行统计分析平均分、趋势等 │ ├── 挖掘引擎 (Mining Engine) - 使用Scikit-learn实现推荐算法 │ └── 智能体管理器 (Agent Manager) - 调度和管理各类后台Agent定时任务 ├── 表现层 (Presentation Layer) │ ├── Web后端 (Flask App) - 提供RESTful API处理业务逻辑 │ ├── 前端模板 (Jinja2 Templates) - 渲染HTML页面 │ └── 可视化组件 (ECharts) - 通过Pyecharts生成图表并嵌入页面 └── 支撑层 (Supporting Layer) ├── 配置管理 (Configuration) ├── 日志记录 (Logging) └── 错误处理 (Error Handling)4. 环境准备与项目初始化操作系统: Windows 10/11, macOS 或 Linux (Ubuntu) 均可。Python版本: 建议使用 Python 3.8 或以上版本。第一步创建项目目录并初始化虚拟环境强烈推荐用于隔离依赖。# 创建项目文件夹 mkdir book_analysis_system cd book_analysis_system # 创建虚拟环境 (以venv为例) python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS/Linux: source venv/bin/activate激活后命令行提示符前会出现(venv)标识。接下来创建requirements.txt文件来管理依赖。# requirements.txt Flask2.3.3 Flask-SQLAlchemy3.0.5 Flask-Login0.6.2 PyMySQL1.0.3 requests2.31.0 beautifulsoup44.12.2 pandas2.0.3 numpy1.24.3 scikit-learn1.3.0 pyecharts2.0.3 APScheduler3.10.4 python-dotenv1.0.0使用pip安装所有依赖(venv) pip install -r requirements.txt5. 核心模块实现详解5.1 数据库模型设计 (models.py)我们设计几个核心表来存储数据。# app/models.py from flask_sqlalchemy import SQLAlchemy from datetime import datetime db SQLAlchemy() class Book(db.Model): 书籍信息表 __tablename__ books id db.Column(db.Integer, primary_keyTrue) title db.Column(db.String(200), nullableFalse, indexTrue) author db.Column(db.String(100)) publisher db.Column(db.String(100)) publish_date db.Column(db.String(50)) price db.Column(db.Float) rating db.Column(db.Float) # 评分如9.0 rating_count db.Column(db.Integer) # 评分人数 summary db.Column(db.Text) tags db.Column(db.String(300)) # 标签用逗号分隔如“小说,编程,经典” source_url db.Column(db.String(500)) created_at db.Column(db.DateTime, defaultdatetime.utcnow) def __repr__(self): return fBook {self.title} class UserBehavior(db.Model): 用户行为表用于推荐算法 __tablename__ user_behaviors id db.Column(db.Integer, primary_keyTrue) # 为简化这里用user_id代替真实用户系统。实际项目可关联User表。 user_id db.Column(db.Integer, indexTrue) book_id db.Column(db.Integer, db.ForeignKey(books.id), indexTrue) behavior_type db.Column(db.String(20)) # 行为类型view, like, collect, purchase created_at db.Column(db.DateTime, defaultdatetime.utcnow) class AnalysisResult(db.Model): 分析结果缓存表供Agent更新 __tablename__ analysis_results id db.Column(db.Integer, primary_keyTrue) result_type db.Column(db.String(50), indexTrue) # 如 ‘rating_distribution‘, ’top_authors‘ result_data db.Column(db.JSON) # 存储JSON格式的分析结果 updated_at db.Column(db.DateTime, defaultdatetime.utcnow, onupdatedatetime.utcnow)5.2 爬虫模块实现 (crawler/douban_crawler.py)以爬取豆瓣读书某个标签下的书籍列表为例。请注意务必遵守网站的robots.txt协议控制请求频率避免对目标网站造成压力。本示例仅用于学习。# crawler/douban_crawler.py import requests from bs4 import BeautifulSoup import time import random from app.models import db, Book from app import create_app def crawl_douban_books(tag编程, start0): 爬取豆瓣读书标签下的书籍 :param tag: 标签名 :param start: 起始位置用于分页 base_url fhttps://book.douban.com/tag/{tag}?start{start}typeT headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 } try: resp requests.get(base_url, headersheaders, timeout10) resp.raise_for_status() # 检查请求是否成功 resp.encoding utf-8 except requests.RequestException as e: print(f请求失败: {e}) return [] soup BeautifulSoup(resp.text, html.parser) book_items soup.find_all(li, class_subject-item) books_data [] for item in book_items: try: title_elem item.find(h2).find(a) title title_elem.get(title, ).strip() detail_url title_elem.get(href, ) # 提取出版信息、作者、价格等豆瓣页面结构可能变化此处为示例 pub_info item.find(div, class_pub) pub_text pub_info.get_text(stripTrue).split(/) if pub_info else [] author pub_text[0] if len(pub_text) 0 else publisher pub_text[-3] if len(pub_text) 2 else publish_date pub_text[-2] if len(pub_text) 1 else price pub_text[-1] if len(pub_text) 0 else # 提取评分 rating_elem item.find(span, class_rating_nums) rating float(rating_elem.get_text(stripTrue)) if rating_elem else 0.0 # 提取评价人数 rating_count_elem item.find(span, class_pl) rating_count_text rating_count_elem.get_text(stripTrue) if rating_count_elem else rating_count int(rating_count_text[1:-4]) if rating_count_text and 人评价 in rating_count_text else 0 book_data { title: title, author: author, publisher: publisher, publish_date: publish_date, price: price, rating: rating, rating_count: rating_count, source_url: detail_url, tags: tag } books_data.append(book_data) except Exception as e: print(f解析书籍信息时出错: {e}) continue # 礼貌性延迟避免请求过快 time.sleep(random.uniform(1, 3)) return books_data def save_books_to_db(books_data): 将爬取的数据存入数据库 app create_app() with app.app_context(): for data in books_data: # 检查书籍是否已存在根据标题和作者 existing_book Book.query.filter_by(titledata[title], authordata[author]).first() if not existing_book: new_book Book(**data) db.session.add(new_book) try: db.session.commit() print(f成功保存 {len(books_data)} 条书籍数据。) except Exception as e: db.session.rollback() print(f保存数据时出错: {e}) if __name__ __main__: # 示例爬取‘编程’标签下前20本书第一页 data crawl_douban_books(tag编程, start0) save_books_to_db(data)5.3 Flask应用与路由 (app/init.py, app/routes.py)创建Flask应用工厂并定义核心路由。# app/__init__.py from flask import Flask from config import Config from app.models import db def create_app(config_classConfig): app Flask(__name__) app.config.from_object(config_class) db.init_app(app) # 注册蓝图 from app.routes import main_bp app.register_blueprint(main_bp) # 创建数据库表首次运行 with app.app_context(): db.create_all() return app# config.py import os basedir os.path.abspath(os.path.dirname(__file__)) class Config: SECRET_KEY os.environ.get(SECRET_KEY) or you-will-never-guess SQLALCHEMY_DATABASE_URI os.environ.get(DATABASE_URL) or \ mysqlpymysql://username:passwordlocalhost/book_analysis_db SQLALCHEMY_TRACK_MODIFICATIONS False# app/routes.py from flask import Blueprint, render_template, jsonify, request from app.models import Book, AnalysisResult from app import db import pandas as pd from sqlalchemy import func main_bp Blueprint(main, __name__) main_bp.route(/) def index(): 首页展示仪表盘 return render_template(index.html) main_bp.route(/api/books) def get_books(): 获取书籍列表API支持分页和搜索 page request.args.get(page, 1, typeint) per_page request.args.get(per_page, 20, typeint) search request.args.get(search, ) query Book.query if search: query query.filter(Book.title.contains(search) | Book.author.contains(search)) pagination query.order_by(Book.rating.desc()).paginate(pagepage, per_pageper_page, error_outFalse) books pagination.items return jsonify({ books: [{id: b.id, title: b.title, author: b.author, rating: b.rating} for b in books], total: pagination.total, pages: pagination.pages, current_page: page }) main_bp.route(/api/analysis/rating_distribution) def rating_distribution(): 评分分布分析API # 先从缓存表查询 cached_result AnalysisResult.query.filter_by(result_typerating_distribution).first() if cached_result: return jsonify(cached_result.result_data) # 若缓存不存在则实时计算 # 使用Pandas直接读取SQL对于大量数据更高效 import pandas as pd df pd.read_sql(Book.query.statement, db.session.bind) # 计算评分分布 rating_bins [0, 6, 7, 8, 9, 10] rating_labels [6分以下, 6-7分, 7-8分, 8-9分, 9-10分] df[rating_group] pd.cut(df[rating], binsrating_bins, labelsrating_labels, rightFalse) distribution df[rating_group].value_counts().sort_index().to_dict() result { labels: list(distribution.keys()), values: list(distribution.values()) } # 存入缓存 new_cache AnalysisResult(result_typerating_distribution, result_dataresult) db.session.add(new_cache) db.session.commit() return jsonify(result) main_bp.route(/api/analysis/top_authors) def top_authors(): 高产作者Top10分析API cached_result AnalysisResult.query.filter_by(result_typetop_authors).first() if cached_result: return jsonify(cached_result.result_data) # 使用SQLAlchemy进行分组统计 from sqlalchemy import func top_authors_data db.session.query( Book.author, func.count(Book.id).label(book_count), func.avg(Book.rating).label(avg_rating) ).filter(Book.author ! ).group_by(Book.author).order_by(func.count(Book.id).desc()).limit(10).all() result { authors: [item[0] for item in top_authors_data], book_counts: [item[1] for item in top_authors_data], avg_ratings: [float(item[2]) if item[2] else 0 for item in top_authors_data] } new_cache AnalysisResult(result_typetop_authors, result_dataresult) db.session.add(new_cache) db.session.commit() return jsonify(result)5.4 可视化前端集成 (templates/index.html)使用Pyecharts生成图表并通过Flask渲染到页面。首先创建一个生成图表的工具函数。# app/charts.py from pyecharts import options as opts from pyecharts.charts import Bar, Pie, Line from pyecharts.globals import ThemeType def create_rating_distribution_bar(data): 创建评分分布柱状图 labels data.get(labels, []) values data.get(values, []) bar ( Bar(init_optsopts.InitOpts(themeThemeType.LIGHT)) .add_xaxis(labels) .add_yaxis(书籍数量, values) .set_global_opts( title_optsopts.TitleOpts(title书籍评分分布), xaxis_optsopts.AxisOpts(name评分区间), yaxis_optsopts.AxisOpts(name数量), ) ) return bar.render_embed() # 返回嵌入页面的HTML片段 def create_top_authors_line(data): 创建高产作者折线图展示作品数量与平均评分 authors data.get(authors, []) book_counts data.get(book_counts, []) avg_ratings data.get(avg_ratings, []) line ( Line(init_optsopts.InitOpts(themeThemeType.LIGHT)) .add_xaxis(authors) .add_yaxis(作品数量, book_counts, yaxis_index0, label_optsopts.LabelOpts(is_showFalse)) .add_yaxis(平均评分, avg_ratings, yaxis_index1, label_optsopts.LabelOpts(is_showFalse)) .extend_axis(yaxisopts.AxisOpts(name平均评分, typevalue, min_0, max_10)) .set_global_opts( title_optsopts.TitleOpts(title高产作者Top10 (作品数 vs 平均评分)), xaxis_optsopts.AxisOpts(name作者, axislabel_optsopts.LabelOpts(rotate-45)), yaxis_optsopts.AxisOpts(name作品数量), tooltip_optsopts.TooltipOpts(triggeraxis, axis_pointer_typecross), ) ) return line.render_embed()然后在路由中调用并传递到模板。# 在 routes.py 中修改或添加 from app.charts import create_rating_distribution_bar, create_top_authors_line main_bp.route(/dashboard) def dashboard(): 可视化仪表盘页面 # 获取数据 rating_data rating_distribution().get_json() # 注意这里直接调用函数实际应从API或缓存取 top_authors_data top_authors().get_json() # 生成图表HTML rating_chart_html create_rating_distribution_bar(rating_data) authors_chart_html create_top_authors_line(top_authors_data) return render_template(dashboard.html, rating_chart_htmlrating_chart_html, authors_chart_htmlauthors_chart_html)对应的HTML模板!-- templates/dashboard.html -- !DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title图书数据分析仪表盘/title script srchttps://cdn.jsdelivr.net/npm/echarts5.4.3/dist/echarts.min.js/script style .chart-container { width: 100%; height: 500px; margin-bottom: 30px; border: 1px solid #eee; border-radius: 8px; padding: 20px; } /style /head body h1图书数据分析可视化系统/h1 div classchart-container {{ rating_chart_html|safe }} /div div classchart-container {{ authors_chart_html|safe }} /div /body /html5.5 智能体Agent实现示例实现一个定时爬虫Agent每天凌晨自动更新数据。# agent/scheduler_agent.py from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.cron import CronTrigger from crawler.douban_crawler import crawl_douban_books, save_books_to_db from app import create_app import logging logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) def scheduled_crawl_job(): 定时爬虫任务 logger.info(开始执行定时爬虫任务...) app create_app() with app.app_context(): try: # 爬取多个标签 tags [编程, 机器学习, 小说, 历史] for tag in tags: books_data crawl_douban_books(tagtag, start0) if books_data: save_books_to_db(books_data) logger.info(f标签 {tag} 爬取完成获取 {len(books_data)} 条数据。) else: logger.warning(f标签 {tag} 未爬取到数据。) except Exception as e: logger.error(f定时爬虫任务执行失败: {e}) logger.info(定时爬虫任务执行完毕。) def start_scheduler(): 启动调度器 scheduler BackgroundScheduler() # 每天凌晨2点执行一次 trigger CronTrigger(hour2, minute0) scheduler.add_job(scheduled_crawl_job, trigger, iddaily_crawl) scheduler.start() logger.info(APScheduler 定时任务已启动。) return scheduler if __name__ __main__: # 直接运行此文件会立即执行一次任务然后启动调度器保持运行 scheduled_crawl_job() scheduler start_scheduler() try: # 保持主线程运行 while True: pass except (KeyboardInterrupt, SystemExit): scheduler.shutdown() logger.info(调度器已关闭。)6. 系统运行与效果验证启动数据库: 确保MySQL服务已启动并创建好book_analysis_db数据库。配置环境变量: 在项目根目录创建.env文件设置数据库连接和密钥。# .env SECRET_KEYyour-secret-key-here DATABASE_URLmysqlpymysql://your_username:your_passwordlocalhost/book_analysis_db初始化应用:(venv) export FLASK_APPapp:create_app # Linux/macOS # 或 (venv) set FLASK_APPapp:create_app # Windows (venv) flask run --host0.0.0.0 --port5000访问系统: 打开浏览器访问http://127.0.0.1:5000/dashboard即可看到可视化图表。手动触发爬虫:(venv) python crawler/douban_crawler.py启动定时Agent(在另一个终端):(venv) python agent/scheduler_agent.py预期效果:Web页面正常显示无错误。图表能正确展示数据初始为空运行爬虫后会有数据。爬虫脚本运行后数据库books表中应有数据插入。定时Agent启动后会在控制台看到日志输出并在设定时间自动执行任务。7. 常见问题与排查思路问题现象可能原因排查方式解决方案ModuleNotFoundError: No module named flask虚拟环境未激活或依赖未安装检查命令行前缀是否有(venv)执行pip list查看激活虚拟环境运行pip install -r requirements.txtsqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1045, ...)数据库连接失败密码错误、用户无权限、数据库不存在检查.env文件中的DATABASE_URL确认MySQL服务状态用命令行尝试连接修正连接字符串创建数据库授予用户权限爬虫脚本运行无错误但数据库无数据1. 网页结构已变化解析失败。2. 数据去重逻辑导致未插入。3. 请求被目标网站屏蔽。1. 打印books_data看是否解析到数据。2. 检查save_books_to_db函数中的去重逻辑。3. 检查请求头User-Agent添加延时。1. 更新BeautifulSoup解析逻辑。2. 调整或暂时注释去重逻辑进行测试。3. 模拟更真实的浏览器行为使用代理IP池高级。图表页面空白或JS错误1. ECharts JS库未加载。2. Pyecharts生成的HTML片段有误。3. 传递给模板的数据为空。1. 浏览器F12查看Console网络和错误。2. 查看网页源代码检查图表div内是否有JS代码。3. 在路由中打印rating_data等数据。1. 确保网络可访问CDN或本地引入ECharts。2. 检查charts.py中图表生成逻辑。3. 确保数据库有数据且API能正确返回。定时任务不执行1. 调度器未成功启动。2. 任务函数内部有未捕获的异常。3. 服务器时间不正确。1. 查看启动日志。2. 在任务函数内增加更详细的try...except和日志。3. 检查服务器系统时间。1. 确保start_scheduler()被调用。2. 完善错误处理确保异常不影响调度器。3. 同步服务器时间。对于长时间运行考虑使用systemd或supervisor托管。8. 项目扩展与最佳实践一个基础的毕业设计到此已完成。但要让它脱颖而出可以考虑以下扩展方向和实践建议用户系统与个性化推荐:实现完整的用户注册、登录使用Flask-Login。记录用户的浏览、评分、收藏行为丰富UserBehavior表。实现更复杂的推荐算法如基于用户的协同过滤、基于内容的推荐或使用Surprise库。提供“猜你喜欢”模块。数据可视化增强:使用ECharts的地图组件展示不同地区作者的分布。实现时间趋势图展示每年出版书籍的数量和平均评分变化。添加词云图展示书籍标签的热度。实现图表联动和下钻Drill-down分析。系统优化与工程化:缓存: 对分析结果API使用Flask-Caching或Redis进行缓存大幅提高响应速度。异步任务: 将耗时的爬虫和分析任务放入消息队列如CeleryRedis避免阻塞Web请求。容器化: 使用Docker和Docker Compose封装应用、MySQL、Redis实现一键部署。日志与监控: 配置完整的日志系统并监控关键指标如爬虫成功率、API响应时间。合规与伦理:遵守robots.txt: 爬虫前务必检查目标网站的robots.txt文件。设置友好延时: 在爬虫请求间添加随机延时如time.sleep(random.uniform(2, 5))。限制爬取速度: 避免短时间内发起大量请求。尊重版权: 展示数据时注明来源。对于商业用途需获得授权。代码质量:配置文件分离: 将开发、测试、生产环境的配置分离。错误处理: 对所有可能失败的操作网络请求、数据库操作进行完善的异常捕获和日志记录。代码复用: 将爬虫、分析等逻辑封装成独立的类或函数提高可测试性。通过这个项目你不仅学会了Flask、爬虫、数据分析和可视化的技术拼接更重要的是掌握了如何将一个业务需求分析图书数据分解为技术模块并设计出一个可运行、可扩展的系统架构。在面试或答辩时你可以清晰地讲述数据流从爬虫到数据库再到分析和前端展示、技术选型的理由、遇到的挑战及解决方案这才是这个毕业设计最大的价值。
返回列表