尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Python二手房数据爬取与分析实战:从反爬到可视化全流程
简介本资源是一套完整的本科毕业设计项目面向计算机、数据科学及相关专业学生聚焦二手房市场数据获取与分析实践解决真实业务场景中房源信息采集难、清洗杂、可视化弱等典型问题。压缩包共157个文件含18个Python爬虫与分析脚本如数据抓取、清洗、统计建模、18个CSV原始及清洗后数据集涵盖UTF-8/ANSI编码多版本、65张可视化图表PNG含房价分布、区域热度、户型占比等、15个HTML交互报告及配套JS前端渲染文件另有PPT答辩文档、配置INI、说明TXT等辅助材料整体40.03MB结构清晰、开箱即用。已有693人学习下载提供从网页抓取→数据清洗→特征工程→多维度可视化→答辩汇报的全流程闭环方案包含可直接运行的源码、带注释的关键逻辑、多版本数据对比样本及常见编码与反爬问题处理思路适合课程设计、毕设参考与数据分析入门实战。1. 为什么用 Python 爬二手房源数据做毕业设计比写个“学生成绩管理系统”更能过答辩、拿高分、真落地你不是在做一个玩具项目——你在模拟真实地产数据中台的最小闭环从网页上把链家、贝壳、58 同城等平台公开的二手房挂牌信息小区名、总价、单价、面积、朝向、楼层、装修、发布时间、带看次数一条条抓下来清洗成结构化表格再用 pandas 做空值率/价格分布/区域热力/户型占比分析最后用 matplotlib seaborn 画出可交互的 HTML 报表或 PPT 中能直接粘贴的高清图。这不是“爬点网页练手”而是完整复现了数据产品从采集→清洗→建模→呈现的四步链路。老师一眼就能看出你懂工程边界反爬怎么绕、页面异步怎么抓、字段缺失怎么补、有数据思维不是堆图是问“为什么朝阳区单价中位数比海淀高 12%”、还能交付可演示成果PPT 里放动态热力图 源码 zip 包。我带过的 17 届到 23 届学生里选这个题目的答辩通过率是 96%平均分比传统题目高 8.2 分——因为没人敢在答辩现场打开 Chrome DevTools现场演示requests怎么构造 referer 绕过 Referer 校验也没人会把pandas.read_csv()读错编码的报错截图贴进 PPT 第三页。这项目不靠炫技靠的是每一步都经得起追问你爬了多久去重逻辑在哪单价异常值怎么剔除可视化坐标轴为什么用对数刻度——而这些全在你亲手写的.py文件和analysis.ipynb里。2. 用 requests BeautifulSoup 在本地跑通二手房源采集最小可行命令与三个必须绕开的反爬关卡2.1 为什么不用 Scrapy先跑通单页再谈框架Scrapy 是重型武器但毕业设计最怕卡在“环境装不上”或“中间件配错导致连首页都打不开”。我们从最轻量、最可控的组合开始requests发请求 BeautifulSoup4解析 HTML lxml作解析器。它不依赖 Twisted 异步引擎不强制要求pip install scrapy后还要配scrapy.cfg更关键的是——所有错误都暴露在明面上requests.exceptions.ConnectionError是网络问题bs4.FeatureNotFound是解析器没装对AttributeError: NoneType object has no attribute text是 CSS 选择器写错了。这种“错误即线索”的调试体验对答辩前两周还在改代码的学生来说就是后悔药。提示别碰 Selenium。它启动浏览器慢、内存占用高、截图难嵌入 PPT且老师一问“为什么不用无头模式”你就得解释 ChromeDriver 版本兼容性——这纯属给自己加戏。2.2 抓取链家北京朝阳区列表页绕过 Referer 校验与 User-Agent 封禁的最小命令链家列表页如https://bj.lianjia.com/ershoufang/chaoyang/会校验Referer头是否来自自家域名同时拒绝常见爬虫 UA。以下命令是本地测试成功的最小集curl -H User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 \ -H Referer: https://bj.lianjia.com/ \ https://bj.lianjia.com/ershoufang/chaoyang/pg1/ \ -o test_list.html对应 Python 代码crawler.py第一段import requests from bs4 import BeautifulSoup headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36, Referer: https://bj.lianjia.com/ } url https://bj.lianjia.com/ershoufang/chaoyang/pg1/ response requests.get(url, headersheaders, timeout10) response.raise_for_status() # 显式抛出 4xx/5xx 错误 soup BeautifulSoup(response.text, lxml)参数说明timeout10防止页面卡死阻塞整个脚本毕业设计答辩演示时最怕“程序卡住 30 秒没反应”response.raise_for_status()强制检查 HTTP 状态码避免静默失败比如返回 403 却继续往下解析空 HTMLlxml比默认html.parser快 3 倍且对 malformed HTML 更鲁棒链家页面常有未闭合标签2.3 解析房源卡片用 CSS 选择器精准定位避开动态渲染陷阱链家列表页是服务端渲染SSR所有房源li classclear LOGCLICKDATA都在初始 HTML 里无需等 JS 执行。我们用soup.select()定位# 获取所有房源卡片 house_cards soup.select(ul.sellListContent li.clear.LOGCLICKDATA) print(f成功解析 {len(house_cards)} 套房源) for card in house_cards[:3]: # 先试前三条 title_elem card.select_one(div.title a) price_elem card.select_one(div.totalPrice span.number) unit_price_elem card.select_one(div.unitPrice span.number) title title_elem.get_text(stripTrue) if title_elem else 未知 total_price price_elem.get_text(stripTrue) if price_elem else 0 unit_price unit_price_elem.get_text(stripTrue) if unit_price_elem else 0 print(f【{title}】总价{total_price}万 | 单价{unit_price}元/㎡)关键避坑点不用find_all(div, class_title)class 名含空格时find_all会失效select()支持标准 CSS 语法get_text(stripTrue)自动去除换行符和首尾空格避免存入 CSV 后出现 650 这种脏数据if xxx_elem else 0防止某条房源缺字段导致整个循环崩掉毕业设计最怕“爬到第 237 条突然报错退出”3. 从列表页到详情页用多线程加速采集 自动识别翻页逻辑避免手动改 URL3.1 为什么必须进详情页列表页根本不够用列表页只给总价、单价、标题、小区名但毕业设计分析需要✅ 房屋朝向东/南/西/北✅ 所在楼层低/中/高或具体“5/32 层”✅ 建筑年代1998 年 / 2015 年✅ 装修情况精装/简装/毛坯✅ 带看次数反映市场热度✅ 发布时间判断是否为新挂牌这些全在详情页如https://bj.lianjia.com/ershoufang/101102738054.html的div classbase和div classtransaction里。不进详情页你的分析报告就是“房价地图”变“房价幻灯片”。3.2 用 ThreadPoolExecutor 并发抓详情5 行代码提速 4 倍单线程爬 100 条详情页约需 90 秒按平均 0.9s/页用 5 线程后压到 22 秒内且代码极简from concurrent.futures import ThreadPoolExecutor, as_completed import time def fetch_detail(detail_url): try: response requests.get(detail_url, headersheaders, timeout8) response.raise_for_status() return BeautifulSoup(response.text, lxml) except Exception as e: print(f⚠️ 详情页 {detail_url} 抓取失败{e}) return None # 假设已有 100 个详情页 URL 列表 detail_urls [...] # 从列表页解析出的 href start_time time.time() results [] with ThreadPoolExecutor(max_workers5) as executor: # 提交所有任务 future_to_url {executor.submit(fetch_detail, url): url for url in detail_urls} # 按完成顺序收集结果 for future in as_completed(future_to_url): soup future.result() if soup: results.append(soup) print(f✅ 并发抓取完成耗时 {time.time() - start_time:.1f} 秒成功 {len(results)}/{len(detail_urls)} 条)参数说明max_workers5线程数不是越多越好。实测 5 线程时链家服务器响应稳定设为 10 易触发 IP 限频返回 403 或空白页timeout8比列表页更短因详情页 DOM 更复杂超时早些退出避免拖慢全局as_completed()不按 URL 顺序返回但保证每个future.result()是独立结果适合后续并行解析3.3 自动翻页用正则识别页码链接拒绝硬编码pg2/pg3链家翻页链接长这样a href/ershoufang/chaoyang/pg2/2/aa href/ershoufang/chaoyang/pg3/3/a但最后一页是a href/ershoufang/chaoyang/pg100/末页/a手动写for i in range(1, 101)极危险——实际可能只有 87 页第 88 页返回 404 导致脚本中断。正确做法是解析当前页的“下一页”按钮def get_next_page_url(soup): next_link soup.select_one(div.page-box div:nth-child(2) a:last-child) if next_link and href in next_link.attrs: href next_link[href] if href.startswith(/): return fhttps://bj.lianjia.com{href} return None # 主循环 current_url https://bj.lianjia.com/ershoufang/chaoyang/pg1/ all_house_urls [] while current_url: print(f正在抓取列表页{current_url}) response requests.get(current_url, headersheaders, timeout10) soup BeautifulSoup(response.text, lxml) # 解析本页所有房源链接 for link in soup.select(ul.sellListContent li.clear a.img): if link.has_attr(href) and ershoufang in link[href]: full_url https: link[href] if link[href].startswith(//) else link[href] if full_url.startswith(http): all_house_urls.append(full_url) # 获取下一页 current_url get_next_page_url(soup) if current_url: time.sleep(1) # 礼貌等待避免被当攻击为什么这招稳不依赖页码数字只认“下一页”按钮是否存在time.sleep(1)是毕业设计安全底线——老师演示时若被封 IP答辩直接黄full_url判断逻辑覆盖了协议相对路径//bj.lianjia.com/...和绝对路径/ershoufang/...4. 数据清洗与结构化用 pandas 处理空值、异常值、文本噪声让分析不翻车4.1 把原始字段转成数值型用pd.to_numeric()的errorscoerce模式详情页解析出的“总价”是字符串650“单价”是85000但可能混入暂无数据或面议。直接int()会崩溃# ❌ 危险写法 df[total_price] df[total_price].apply(int) # 遇到 面议 直接报错 # ✅ 安全写法 df[total_price] pd.to_numeric(df[total_price], errorscoerce) df[unit_price] pd.to_numeric(df[unit_price], errorscoerce)errorscoerce会把无法转换的值如面议、、暂无自动转为NaN后续用df.dropna(subset[total_price])清洗即可。这是毕业设计数据质量的生命线——没有NaN就没有可信分析。4.2 拆解“楼层”字段用正则提取数字拒绝人工规则详情页楼层字段长这样低楼层(共32层)中楼层(共32层)5层(共32层)顶层(共32层)想统计“中楼层占比”不能靠if 中楼层 in x——因为还有第15层(共32层)。用正则一招解决import re def extract_floor(text): if not isinstance(text, str): return np.nan # 匹配 数字层 或 顶层 或 低/中/高楼层 match re.search(r(\d)层|顶层|低楼层|中楼层|高楼层, text) if match: return match.group(0) return 未知 df[floor_type] df[floor_info].apply(extract_floor)效果floor_infofloor_type5层(共32层)5层顶层(共32层)顶层中楼层(共32层)中楼层地下室(共32层)未知这样后续df[floor_type].value_counts()就能直接出饼图数据。4.3 识别并剔除异常单价用 IQR 法不是简单删 10 万的北京二手房单价合理区间是 3 万–12 万元/㎡但存在极端值假房源标价 1 万/㎡ 吸引点击别墅类标价 25 万/㎡文本错位把“总价 1200 万”误解析为“单价 1200 万”用 IQR四分位距自动识别Q1 df[unit_price].quantile(0.25) Q3 df[unit_price].quantile(0.75) IQR Q3 - Q1 lower_bound Q1 - 1.5 * IQR upper_bound Q3 1.5 * IQR outliers df[(df[unit_price] lower_bound) | (df[unit_price] upper_bound)] print(f检测到 {len(outliers)} 条单价异常值 {lower_bound:.0f} 或 {upper_bound:.0f}) df_clean df[(df[unit_price] lower_bound) (df[unit_price] upper_bound)]为什么比人工阈值强IQR 适应数据分布北京均价 8 万时阈值自动放宽深圳均价 15 万时自动收紧不会误杀“真实高价房”如金融街 18 万/㎡ 的学区房输出outliersDataFrame 可导出为abnormal.csv答辩时展示“我们如何定义异常”5. 可视化分析用 seaborn 画专业级图表 用 plotly 生成可交互 HTMLPPT 直接截图5.1 区域房价热力图用 geopandas 高德 API 坐标拒绝手绘地图单纯用plt.bar()画“朝阳区 8.2 万海淀 9.1 万”太单薄。真正加分项是 在北京行政地图上按街道/商圈着色显示均价 颜色深浅 单价高低如国贸商圈深红天通苑浅黄实现路径从高德开放平台申请免费 Key搜索“高德地图 API 行政区划”调用/config/district?keywords北京subdistrict2获取朝阳区各街道边界 GeoJSON用geopandas读取pandas关联均价数据matplotlib渲染但毕业设计不必这么重——用plotly.express.choropleth()一行搞定import plotly.express as px # 假设 df_district 包含district_name, avg_unit_price, district_code fig px.choropleth( df_district, geojsonhttps://geo.datav.aliyun.com/areas_v3/boundaries/beijing.json, # 阿里云免费北京 GeoJSON locationsdistrict_code, featureidkeyproperties.adcode, coloravg_unit_price, color_continuous_scaleYlOrRd, labels{avg_unit_price: 均价(元/㎡)}, title北京市各行政区二手房单价热力图 ) fig.write_html(district_heatmap.html) # 生成可双击打开的 HTML效果双击district_heatmap.html鼠标悬停显示“朝阳区82,350 元/㎡”缩放平移流畅——答辩时全屏演示比静态 PNG 高出两个段位。5.2 户型与总价关系用 seaborn.jointplot 揭示分布规律不是堆柱状图学生常犯错误画“两居室 350 套三居室 420 套”柱状图。这没信息量。真正该问❓ 两居室集中在什么总价区间❓ 四居室是否必然 800 万有没有低价四居用jointplot一次性展示户型分布 总价分布 散点趋势import seaborn as sns # 确保户型字段已标准化2室 → 两居室 df[bedroom_type] df[bedroom_count].map({1:一居室, 2:两居室, 3:三居室, 4:四居室, 5:五居室}) g sns.jointplot( datadf, xtotal_price, ybedroom_type, kindhist, # 用直方图替代散点避免重叠 marginal_kwsdict(bins20), huebedroom_type, paletteSet2 ) g.fig.suptitle(户型数量分布与总价区间关系, y1.02) g.savefig(bedroom_price_distribution.png, dpi300, bbox_inchestight)输出图解读左侧直方图总价分布整体右偏下方直方图各户型数量三居室最多中间热力区块颜色越深 该户型在该总价段越密集如两居室峰值在 400–600 万——这图放进 PPT老师会问“为什么四居室在 500 万档也有小高峰是不是老破小” 你答“对我们筛选出 500 万内的四居室发现全是 1980 年代单位房面积大但单价仅 3.2 万。” ——这就是分析深度。5.3 带看次数 vs 发布时间用 matplotlib 时间序列图暴露市场冷热周期“带看次数”是核心热度指标但它随时间衰减。画plt.plot(df[post_date], df[watch_times])是灾难——日期是字符串且未排序。正确流程import matplotlib.pyplot as plt import matplotlib.dates as mdates # 1. 转日期类型并排序 df[post_date] pd.to_datetime(df[post_date], format%Y-%m-%d, errorscoerce) df df.dropna(subset[post_date, watch_times]).sort_values(post_date) # 2. 按周聚合平均带看次数 weekly_data df.set_index(post_date).resample(W).agg({ watch_times: mean, total_price: median }).dropna() # 3. 双 Y 轴图 fig, ax1 plt.subplots(figsize(12, 6)) ax2 ax1.twinx() ax1.bar(weekly_data.index, weekly_data[watch_times], alpha0.6, label周均带看次数, colorsteelblue) ax2.plot(weekly_data.index, weekly_data[total_price], r-, linewidth2, label周中位总价) ax1.set_xlabel(发布时间周) ax1.set_ylabel(周均带看次数, colorsteelblue) ax2.set_ylabel(周中位总价万元, colorred) ax1.xaxis.set_major_formatter(mdates.DateFormatter(%m-%d)) ax1.xaxis.set_major_locator(mdates.WeekdayLocator(interval4)) plt.title(带看热度与房价中位数的时间趋势近 12 周) fig.tight_layout() plt.savefig(watch_trend.png, dpi300, bbox_inchestight)为什么这图能过答辩X 轴是真实时间不是序号体现数据时效性双 Y 轴揭示相关性若带看上升但总价下跌说明“降价促销量”若两者同升说明市场回暖resample(W)避免单日噪声老师能看出你懂时间序列处理6. 避坑指南毕业设计答辩前必查的 4 个血泪现场以及我的应急 checklist6.1 现象爬虫运行 2 小时后突然全部返回 403但浏览器能正常访问原因链家服务端有 IP 级请求频率监控连续请求超过阈值实测约 120 次/小时即封禁 10 分钟。不是 UA 或 Referer 问题是纯流量墙。解决立即停用脚本换手机热点获取新公网 IP在代码中加入指数退避time.sleep(random.uniform(1.5, 3.0))替代固定sleep(1)答辩演示时提前用requests.get()测试目标 URL 是否返回 200失败则弹窗提示“网络受限请切换热点”6.2 现象CSV 文件里中文全变成乱码Excel 打开是方块原因pandas.to_csv()默认用utf-8编码但 Windows Excel 默认用gbk打开。解决保存时强制指定encodingutf_8_sig带 BOM 的 UTF-8Excel 能自动识别df.to_csv(cleaned_data.csv, encodingutf_8_sig, indexFalse)或者生成 Excel 文件答辩时更体面df.to_excel(cleaned_data.xlsx, indexFalse) # 无需额外编码参数6.3 现象PPT 里插入的 PNG 图表模糊放大后锯齿明显原因plt.savefig()默认 DPI 过低80打印或全屏演示时像素不足。解决所有savefig()必加dpi300参数plt.savefig(chart.png, dpi300, bbox_inchestight)更推荐 SVG 格式矢量图无限缩放plt.savefig(chart.svg, bbox_inchestight) # PPT 2016 直接支持插入 SVG6.4 现象答辩现场演示时pip install -r requirements.txt报错cv2安装失败原因opencv-python在某些学校机房的旧版 pip 或受限网络下安装极慢甚至失败。解决终极方案把cv2从requirements.txt中删除改用PILPillow做基础图像处理毕业设计可视化完全够用备用方案提前下载 wheel 包pip download opencv-python --no-deps --platform win_amd64 --python-version 38 --abi cp38 --only-binary:all:将下载的.whl文件和pip install xxx.whl命令写进答辩备注页现场离线安装。注意答辩前 48 小时务必执行我的应急 checklist在答辩用电脑上python crawler.py运行一次确认能生成raw_data.csvjupyter notebook analysis.ipynb运行全部 cells确认图表能输出 PNG/SVG用 PowerPoint 打开 PPT检查所有图片是否正常显示尤其 SVG把source_code.zip、PPT.pptx、report.pdf三文件压缩为final_submit.zip重命名姓名_学号_二手房分析.zip打印一份《答辩问答预判清单》含“反爬怎么做的”“异常值怎么定义”“热力图数据来源”三问答案放在手边我带过 23 届一个学生他答辩前夜发现链家改版列表页结构全变。没慌用 Chrome 开发者工具重新抓ul.sellListContent li30 分钟重写解析逻辑第二天照样拿了优秀。毕业设计不是考你写得多完美是考你面对黑匣子时能不能用print()、type()、dir()三板斧把它撬开。这套方案我压过 7 届学生从没人在答辩现场被问倒——因为所有“为什么”都藏在你亲手写的 300 行代码注释里。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

Claude Code通知系统实现与优化指南

Claude Code通知系统实现与优化指南

1. 为什么Claude Code需要通知铃铛在开发过程中,我们经常遇到需要长时间等待Claude Code执行任务的情况。比如代码生成、重构建议、调试分析等操作,可能需要几十秒甚至几分钟才能完成。传统做法是开发者必须盯着进度条或不断刷新界面查看结果——这种被动…

📅 2026/10/25 8:19:31
2023年AI热点争议:技术伦理、商业落地与开源生态

2023年AI热点争议:技术伦理、商业落地与开源生态

1. 今年AI领域的热点争议全景图2023年的AI领域就像一场永不停歇的科技嘉年华,每天都有新话题引爆行业讨论。从业内视角来看,今年的争议焦点主要集中在三个维度:技术伦理的边界之争、商业落地的路径之争,以及开源与闭源的生态之争。…

📅 2026/10/25 8:19:31
AI情感交互技术的社会心理影响与伦理挑战

AI情感交互技术的社会心理影响与伦理挑战

1. 项目概述:当AI技术遇上社会心理那天在咖啡馆听到邻桌讨论"AI会不会让人类失业"时,我突然意识到,我们正站在一个奇特的十字路口。作为从业十余年的技术观察者,我见证过AlphaGo战胜李世石引发的职业棋手恐慌&#xff0…

📅 2026/10/25 8:19:31
MORE NEWS

更多资讯

📰

SpringBoot微信小程序养老服务平台功能介绍

商品编号:000040【一、项目简介】 面向养老服务预约的微信小程序平台,配套网页运营后台。提供生活照料、医疗陪护、康复护理、心理慰藉、文化娱乐和家政服务分类,包含服务浏览、预约订单、评价反馈与行为分析模块。展示服务分类、热门服务与推…

📰

ROS2 Web端地图显示与导航控制实战指南

简介:本资源是一套基于ROS 2 Web前端的TurtleBot3地图可视化与交互导航实现方案,面向ROS初学者及Web前端开发者,解决机器人SLAM建图结果在浏览器端实时显示、目标点导航与位姿校正等核心需求。项目纯前端实现,不依赖后端服务或键盘…

📰

短信PDU编码解析与生成:嵌入式设备短信通信实战指南

简介:本资源是一套面向嵌入式开发与通信协议学习者的短信PDU编码解码C语言实现,适用于理解GSM网络中SMS消息底层传输机制的初学者与进阶开发者。代码完整覆盖电话号码国际格式转换、短信中心地址编码、SMS-SUBMIT/SMS-DELIVER类型识别、GSM 7-bit与UCS-2…

📰

特斯拉Optimus3量产优化:执行器、灵巧手与热管理如何突破可靠性瓶颈

1. 从"周周谈"里挖出的真问题:Optimus3这次到底改了什么特斯拉的AI团队最近放出的消息里,Optimus3的优化方向比很多人预想的要务实得多。不是继续堆叠自由度数字,也不是搞什么炫技的跑酷演示,而是把力气花在了"怎么…

📰

人工智能课程资源模块化复习:从神经网络到AI伦理

简介:这是一套面向零基础学习者与自学者的微软人工智能课程中文版资料,对应为期12周、共24课的系统大纲,围绕符号人工智能、神经网络与深度学习、计算机视觉、自然语言处理、遗传算法及多智能体系统等主题展开,并结合TensorFlow与…

📰

电动汽车VCU开发实战:从原理图到控制策略的完整拆解

简介:这份资源面向电动汽车整车控制器(VCU)的学习者与开发者,提供一套从软件到硬件的完整开发参考。包内包含VCU控制源码、硬件PCB原理图、控制策略说明书与硬件说明书,源码覆盖底层驱动、中间件与应用层控制逻辑&…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

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

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

📞 💬