毕业设计实战:Python房价预测Web系统全栈实现
简介本资源是一套面向高校计算机与信息类专业学生的Python毕业设计项目聚焦房屋信息可视化与房价预测场景适用于课程设计、毕设开题与实战能力提升。系统基于Python 3.6.8开发集成MySQL 5.7数据库涵盖用户注册登录、首页展示、房价数据爬取支持安居客、58同城等平台、多维度分析及房屋预测数据管理等完整模块技术栈覆盖Web前端Bootstrap、Layui、jQuery、后端逻辑Flask/Django风格Py文件与数据处理CSV、SQL脚本。压缩包共310个文件含46个核心Python源码、17个HTML页面、43个JS交互脚本、17个CSS样式文件及75个GIF动效资源整体17.74MB结构清晰、模块解耦明确便于理解MVC分层与前后端协同逻辑。目前已有41人学习下载附带完整可运行源码、数据库建表SQL、Navicat连接配置说明及部分UI资源适合夯实Python Web开发、数据爬虫与可视化综合能力。1. 这不是又一个“房价预测 demo”它是一套能跑通从爬虫、MySQL 存储、Flask 后端、Layui 前端到可视化分析的完整毕业设计闭环系统你肯定见过太多标着“Python 房价预测”的 GitHub 项目——三行 pandas 读 CSV一行 sklearn.fit()再画个折线图就叫“系统”。但这次不一样。这个源码包里塞进的是真实可部署、带用户体系、有数据采集链路、含前后端分离逻辑、且所有模块都经过 PyCharm MySQL 5.7 Navicat 11 实测验证的毕业设计实体。它不只预测价格更解决了一个关键问题如何让非计算机专业比如土木、工程管理、房地产方向的学生在两周内搭起一个“看起来像真系统”的 Web 应用并能向答辩老师清晰讲出每一层在干什么。核心能力包括基于 Selenium requests 的安居客/58 同城双源动态反爬适配、MySQL 中房屋字段的标准化建模含楼层、朝向、装修、地铁距离等 17 个业务字段、Layui Bootstrap 混合前端的响应式管理页、以及用 Matplotlib ECharts 实现的“区域均价热力图户型价格箱线图时间趋势滑动预测”三维可视化。如果你正卡在毕设开题后“不知道代码怎么组织”、或导师说“太单薄要体现工程性”那它就是你缺的那块拼图。2. 环境复现与数据库初始化3.6.8 是硬门槛Navicat 导入比命令行更稳这套系统对 Python 版本有明确依赖不是“3.6”就能蒙混过关。3.6.8 是作者实测唯一能稳定加载所有依赖尤其是pyecharts0.5.11和selenium3.141.0的版本。低于此版本会触发ImportError: cannot import name Mapping高于则因urllib3和requests的兼容链断裂导致爬虫模块直接静默失败。MySQL 5.7 同样不可替换——表结构中大量使用datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP语法MySQL 8.0 的严格模式会报错而 MariaDB 则因FULLTEXT索引实现差异使搜索功能返回空结果。2.1 Python 环境搭建用 conda 创建隔离环境避免 pip 污染全局# 推荐用 conda比 virtualenv 更稳尤其对 numpy/scipy conda create -n house_pred python3.6.8 conda activate house_pred pip install -r requirements.txt提示requirements.txt文件位于压缩包根目录共 23 行依赖。重点检查pymysql0.9.3非 mysqlclient、flask1.0.2非 2.x、lxml4.4.1用于解析安居客 HTML。若pip install卡在Building wheel for lxml请先执行conda install -c conda-forge lxml再运行 pip。2.2 MySQL 数据库创建与 Navicat 导入别手敲 SQL用 .sql 文件一键还原压缩包内含house_db.sql文件大小 1.2MB这是完整的数据库脚本。不要手动建库、不要复制粘贴建表语句——里面包含 7 张表的外键约束、全文索引、默认值和注释手敲极易遗漏。正确做法是在 Navicat 11 中新建连接主机127.0.0.1端口3306用户名root密码为空默认配置右键连接名 → “新建数据库”编码选utf8mb4排序规则utf8mb4_unicode_ci右键新库 → “运行 SQL 文件”选择house_db.sql勾选“继续执行遇到错误的语句”点击“开始”。导入完成后你会看到user,house_info,prediction_result,crawl_log等 7 张表。其中house_info表含 17 个字段关键业务字段如下字段名类型含义示例值area_namevarchar(50)所属行政区“浦东新区”subway_distdecimal(5,2)距最近地铁站距离km0.85floor_leveltinyint楼层1低层2中层3高层2decorationtinyint装修1毛坯2简装3精装3price_per_m2decimal(10,2)单价元/㎡72500.00predict_pricedecimal(10,2)预测总价元8260000.002.3 配置文件修改config.py里的三处必须改否则 Flask 启动即报错项目根目录下config.py是核心配置文件。需修改以下三处其他保持默认# config.py import os class Config: # 1. 数据库连接字符串必须改成你本地 MySQL 的实际账号密码 SQLALCHEMY_DATABASE_URI mysqlpymysql://root:127.0.0.1:3306/house_db?charsetutf8mb4 # 2. SECRET_KEY生成一个随机密钥防止 session 被篡改用 python -c import secrets; print(secrets.token_hex()) 生成 SECRET_KEY a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 # 3. 爬虫超时设置安居客反爬较严timeout 必须 ≥ 15 秒否则 get_house_list() 会返回空列表 CRAWL_TIMEOUT 15注意SQLALCHEMY_DATABASE_URI中的house_db必须与你在 Navicat 中创建的数据库名完全一致区分大小写SECRET_KEY若不改登录后所有页面会提示“CSRF token missing”这是 Flask-WTF 的安全机制不是 bug。3. 核心模块拆解爬虫、预测、可视化每个模块都留了调试入口系统采用典型的三层架构app/crawl/数据采集、app/predict/模型训练与预测、app/static/前端资源。所有模块均提供if __name__ __main__:入口方便单独调试无需启动整个 Web 服务。3.1 爬虫模块双源适配 动态 UA 自动翻页不是简单 requests.get爬虫逻辑集中在app/crawl/ajk_crawler.py安居客和app/crawl/58_crawler.py58 同城。二者均继承自BaseCrawler共享反爬策略动态 User-Agent每次请求从app/crawl/user_agents.txt含 200 条主流浏览器 UA中随机选取Referer 模拟构造https://sh.58.com/ershoufang/或https://sh.anjuke.com/sale/作为来源页请求间隔控制time.sleep(random.uniform(1.5, 3.0))避免被封 IP异常重试机制网络错误自动重试 3 次超时则记录到crawl_log表。调试方法直接运行python app/crawl/ajk_crawler.py它会打印出抓取的前 5 条房源标题、单价、链接。若输出为空请检查CRAWL_TIMEOUT是否 ≥15以及user_agents.txt是否存在。3.2 预测模块XGBoost 回归模型 特征工程脚本不是调包侠式训练预测核心在app/predict/model_train.py。它不直接用XGBRegressor().fit()而是做了三步关键处理特征缩放对area,room_num,hall_num,toilet_num,floor_level,subway_dist等数值型字段做StandardScaler归一化类别编码对decoration,orientation,property_type等字段用LabelEncoder编码非 one-hot因类别数少且有序目标变量转换对total_price总价取log1p缓解长尾分布提升模型鲁棒性。训练后模型保存为app/predict/xgb_model.pkl预测时直接加载无需重新训练。验证指标显示在测试集上 MAE平均绝对误差为 ¥12.6 万R² 达 0.87符合毕业设计要求。3.3 可视化模块ECharts 前端 Matplotlib 后端双渲染支持导出 PNG可视化分两层前端交互图由templates/index.html中的 ECharts 实现包括“上海各区均价热力图”、“三室两厅户型价格分布箱线图”、“近半年挂牌价趋势折线图”后端静态图app/routes.py中/api/export_chart接口调用app/visualize/plot_utils.py用 Matplotlib 生成 PNG供用户下载。关键参数在app/visualize/config.py# 图片分辨率与字体 DPI 150 FONT_SIZE 12 CHINESE_FONT SimHei # 必须系统已安装Windows 默认有Linux 需 sudo apt install fonts-wqy-zenhei若导出图片中文乱码请确认系统是否安装中文字体并修改CHINESE_FONT为WenQuanYi Zen HeiLinux或Microsoft YaHeiWindows。4. 避坑指南这 4 个坑我替你踩过了省下至少 15 小时 debug 时间4.1 现象启动 Flask 后访问http://127.0.0.1:5000显示TemplateNotFound: index.html原因PyCharm 默认工作目录不是项目根目录导致 Flask 找不到templates/文件夹。app.py中app Flask(__name__)默认从当前路径找 templates而你可能在app/目录下右键运行。解决在 PyCharm 中右键app.py→ “Modify Run Configuration” → “Working directory” 改为项目根目录即含app/,templates/,static/的文件夹或在代码中显式指定app Flask(__name__, template_folder../templates, static_folder../static)4.2 现象爬虫成功运行但house_info表中price_per_m2字段全为 0原因安居客网页结构更新原 XPath//div[classprice]/span[1]/text()已失效新页面改为//div[classprice]/span[classunit]/text()。解决打开app/crawl/ajk_crawler.py找到parse_house_list()方法将第 87 行price_text item.xpath(.//div[classprice]/span[1]/text()).get()改为price_text item.xpath(.//div[classprice]/span[classunit]/text()).get() or \ item.xpath(.//div[classprice]/span[1]/text()).get()这是典型的“XPath 容错写法”优先匹配新结构失败则回退旧结构。4.3 现象登录后点击“房价分析”菜单页面空白浏览器控制台报Uncaught ReferenceError: echarts is not defined原因static/js/echarts.min.js文件被压缩损坏或index.html中script标签顺序错误导致 ECharts 在 jQuery 之前加载。解决检查static/js/目录下echarts.min.js文件大小正常应为 1.8MB。若小于 1MB说明下载不完整需重新解压。同时确认index.html中脚本顺序为script src{{ url_for(static, filenamejs/jquery.min.js) }}/script script src{{ url_for(static, filenamejs/echarts.min.js) }}/script script src{{ url_for(static, filenamejs/index_chart.js) }}/script4.4 现象预测结果页面显示“预测失败No module named xgboost原因xgboost在 Windows 上需编译pip install xgboost常失败且requirements.txt中写的是xgboost0.90但该版本不兼容 Python 3.6.8。解决卸载后用 conda 安装指定版本pip uninstall xgboost -y conda install -c conda-forge xgboost0.820.82 是唯一通过全部测试的版本更高版本会触发XGBoostError: Invalid Parameter type。5. 前端资源深度解析Layui Bootstrap 混合开发的取舍与代价这个系统的前端不是纯 Layui 或纯 Bootstrap而是以 Layui 为骨架、Bootstrap 为装饰、自定义 CSS 为缝合剂的混合体。这种设计源于毕业设计的实际约束Layui 提供开箱即用的 Admin UI表格、弹窗、表单验证而 Bootstrap 的栅格系统和组件如卡片、轮播更适合展示房价数据。但混合带来三个必须直面的问题。5.1 CSS 冲突根源.layui-btn与.btn的优先级战争Layui 的按钮类.layui-btn默认font-weight: bold而 Bootstrap 的.btn默认font-weight: normal。当两者同时作用于一个按钮如button classlayui-btn btn btn-primary提交/buttonLayui 的 CSS 文件在static/css/下加载顺序靠后其样式会覆盖 Bootstrap。这导致所有混合按钮都变粗破坏视觉一致性。解决方案是在static/css/custom.css末尾强制重置/* custom.css 第 127 行起 */ .layui-btn.btn { font-weight: normal !important; border-radius: 4px !important; } .layui-btn.btn-primary { background-color: #007bff !important; border-color: #007bff !important; }注意!important在工程中应慎用但此处是混合框架下的必要妥协。若未来升级 Layui需同步检查此重置规则是否仍生效。5.2 JS 插件加载顺序layer.js 必须在 jQuery 之后但在 laydate.js 之前static/js/目录下插件有严格依赖链jquery.min.js→layer.jsLayui 弹窗→laydate.js日期选择器→bootstrap.bundle.min.js。若顺序错乱会出现layer.open is not a function或laydate.render is not a function。templates/base.html中的加载顺序已按此排列但若你新增 JS 文件务必插入在laydate.js之后、bootstrap.bundle.min.js之前。5.3 响应式断点冲突Layui 的layui-col-md6与 Bootstrap 的col-md-6如何共存Layui 的栅格系统基于layui-col-*类Bootstrap 基于col-*类。二者断点数值不同Layuimd对应 992pxBootstrapmd对应 768px。当在一个容器中混用如div classlayui-col-md6 col-md-6小屏下 Bootstrap 的col-md-6会强制占半宽而 Layui 的layui-col-md6因未达 992px 断点会退化为 100% 宽度造成布局错乱。血泪经验全站统一用 Layui 栅格仅在需要复杂布局如房价对比卡片组时用 Bootstrap 的container-fluidrow包裹内部子元素用layui-col-*。例如首页的“最新预测”模块!-- templates/index.html -- div classcontainer-fluid div classrow div classlayui-col-md6 !-- Layui 表格最新预测列表 -- table classlayui-table.../table /div div classlayui-col-md6 !-- Layui 图表容器 -- div idprice_trend_chart styleheight:400px;/div /div /div /div这样既利用了 Bootstrap 的流体容器又保持了 Layui 栅格的断点一致性。6. 毕业答辩加分技巧三步让系统“看起来更专业”导师当场问不出技术漏洞答辩不是考你能不能写代码而是考你能不能讲清楚为什么这么写、边界在哪、如果换种方案会怎样。我带过 12 届毕设发现能拿高分的学生都做了这三件事6.1 给爬虫加“人工审核开关”把“自动化”变成“人机协同”系统默认爬虫全自动运行但这在答辩时很危险——老师会问“如果安居客改版你的系统是不是就废了” 正确回答是我们预留了人工干预通道。在app/crawl/ajk_crawler.py开头添加# 新增开关True自动爬取False跳过爬取只用已有数据 AUTO_CRAWL False # ← 答辩时设为 False演示用历史数据 if not AUTO_CRAWL: print(【答辩模式】跳过爬虫使用数据库中已有数据) return []然后在app/routes.py的/admin/crawl接口中增加状态返回app.route(/admin/crawl) def admin_crawl(): if not AUTO_CRAWL: return jsonify({status: skipped, msg: 答辩模式爬虫已禁用}) # ...原有爬取逻辑答辩时你可以说“我们设计了‘生产模式’和‘答辩模式’双态切换确保在任何网络环境下都能稳定演示核心功能。” 这比单纯说“我用了 Selenium”有力得多。6.2 在预测结果页加“特征重要性条形图”把黑匣子变成白盒XGBoost 的feature_importances_是绝佳的答辩素材。在app/routes.py的/predict/result接口中加入# 获取特征重要性 importance model.feature_importances_ feature_names [area, room_num, hall_num, toilet_num, floor_level, subway_dist, decoration] # 生成条形图数据 importance_data [{name: n, value: float(v)} for n, v in zip(feature_names, importance)] return render_template(predict_result.html, importance_dataimportance_data)前端predict_result.html中用 ECharts 渲染option { tooltip: { trigger: axis }, xAxis: { type: category, data: importanceData.map(d d.name) }, yAxis: { type: value }, series: [{ type: bar, data: importanceData.map(d d.value), label: { show: true, position: top } }] };这张图能直观回答“哪个因素对房价影响最大”——通常是area面积和subway_dist地铁距离。这证明你理解了业务逻辑而非只会调参。6.3 用 Navicat 做“数据溯源演示”让数据库成为你的答辩武器答辩时打开 Navicat连上house_db执行三条 SQL-- 1. 查看爬虫日志证明数据真实采集 SELECT * FROM crawl_log ORDER BY start_time DESC LIMIT 5; -- 2. 查看一条预测记录的原始数据与预测值对比 SELECT h.title, h.area_name, h.price_per_m2, p.predict_price, p.mae_error FROM house_info h JOIN prediction_result p ON h.id p.house_id WHERE h.id (SELECT id FROM house_info ORDER BY id DESC LIMIT 1); -- 3. 查看用户操作审计登录、预测、导出 SELECT user_id, action, ip_addr, create_time FROM user_action_log;这三步操作10 秒内就能向老师证明你的数据有来路、预测有依据、系统有审计。比讲 10 分钟原理更有效。从那以后我每次帮学生改毕设都会强制他们在答辩前用 Navicat 执行这三条 SQL并截图放进答辩 PPT 的“系统验证”页。不是为了炫技而是让所有技术决策——从爬虫频率到特征选择——都有数据库里的证据链支撑。希望帮到你。本文还有配套的精品资源点击获取