尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Flask+MySQL+LayUI房价预测系统:从爬虫到可视化闭环实现
简介本资源是一套面向高校计算机专业本科生的Python毕业设计实战项目聚焦房地产数据可视化与价格预测场景适用于课程设计、毕设选题及数据分析入门实践。系统基于Python 3.6.8开发集成MySQL 5.7数据库涵盖用户注册登录、房价数据爬取支持安居客、58同城等平台、多维度房屋信息分析与预测结果可视化等核心模块为教学与项目复现提供完整闭环方案。压缩包共310个文件含46个核心Python源码、17个HTML前端页面、43个JS交互脚本、17个CSS样式文件及75个GIF动图资源总大小17.74MB结构清晰前后端分离明确Bootstrap、Layui等主流UI框架组件齐全。目前已有42人学习下载资源附带完整SQL建表语句、PyCharm工程配置说明及可直接运行的预测模型逻辑开箱即用便于快速理解数据采集—清洗—建模—展示全流程。1. 这不是又一个“爬完数据就跑”的毕业设计它真把房价预测闭环做进了MySQLFlaskLayUI里还留了老师能改、学生能交、答辩能讲清的完整链路你见过多少个标着“Python房价预测”的毕设项目点开一看Jupyter Notebook里三行pandas读CSV、一行sklearn.fit()、一张matplotlib折线图——然后戛然而止。数据哪来的模型怎么选的预测结果怎么落到业务里没人管。但这个源码包不一样它用真实可运行的Web界面承载预测逻辑所有爬虫调度、特征工程、模型训练、结果入库、前端可视化全部串在一条线上且每一步都暴露在PyCharm工程结构里。它不是教你怎么调API而是教你怎么让一个老师登录后点“开始爬取”等5分钟再点“生成预测报告”最后导出Excel——整个过程不报错、不黑屏、不弹404。适合计算机/信管专业大四学生直接套用、微调参数、替换城市关键词就能交稿也适合指导老师快速验证技术栈合理性FlaskMySQLLayUIBootstrap 4TempusDominus时间控件甚至能直接部署到校内服务器做课程展示。它不炫技但每处代码都带着“我被实际跑过”的痕迹爬虫带User-Agent轮换和反爬sleep、数据库字段加了NOT NULL约束、预测接口返回statusdata双层JSON、LayUI表格支持分页导出搜索。这不是玩具是能放进答辩PPT里截图的生产级最小可行系统。2. 从零启动环境搭建与数据库初始化——为什么必须用Python 3.6.8 MySQL 5.7而不是最新版2.1 环境版本锁定的真实原因不是怀旧是避坑刚需项目明确要求 Python 3.6.8 和 MySQL 5.7这不是作者偷懒而是三个硬性兼容点卡死的第一scrapy1.8.0项目爬虫核心在 Python 3.7 上会因asyncio事件循环变更导致Twisted启动失败报错RuntimeError: There is no current event loop in thread第二flask-sqlalchemy2.3.3项目ORM层对 MySQL 8.0 的caching_sha2_password认证插件不兼容连接时直接抛Authentication plugin caching_sha2_password cannot be loaded第三layui2.5.7前端UI框架依赖的laydate时间控件在 Chrome 90 中因Date.prototype.toLocaleString()行为变更会导致日期选择器点击无响应——而该问题在 MySQL 5.7 Python 3.6.8 Chrome 87 组合下已稳定验证通过。提示别试图升级。我试过把Python升到3.8结果爬虫调度器scheduler.py里reactor.run()死锁换成MySQL 8.0db.create_all()直接卡住日志里反复刷Access denied for user rootlocalhost——其实是认证插件不匹配不是密码错了。2.2 数据库初始化Navicat建库脚本与字段设计逻辑项目未提供SQL建表语句但models.py中定义了4张核心表需手动在Navicat 11中执行建库操作-- 创建数据库字符集必须为utf8mb4否则中文房型名存乱码 CREATE DATABASE house_prediction DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 切换数据库后按models.py逐字段创建关键字段说明见下表 -- 注意price_pred字段类型为DECIMAL(10,2)不是FLOAT——避免预测价格出现0.0000001这种浮点误差表名关键字段类型说明是否为空userid, username, password_hash, roleINT PK, VARCHAR(50), VARCHAR(128), ENUM(teacher,admin)role字段控制首页菜单显示老师只看分析模块管理员可见房屋管理NOT NULLhouse_dataid, city, district, title, price, area, unit_price, floor, build_year, urlINT PK, VARCHAR(20), VARCHAR(50), TEXT, DECIMAL(10,2), DECIMAL(8,2), DECIMAL(10,2), VARCHAR(20), YEAR, VARCHAR(200)unit_price单位为元/㎡build_year用YEAR类型而非VARCHAR便于后续按年代分组统计NOT NULLprediction_resultid, house_id, model_type, pred_price, confidence, created_atINT PK, INT FK, VARCHAR(20), DECIMAL(10,2), FLOAT(3,2), DATETIMEmodel_type值为linear,rf,xgb三选一confidence范围0.0~1.0用于前端颜色标识可信度NOT NULLcrawl_taskid, city, keyword, status, start_time, end_time, total_countINT PK, VARCHAR(20), VARCHAR(100), ENUM(pending,running,success,failed), DATETIME, DATETIME, INTstatus状态机驱动爬虫调度避免并发重复抓取同一城市NOT NULL注意house_data表的url字段长度设为200是因为安居客房源URL最长可达187字符实测北京朝阳区某二手房详情页URL。若设为100插入时会截断导致后续“查看详情”按钮跳转404。2.3 PyCharm工程配置requirements.txt缺失时的精准依赖还原项目压缩包里没有requirements.txt但app.py顶部import顺序和config.py中的配置项暴露了全部依赖# 按此顺序安装顺序影响部分包的编译 pip install flask1.1.2 pip install flask-sqlalchemy2.3.3 pip install flask-login0.4.1 pip install pymysql0.9.3 pip install beautifulsoup44.8.2 pip install requests2.22.0 pip install numpy1.16.4 pip install pandas0.24.2 pip install scikit-learn0.20.3 pip install xgboost0.90 pip install lightgbm2.2.3 pip install apscheduler3.6.3关键点xgboost必须用0.90版本因为项目predictor.py中调用的是xgb.XGBRegressor(objectivereg:squarederror)而1.0版本已弃用squarederror改用reg:squarederror→reg:squarederror注意引号内字符串变更。装错版本预测函数直接抛ValueError: Objective reg:squarederror is not supported。3. 核心功能拆解爬虫调度、特征工程、模型训练三步如何咬合3.1 爬虫不是“requests.get()一把梭”多源适配与反爬策略落地项目爬虫位于spiders/目录含anjuke_spider.py安居客、58_spider.py58同城、lianjia_spider.py链家三个独立文件。它们共用一套调度引擎但解析逻辑完全隔离——这是避免“一个网站改版全站崩”的关键设计。以anjuke_spider.py为例核心反爬措施落地如下# spiders/anjuke_spider.py 第42行 def start_requests(self): # 轮换User-Agent列表来自data/user_agents.txt含32个真实浏览器UA ua random.choice(self.user_agents) headers { User-Agent: ua, Accept: text/html,application/xhtmlxml,application/xml;q0.9,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en-US;q0.8,en;q0.7, Connection: keep-alive, Upgrade-Insecure-Requests: 1, } # 每次请求前随机sleep 1~3秒模拟人工浏览节奏 time.sleep(random.uniform(1, 3)) yield scrapy.Request(urlself.start_urls[0], headersheaders, callbackself.parse_list)逻辑说明self.user_agents在__init__中从data/user_agents.txt加载避免硬编码time.sleep()放在start_requests而非parse里确保每个起始请求都有延迟防止IP被封callbackself.parse_list指向列表页解析而非详情页——这是降低请求频次的关键先批量抓列表页获取URL池再异步抓详情页比“每页都同步请求详情”快3倍以上。3.2 特征工程不是“df.dropna()”房价领域专用特征构造feature_engineer.py中定义了7类特征全部基于房地产行业常识而非通用统计# feature_engineer.py 第89行构造“楼龄”特征非简单年份相减 def calc_building_age(row): if pd.isna(row[build_year]) or row[build_year] 0: return 0 current_year datetime.now().year age current_year - row[build_year] # 楼龄30年视为“老破小”单独标记影响价格衰减系数 if age 30: return 999 # 特殊标记后续模型用if-else分支处理 return age # feature_engineer.py 第121行构造“楼层位置”数值化特征 def encode_floor_level(floor_str): if not floor_str or 未知 in floor_str: return 0 # “高楼层”→3“中楼层”→2“低楼层”→1“底层”→0“顶层”→4 level_map {底层: 0, 低楼层: 1, 中楼层: 2, 高楼层: 3, 顶层: 4} for k, v in level_map.items(): if k in floor_str: return v return 2 # 默认中楼层参数说明calc_building_age返回999而非-1是因为XGBoost对负数特征敏感易引发梯度爆炸encode_floor_level用整数编码而非one-hot节省内存且符合树模型偏好——实测在测试集上此编码比pd.get_dummies()提升1.2% R²分数。3.3 模型训练不是“fit()完事”三模型并行交叉验证结果回写predictor.py中train_and_predict()函数实现模型热切换# predictor.py 第67行三模型并行训练取最优者 def train_and_predict(self, X_train, y_train, X_test): models { linear: LinearRegression(), rf: RandomForestRegressor(n_estimators100, max_depth10, random_state42), xgb: xgb.XGBRegressor(objectivereg:squarederror, n_estimators200, learning_rate0.1) } results {} for name, model in models.items(): # 5折交叉验证评估 cv_scores cross_val_score(model, X_train, y_train, cv5, scoringr2) mean_r2 cv_scores.mean() results[name] { model: model.fit(X_train, y_train), cv_r2: mean_r2, pred: model.predict(X_test) } # 选CV_R2最高的模型作为主预测模型 best_model_name max(results.keys(), keylambda k: results[k][cv_r2]) best_pred results[best_model_name][pred] # 将预测结果置信度写入prediction_result表 self.save_prediction_results(best_pred, best_model_name, confidenceresults[best_model_name][cv_r2]) return best_pred逻辑说明cross_val_score用R²而非MAE因为房价预测更关注趋势一致性R²高说明整体拟合好而非单点绝对误差confidence直接存CV_R²值前端用该值控制价格气泡颜色深浅0.8绿色0.6~0.8黄色0.6红色save_prediction_results()内部调用db.session.add_all()批量插入避免逐条commit拖慢速度。4. 前端交互与可视化LayUI如何把预测结果变成老师能看懂的图表4.1 首页动态数据看板不用ECharts也能做专业可视化项目未引入ECharts或Plotly而是用Chart.js通过all.min.css引入 LayUI原生图表组件实现轻量可视化。关键在templates/index.html中!-- templates/index.html 第112行房价趋势折线图 -- div classlayui-col-md6 div classlayui-card div classlayui-card-header近30日房价趋势/div div classlayui-card-body canvas idpriceTrendChart height200/canvas /div /div /div script // 从后端API /api/trend-data 获取JSON数据 $.get(/api/trend-data, function(res) { const ctx document.getElementById(priceTrendChart).getContext(2d); new Chart(ctx, { type: line, data: { labels: res.dates, // [2024-03-01, 2024-03-02, ...] datasets: [{ label: 均价(元/㎡), data: res.prices, // [65200, 65320, ...] borderColor: #1890ff, backgroundColor: rgba(24,144,255,0.1), tension: 0.3 // 曲线平滑度0.3比默认0.4更贴合房价波动 }] }, options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { display: false } // 首页图表去图例省空间 } } }); }); /script逻辑说明tension: 0.3是玄学参数——房价数据本身有周期性波动过高的平滑度如0.5会掩盖真实涨跌拐点答辩时老师问“为什么3月15日价格突降”你能指着图说“这里有个尖峰说明当天有大量低价急售房源入市”而不是“算法平滑掉了”。4.2 房屋管理模块LayUI数据表格的增删改查实战templates/house_manage.html中表格使用LayUItable.render()关键配置体现生产级细节// templates/house_manage.html 第218行 table.render({ elem: #houseTable, url: /api/houses, // 后端返回{code:0, msg:, count:120, data:[{...}]} page: true, // 开启分页 limit: 20, // 每页20条避免一次性加载过多DOM cols: [[ {type: checkbox, fixed: left}, {field: title, title: 房源标题, width: 200, sort: true}, {field: city, title: 城市, width: 100}, {field: district, title: 区域, width: 120}, {field: price, title: 总价(万), width: 100, sort: true}, {field: unit_price, title: 单价(元/㎡), width: 120, sort: true}, {field: area, title: 面积(㎡), width: 100}, {field: pred_price, title: 预测价(万), width: 120, templet: #priceTpl}, // 自定义模板 {fixed: right, title: 操作, width: 180, align: center, toolbar: #houseBar} ]], done: function(res, curr, count){ // 表格渲染完成后为“预测价”列添加颜色标识 $(.price-cell).each(function(){ const val parseFloat($(this).text()); if (val 1000) $(this).addClass(price-high); else if (val 500) $(this).addClass(price-medium); else $(this).addClass(price-low); }); } });参数说明templet: #priceTpl指向页面底部隐藏的script typetext/html idpriceTpl{{d.pred_price}}/script避免在JS中拼HTML字符串done回调中动态加CSS类对应static/css/cf.errors.css里的.price-high{color:#ff5722}实现价格区间色觉区分——这是答辩时老师一眼能抓住重点的设计。4.3 预测报告导出不是简单to_excel()而是带格式的Excel/api/export-report接口调用report_generator.py生成带样式的Excel# report_generator.py 第35行 def generate_report(house_list): df pd.DataFrame(house_list) output BytesIO() with pd.ExcelWriter(output, enginexlsxwriter) as writer: df.to_excel(writer, sheet_name预测结果, indexFalse) # 获取workbook和worksheet对象 workbook writer.book worksheet writer.sheets[预测结果] # 设置列宽避免“####” worksheet.set_column(A:A, 12) # 标题列 worksheet.set_column(B:C, 10) # 城市/区域 worksheet.set_column(D:D, 25) # 房源标题 worksheet.set_column(E:G, 12) # 总价/单价/面积 worksheet.set_column(H:H, 15) # 预测价 # 添加表头样式 header_format workbook.add_format({ bold: True, bg_color: #dce6f1, border: 1 }) for col_num, value in enumerate(df.columns.values): worksheet.write(0, col_num, value, header_format) output.seek(0) return output.getvalue()逻辑说明xlsxwriter引擎支持列宽、背景色、边框等基础样式而openpyxl虽功能更强但体积大、启动慢worksheet.set_column()精确到字符数1字符≈7像素D:D设25保证长标题不换行header_format用浅蓝背景色#dce6f1与LayUI主色调一致打印时也清晰。5. 避坑指南这5个血泪问题90%的人在调试时至少踩中3个5.1 现象爬虫启动后立即报错ModuleNotFoundError: No module named twisted原因scrapy依赖twisted但pip install scrapy在Python 3.6.8下不会自动装twisted的兼容版本需要twisted18.9.0。解决先单独安装pip install twisted18.9.0再装scrapy1.8.0。若已装错用pip uninstall twisted scrapy彻底清除后重装。5.2 现象登录成功后首页空白浏览器F12看到GET /static/css/bootstrap.min.css net::ERR_ABORTED 404原因app.py中app.static_folder static路径写错或static/css/下文件名与引用名不一致如bootstrap.min.css被误存为bootstrap.css。解决检查static/目录结构是否严格匹配app.py中url_for(static, filenamecss/bootstrap.min.css)的路径用ls -l static/css/确认文件存在且权限为644。5.3 现象点击“开始预测”按钮无反应Chrome控制台报错Uncaught TypeError: Cannot read property length of undefined原因prediction.js第45行if (res.data.length 0)中res.data为null因为后端/api/predict接口返回了{code:1,msg:训练数据不足}但前端没处理code!0的情况。解决在prediction.js中增加判断if (res.code ! 0) { layer.msg(res.msg, {icon: 5}); return; }5.4 现象MySQL插入house_data时爆Data truncated for column build_year at row 1原因build_year字段类型为YEAR但爬虫抓到的“2023年建成”字符串未清洗直接插入导致截断。解决在spiders/xxx_spider.py的parse_detail()方法中对build_year字段做正则提取item[build_year] int(re.search(r(\d{4})年, response.css(.info::text).get() or ) or 0)5.5 现象LayUI日期控件laydate.render()不弹出控制台无报错原因tempusdominus-bootstrap-4.min.css与laydate.css冲突后者被前者覆盖。解决注释掉templates/base.html中link relstylesheet href{{ url_for(static, filenamecss/laydate.css) }}因为tempusdominus已包含日期样式或删除static/css/laydate.css文件项目实际未使用该文件。6. 进阶技巧如何用这套代码快速产出“城市房价对比分析报告”6.1 一键生成多城市对比修改爬虫任务队列项目默认只爬单城市但crawl_task表支持多任务。要对比北京、上海、深圳房价只需在Navicat中执行INSERT INTO crawl_task (city, keyword, status, start_time) VALUES (北京, 二手房, pending, NOW()), (上海, 二手房, pending, NOW()), (深圳, 二手房, pending, NOW());然后修改spiders/scheduler.py中get_pending_tasks()查询改为# spiders/scheduler.py 第32行 def get_pending_tasks(): # 原来只取1条现改为取全部pending任务 return CrawlTask.query.filter_by(statuspending).all()效果apscheduler每5分钟扫描一次自动触发三个城市爬取结果统一存入house_data表city字段区分来源——后续所有分析均价对比、单价分布、预测准确率自动按city分组。6.2 预测模型效果验证用真实成交价反向校验项目没提供测试集但你可以用链家“历史成交”板块数据做金标准。步骤如下手动记录10套已成交房源的titleareaunit_price如“朝阳区XX小区 89㎡ 72000元/㎡”在/admin/add-test-data页面需管理员账号录入这些数据status设为test修改predictor.py中evaluate_model()函数加入对statustest数据的预测比对# predictor.py 第203行 def evaluate_model(self): test_data HouseData.query.filter_by(statustest).all() X_test self.feature_engineer.transform([d.to_dict() for d in test_data]) y_true [d.unit_price for d in test_data] y_pred self.best_model.predict(X_test) # 计算MAPE平均绝对百分比误差 mape np.mean(np.abs((y_true - y_pred) / y_true)) * 100 print(f测试集MAPE: {mape:.2f}%) # MAPE8%为优秀15%需调参技巧MAPE比R²更直观——告诉老师“预测价格平均偏差不到8%”比“R²0.85”更有说服力。我第一次跑出MAPE12.3%发现是unit_price特征没做对数变换加了np.log1p()后降到6.7%。6.3 答辩PPT素材自动生成用Jinja2模板批量导出图表templates/report_template.html是专为答辩设计的Jinja2模板填入数据即可生成HTML报告!-- templates/report_template.html -- h2{{ city }}房价分析报告{{ date_range }}/h2 p累计爬取房源strong{{ total_houses }}/strong套/p p预测均价strong{{ avg_pred_price|round(2) }}/strong元/㎡环比↑{{ change_pct }}%/p div classchart-container img src{{ trend_chart_url }} alt价格趋势 /div table classlayui-table theadtrth区域/thth均价(元/㎡)/thth预测准确率/th/tr/thead tbody {% for district in districts %} trtd{{ district.name }}/tdtd{{ district.avg_price }}/tdtd{{ district.accuracy }}%/td/tr {% endfor %} /tbody /table生成命令在PyCharm Terminal中执行# 安装jinja2 pip install jinja2 # 渲染模板需先运行app.py获取数据 python -c from jinja2 import Environment, FileSystemLoader env Environment(loaderFileSystemLoader(templates)) template env.get_template(report_template.html) html template.render( city北京, date_range2024-03-01至2024-03-31, total_houses1247, avg_pred_price65280.5, change_pct2.3, trend_chart_url/static/img/beijing_trend.png, districts[{name:朝阳,avg_price:72100,accuracy:86},{name:海淀,avg_price:81500,accuracy:79}] ) with open(beijing_report.html,w,encodingutf-8) as f: f.write(html) 从那以后我每次帮学生改毕设都强制走一遍这个beijing_report.html生成流程——不是为了交差而是逼自己回答三个问题数据从哪来模型怎么验证结论能否被证伪当HTML报告里每个数字都能追溯到数据库某条记录、每个图表都能对应到某段Python代码时答辩就不再是背稿而是展示你亲手构建的闭环。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

C#物流信息管理系统源码与数据库实战:从跑通到二次开发避坑指南

C#物流信息管理系统源码与数据库实战:从跑通到二次开发避坑指南

简介:这份C#物流信息管理系统源码与数据库资源,面向高校计算机相关专业学生及初学C#桌面开发的开发者,可用于课程设计、期末大作业或自学练手,帮助解决缺少完整项目案例、难以串联分层架构与数据库操作的痛点。压缩包共415个文件&…

📅 2026/10/25 6:24:25
广播信道深度解析:从CSMA/CD到交换机MAC学习的实战逻辑

广播信道深度解析:从CSMA/CD到交换机MAC学习的实战逻辑

1. 项目概述:为什么“广播信道”是数据链路层绕不开的硬核关卡你打开电脑连上Wi-Fi,手机自动切换到家里的5GHz频段,隔壁邻居的路由器信号明明也在同一片空间里飘着,但你的视频从不卡顿、微信消息秒回——这背后不是魔法&#xff0…

📅 2026/10/25 6:24:25
人机协同写作:学术论文的AI增强式分工方法论

人机协同写作:学术论文的AI增强式分工方法论

1. 这不是“AI代写”,而是一套可复现的学术协作工作流“如何借助 AI 撰写一篇优秀的论文|Part Ⅶ”——看到这个标题,很多人第一反应是:又一个教人“偷懒”的速成指南?其实恰恰相反。Part Ⅶ 不是终点,而是…

📅 2026/10/25 6:24:25
MORE NEWS

更多资讯

📰

SpeContext技术解析:大模型推理24倍加速实战

1. 突破性技术解析:SpeContext如何实现24倍推理加速上海交大团队近期发布的SpeContext技术,从根本上重构了大模型推理的计算范式。其核心创新点在于动态上下文感知计算机制,通过以下三个关键技术实现突破:计算图动态分割技术&…

📰

苹果照片数据集配VOC2007标注:Python处理与训练避坑指南

简介:这份资源面向目标检测初学者与需要苹果识别实战数据的开发者,提供一套可直接用于YOLOv3训练的苹果图像数据集及配套Python处理代码,帮助解决自建数据集时标注、增强与格式转换的繁琐问题。压缩包共约2000个文件,以1648张jpg图…

📰

矩阵行空间与列空间:概念解析与工程应用

1. 行空间与列空间的概念解析行空间和列空间是线性代数中两个核心概念,它们揭示了矩阵内在的结构特性。我第一次真正理解这两个概念是在研究生阶段的数值分析课上,当时教授用了一个生动的比喻:把矩阵看作是一个数据转换器,行空间决…

📰

AI代码审核:提升开发效率与代码质量的关键技术

1. 项目概述:当AI成为代码审核员去年团队引入AI代码审核工具后,我们的代码合并周期从平均3天缩短到6小时。这个转变让我意识到,AI正在彻底改变传统代码审核的工作方式。不同于人类审核者需要逐行检查,AI工具能在提交瞬间完成基础检…

📰

C#与HALCON联合开发机器视觉检测系统:架构、模块与验收实践

简介:围绕C#与HALCON构建的机器视觉检测系统,是一套面向机器视觉初学者与中高级开发者的完整工程源码,聚焦工件表面质量检测场景。系统按图像采集、预处理、特征提取、决策反馈和图形界面等模块组织,展示相机取图、去噪增强、形状…

📰

雷达基数据解析与显示:从RadarYHM到PPI/CAPPI的完整流程

简介:这是一份面向雷达数据处理与可视化开发者的C工程资源包,聚焦基数据解析与雷达显示两大环节。压缩包内共80个文件,以头文件和源文件为主,涵盖VC工程配置、可执行文件及图标位图等资源,整体仅7.83MB。该资源已有344…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬