资讯动态

Python二手房房价预测分析源码:从爬虫到机器学习全流程实战

发布时间:2026/10/12 20:39:06 来源:尧图企业网站定制
简介这份资源面向计算机相关专业的毕业设计、期末大作业与课程设计需求者提供一套从数据采集到房价预测建模的完整Python实战方案覆盖爬虫、数据清洗、特征工程与机器学习预测全流程适合具备Python基础、希望快速完成高分项目的学生参考。压缩包共26个文件约1.28MB以15个py脚本为核心辅以ipynb交互式笔记本、csv数据集、html分析报告、jpg可视化图表及read、md说明文档代码含注释新手也能理解整体逻辑。目前已有416人学习下载说明该方案在同类选题中具备一定参考价值。资源围绕北京二手房数据展开包含链家与安居客两个爬虫模块可帮助读者掌握数据抓取、字段整理、可视化呈现与模型训练评估的完整链路并附有项目说明与依赖配置下载后简单部署即可运行便于对照复现与二次修改适合作为毕业设计或课程设计的起步模板。1. 从一份能跑通的二手房房价预测源码说起很多做毕业设计或课程大作业的同学卡住的地方往往不是模型本身而是数据从哪来、字段怎么对齐、特征怎么构造、跑出来的图为什么和别人的不一样。这份基于 Python 的二手房房价预测分析源码把「爬虫采集 → 数据清洗 → 特征工程 → 机器学习建模 → 可视化输出」整条链路打包成了一个可直接运行的工程目录里既有lianjia.csv、anjuke.csv这样的原始数据也有lianjia_scrapy_crawl、anjuke_scrapy_crawl两套爬虫脚本还有北京二手房房价预测与分析.ipynb这个主分析笔记和配套的visuals.py。它解决的核心问题是让你不用从零搭环境、不用自己摸索字段含义就能在本地复现一套完整的房价预测流程并且拿到能写进论文或答辩 PPT 的图表和指标。适合谁正在做毕业设计、期末大作业、课程设计需要一份结构完整、注释清晰、导师认可度高的 Python 机器学习项目的人。下面我按实际拆包和跑通的顺序把这份资源讲透。2. 拆开压缩包目录结构与两套爬虫的选型逻辑2.1 文件清单与各模块职责拿到压缩包后先别急着运行ipynb花两分钟把目录结构看清楚后面排错会省很多事。这份资源的文件组织大致是这样的文件/目录类型作用北京二手房房价预测与分析.ipynbJupyter Notebook主分析流程含数据读取、清洗、建模、评估北京二手房房价预测与分析.htmlHTMLNotebook 导出结果方便直接看输出visuals.pyPython 脚本封装绘图函数被 Notebook 调用lianjia.csv数据文件链家二手房原始/半清洗数据anjuke.csv数据文件安居客二手房原始/半清洗数据lianjia_scrapy_crawl爬虫目录基于 Scrapy 的链家采集脚本anjuke_scrapy_crawl爬虫目录基于 Scrapy 的安居客采集脚本ershoufang_0.JPG~ershoufang_3.JPG图片可视化结果截图可直接用于报告README.md文档项目说明与运行提示.gitignore配置Git 忽略规则这里有个细节值得注意数据文件是.csv而不是数据库说明作者已经把爬取结果落盘成了静态文件。这意味着你即使不跑爬虫也能直接用现成数据完成后续的机器学习部分。对于时间紧、只想跑通建模流程的同学这是最省事的路径。2.2 为什么是 Scrapy 而不是 requests两套爬虫都用了 Scrapy 框架而不是很多人入门时写的requests BeautifulSoup。常见做法是单页、少量数据用 requests 就够了但二手房列表页有分页、有详情页、字段多、需要限速和重试Scrapy 的Item Pipeline、Downloader Middleware、AutoThrottle这些机制能省掉大量手写调度代码。源码里lianjia_scrapy_crawl和anjuke_scrapy_crawl分开也是因为两个站点的页面结构、字段命名、翻页规则不一样混在一起反而容易互相干扰。如果你只是想理解爬虫原理可以只看其中一个目录的spiders文件夹如果你要复现采集建议先跑链家那套因为lianjia.csv的字段更规整后续清洗逻辑也主要围绕它展开。2.3 环境准备与依赖安装在跑任何代码之前先把 Python 环境理顺。这份源码没有附带requirements.txt所以依赖需要自己装。我一般会先建一个虚拟环境避免和系统里的包冲突# 创建虚拟环境Python 3.8 及以上都可以 python -m venv venv # Windows 激活 venv\Scripts\activate # macOS / Linux 激活 source venv/bin/activate # 安装核心依赖 pip install numpy pandas matplotlib seaborn scikit-learn jupyter scrapy逻辑说明numpy和pandas负责数值计算与表格处理matplotlib和seaborn负责绘图scikit-learn提供回归模型和评估指标jupyter用来打开.ipynbscrapy只在你要跑爬虫时才需要。参数上Python 版本建议 3.8 到 3.10太新的版本有时会让某些老依赖编译失败如果安装scrapy时卡在Twisted可以先单独pip install twisted再装scrapy。提示如果你只做建模分析不跑爬虫可以跳过scrapy的安装能省不少时间。3. 数据清洗与特征工程把 CSV 变成模型能吃的格式3.1 读取数据与字段初探打开北京二手房房价预测与分析.ipynb前几个 cell 通常是导入库和读取 CSV。这里不要直接点「Run All」先逐块看。二手房数据里最常见的字段包括总价、单价、小区、区域、户型、面积、朝向、楼层、装修、建成年代等。不同来源的 CSV 字段名可能不一致比如链家用「总价(万)」安居客可能用「价格」所以第一步是统一列名。import pandas as pd import numpy as np # 读取链家数据注意编码中文 CSV 常见 utf-8 或 gbk df pd.read_csv(lianjia.csv, encodingutf-8) # 查看前五行和字段类型 print(df.head()) print(df.dtypes) # 统一列名去掉括号和单位方便后续处理 df.columns [c.replace((万), ).replace((㎡), ).replace((元/平), ) for c in df.columns]逻辑说明encoding参数很关键如果报UnicodeDecodeError换成gbk再试。列名清洗是为了后面写特征时不用反复处理特殊字符。参数上df.head()用来确认数据是否读歪df.dtypes用来判断哪些列是字符串、哪些是数值字符串列通常需要转换。3.2 缺失值、异常值与重复值处理二手房数据里缺失和异常是常态。比如「建成年代」可能为空「面积」可能出现 0 或 9999 这种明显错误的值。常见做法是缺失比例超过 60% 的列直接删掉数值列用中位数填充类别列用众数填充面积小于 10 平米或大于 1000 平米的记录视为异常直接过滤。# 删除缺失过多的列 threshold len(df) * 0.6 df df.dropna(threshthreshold, axis1) # 数值列用中位数填充 num_cols df.select_dtypes(include[np.number]).columns df[num_cols] df[num_cols].fillna(df[num_cols].median()) # 类别列用众数填充 cat_cols df.select_dtypes(include[object]).columns for col in cat_cols: df[col] df[col].fillna(df[col].mode()[0]) # 过滤异常面积 df df[(df[面积] 10) (df[面积] 1000)] # 去重 df df.drop_duplicates()逻辑说明thresh参数控制保留列的最低非空数量axis1表示按列判断。中位数比均值更抗异常值适合房价这种偏态分布。类别列用众数填充是为了不破坏类别分布。面积过滤的上下限可以根据你的数据分布调整但 10 到 1000 是一个比较安全的经验区间。3.3 特征构造把「户型」「朝向」变成数值机器学习模型不能直接吃字符串所以要把类别特征转成数值。户型可以拆成「室」「厅」两个数值列朝向可以按优劣映射成分数楼层可以分成低、中、高三个类别再做独热编码。# 拆分户型例如 2室1厅 - 2 和 1 df[室] df[户型].str.extract(r(\d)室).astype(float) df[厅] df[户型].str.extract(r(\d)厅).astype(float) # 朝向映射成分数南向最高 direction_map {南: 5, 东南: 4, 东: 3, 西南: 3, 北: 2, 西: 2, 东北: 1, 西北: 1} df[朝向分数] df[朝向].map(direction_map).fillna(2) # 楼层分类 def floor_level(x): if pd.isna(x): return 未知 x str(x) if 低 in x: return 低楼层 elif 中 in x: return 中楼层 elif 高 in x: return 高楼层 return 未知 df[楼层类别] df[楼层].apply(floor_level) # 对楼层类别做独热编码 df pd.get_dummies(df, columns[楼层类别], drop_firstTrue)逻辑说明正则(\d)室用来提取数字astype(float)是为了后续能参与计算。朝向映射没有绝对标准这里给的分数只是常见做法你可以根据业务理解调整。pd.get_dummies的drop_firstTrue是为了避免虚拟变量陷阱在线性回归里尤其重要。注意如果你用的是树模型如随机森林、XGBoost独热编码不是必须的但做了也不影响只是维度会增加。4. 建模与评估选哪个回归模型、指标怎么看4.1 训练集测试集划分与特征选择特征构造完之后要把数据分成训练集和测试集。常见比例是 8:2 或 7:3。目标变量通常是「总价」或「单价」如果预测总价面积就是一个强特征如果预测单价面积的影响会小一些。源码里主分析笔记应该是围绕总价或单价做的回归。from sklearn.model_selection import train_test_split # 选择特征列排除目标变量和原始文本列 feature_cols [面积, 室, 厅, 朝向分数, 建成年代] # 根据实际列名调整 X df[feature_cols] y df[总价] # 或 df[单价] # 划分训练集和测试集 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.2, random_state42)逻辑说明random_state42是为了结果可复现答辩时老师如果让你再跑一遍固定随机种子能保证指标一致。feature_cols需要根据你清洗后的实际列名调整如果某些列缺失先回上一步检查。4.2 线性回归、随机森林与评估指标源码里大概率会对比多个模型。常见组合是线性回归做基线随机森林或梯度提升树做提升。评估指标用 MAE、MSE、RMSE 和 R²。RMSE 对异常值敏感R² 反映拟合优度MAE 解释性最强。from sklearn.linear_model import LinearRegression from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score # 线性回归基线 lr LinearRegression() lr.fit(X_train, y_train) lr_pred lr.predict(X_test) # 随机森林 rf RandomForestRegressor(n_estimators100, random_state42) rf.fit(X_train, y_train) rf_pred rf.predict(X_test) # 评估函数 def evaluate(y_true, y_pred, name): mae mean_absolute_error(y_true, y_pred) rmse np.sqrt(mean_squared_error(y_true, y_pred)) r2 r2_score(y_true, y_pred) print(f{name} - MAE: {mae:.2f}, RMSE: {rmse:.2f}, R2: {r2:.4f}) evaluate(y_test, lr_pred, LinearRegression) evaluate(y_test, rf_pred, RandomForest)逻辑说明n_estimators100是随机森林的树数量太少容易欠拟合太多训练慢100 到 300 是常见区间。random_state同样是为了复现。评估时不要只看 R²如果 MAE 很大说明预测偏差在业务上不可接受需要回头检查特征或异常值。4.3 可视化输出与 visuals.py 的调用visuals.py里封装的应该是房价分布图、特征重要性图、预测值与真实值对比图等。这些图在ershoufang_0.JPG到ershoufang_3.JPG里能看到效果。调用方式通常是在 Notebook 里import visuals然后传 DataFrame 进去。import visuals # 假设 visuals 里有绘制房价分布的函数 visuals.plot_price_distribution(df, save_pathprice_dist.png) # 绘制特征重要性 visuals.plot_feature_importance(rf, feature_cols, save_pathfeature_importance.png)逻辑说明把绘图逻辑单独抽到visuals.py的好处是 Notebook 更干净也方便重复使用。如果你要改图风格直接改visuals.py里的参数即可不用动主流程。保存路径建议用相对路径避免换电脑后找不到文件。5. 避坑与排查跑这份源码时最容易翻车的几个点5.1 中文乱码与编码报错现象读取lianjia.csv或anjuke.csv时抛出UnicodeDecodeError或者读进来后中文列名变成乱码。原因CSV 文件可能是gbk或gb18030编码而pd.read_csv默认用utf-8。解决先试encodinggbk再试encodinggb18030如果都不行用chardet检测编码。import chardet with open(lianjia.csv, rb) as f: result chardet.detect(f.read(10000)) print(result[encoding])5.2 列名不匹配导致 KeyError现象运行到特征选择或绘图时报KeyError: 面积或类似错误。原因清洗后列名被修改或者原始 CSV 里列名带空格、括号。解决在 Notebook 里单独跑一个 cell 打印df.columns把实际列名复制到feature_cols里。不要凭记忆写列名。5.3 爬虫跑不动或返回空数据现象运行lianjia_scrapy_crawl后没有生成新的 CSV或者日志里全是 403、302。原因目标站点页面结构变了或者请求频率过高被限制。解决先检查spiders里的start_urls和parse方法是否还能匹配当前页面降低并发在settings.py里把DOWNLOAD_DELAY调到 2 以上开启AUTOTHROTTLE。如果只是做毕业设计直接用现成的lianjia.csv更稳妥。5.4 模型指标异常低或异常高现象R² 是负数或者接近 1。原因负数通常说明特征和目标变量关系没捕捉到可能是特征选错、数据没清洗干净接近 1 可能是数据泄漏比如把「单价」当特征去预测「总价」。解决检查特征列里有没有包含目标变量的直接计算结果确保训练集和测试集划分在特征工程之后、但目标变量没有参与构造。5.5 Jupyter Notebook 路径问题现象FileNotFoundError找不到 CSV 或图片保存失败。原因Notebook 的工作目录和文件实际目录不一致。解决在 Notebook 开头加import os; print(os.getcwd())确认当前目录然后用相对路径或os.chdir()切到项目根目录。6. 进阶技巧把这份源码改成你自己的课题跑通默认流程只是第一步真正让这份资源发挥价值的是把它改成你自己的题目。比如把「北京」换成你所在的城市把「总价预测」换成「单价预测」或「是否高价房分类」把线性回归换成 XGBoost 并做网格调参。这里给一个特征重要性和调参的进阶示例。from sklearn.model_selection import GridSearchCV # 随机森林调参 param_grid { n_estimators: [100, 200, 300], max_depth: [None, 10, 20], min_samples_split: [2, 5, 10] } rf RandomForestRegressor(random_state42) grid GridSearchCV(rf, param_grid, cv5, scoringneg_mean_absolute_error, n_jobs-1) grid.fit(X_train, y_train) print(最佳参数:, grid.best_params_) print(最佳 MAE:, -grid.best_score_) # 用最佳模型重新评估 best_rf grid.best_estimator_ best_pred best_rf.predict(X_test) evaluate(y_test, best_pred, BestRandomForest)逻辑说明cv5是五折交叉验证scoringneg_mean_absolute_error是因为 sklearn 的 GridSearchCV 默认越大越好所以用负 MAE。n_jobs-1表示用满所有 CPU 核心能明显加快调参速度。调参之后把best_params_记下来写进论文的实验设置部分比只写「用了随机森林」更有说服力。另一个技巧是特征重要性分析。随机森林训练完后可以直接拿到feature_importances_把它和visuals.py里的绘图函数结合输出一张能放进答辩 PPT 的图。import pandas as pd importance pd.DataFrame({ feature: feature_cols, importance: best_rf.feature_importances_ }).sort_values(importance, ascendingFalse) print(importance)逻辑说明feature_importances_的长度和feature_cols一致排序后能直观看到哪个特征对房价影响最大。如果「面积」排第一符合常识如果某个你没想到的列排前面就要回头检查是不是数据泄漏。最后说一个我自己的习惯每次拿到别人的源码先不跑全流程而是把ipynb里的 cell 按「数据读取 → 清洗 → 特征 → 建模 → 评估」拆成五个独立脚本每个脚本单独跑通再串起来。这样一旦中间某步报错能立刻定位是哪一层的问题不用在 Notebook 里来回翻。从那以后我每次复现这类项目都强制走一遍这个拆分流程省下来的排错时间比一开始多花的那点功夫值多了。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑