当前位置: 首页 > news >正文

重庆市二手房价格数据分析与可视化系统

重庆市二手房价格数据分析与可视化系统 - 技术教学文档

项目地址: https://github.com/NewDay412/MetroHouseLab

第一章:项目架构设计

1.1 整体架构

本项目采用模块化设计,分为以下几个核心模块:

┌─────────────────────────────────────────────────────────────┐ │ 用户界面层 (Web) │ │ Flask + ECharts + HTML/CSS/JS │ ├─────────────────────────────────────────────────────────────┤ │ 业务逻辑层 │ │ 数据爬取 | 数据清洗 | 数据分析 | 增量更新 │ ├─────────────────────────────────────────────────────────────┤ │ 数据存储层 │ │ CSV 文件 | MongoDB 数据库 │ ├─────────────────────────────────────────────────────────────┤ │ 外部数据源 │ │ 安居客 | 链家 (API/HTML) │ └─────────────────────────────────────────────────────────────┘

1.2 模块职责划分

模块职责核心技术
spiders数据采集Selenium、requests、BeautifulSoup
data_cleaning数据清洗pandas、正则表达式
data_mining数据分析scikit-learn(K-Means、线性回归)
storage数据存储CSV、MongoDB
web可视化展示Flask、ECharts

第二章:爬虫技术实现

2.1 爬虫架构设计

# 爬虫基类设计原则classBaseSpider:def__init__(self):self.headers=self._build_headers()self.session=self._create_session()self.storage=CSVStorage()def_build_headers(self):"""构建请求头,模拟浏览器"""return{'User-Agent':self.ua.random,'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language':'zh-CN,zh;q=0.9,en;q=0.8','Accept-Encoding':'gzip, deflate, br','Connection':'keep-alive','Cache-Control':'max-age=0',}

2.2 Selenium 反爬绕过技术

2.2.1 隐藏 WebDriver 特征
# 关键配置:隐藏自动化特征chrome_options.add_argument('--disable-blink-features=AutomationControlled')chrome_options.add_experimental_option('excludeSwitches',['enable-automation'])chrome_options.add_experimental_option('useAutomationExtension',False)# CDP 命令注入,彻底隐藏 webdriver 属性driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument',{'source':''' Object.defineProperty(navigator, 'webdriver', { get: () => undefined }); Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] }); Object.defineProperty(navigator, 'languages', { get: () => ['zh-CN', 'zh', 'en'] }); '''})
2.2.2 模拟人类行为
defsimulate_human(self):"""模拟人类行为,降低被识别风险"""# 随机滚动for_inrange(random.randint(2,4)):scroll_amount=random.uniform(100,300)self.driver.execute_script(f'window.scrollBy(0,{scroll_amount})')self.random_delay(0.3,0.8)# 随机鼠标移动action=ActionChains(self.driver)for_inrange(random.randint(2,3)):x=random.randint(100,800)y=random.randint(100,600)action.move_by_offset(x,y).pause(random.uniform(0.1,0.3))action.perform()

2.3 反爬检测与处理

defis_blocked(self):"""检测是否被反爬拦截"""page_source=self.driver.page_source.lower()# 网易易盾验证码检测if'yidun'inpage_sourceor'captcha-wy'inpage_source:returnTrue# 通用验证码检测if'请验证您是真人'inpage_sourceor'人机验证'inpage_source:returnTrue# 反垃圾检测if'antispam'inpage_sourceor'captcha'inpage_source:returnTruereturnFalse

2.4 数据解析技术

defparse_anjuke(self,html,district):"""解析安居客页面数据"""soup=BeautifulSoup(html,'lxml')# 多重选择器策略,应对页面结构变化items=soup.select('.property-ex')orsoup.select('.list-item')orsoup.select('[class*="property"]')foriteminitems:# 价格解析(核心逻辑)price_total_text=item.select_one('.property-price-total').get_text(strip=True)price_avg_text=item.select_one('.property-price-average').get_text(strip=True)# 正则提取数字total_price=float(re.search(r'(\d+(?:\.\d+)?)',price_total_text).group(1))# 单价解析(从元转换为元/㎡)unit_price_val=float(re.search(r'(\d+)',price_avg_text).group(1))# 面积解析area_match=re.search(r'(\d+(?:\.\d+)?)㎡',info_text)area=float(area_match.group(1))ifarea_matchelse0# 备用计算:通过总价和面积反推单价ifunit_price_val==0andtotal_price>0andarea>0:unit_price_val=round(total_price*10000/area,0)

第三章:数据清洗技术

3.1 数据清洗流程

原始数据 → 缺失值处理 → 去重 → 异常值检测 → 格式转换 → 特征提取 → 清洗后数据

3.2 核心清洗逻辑

classDataCleaner:defclean(self):"""数据清洗主流程"""# 1. 加载原始数据df=self.load_raw_data()# 2. 去重df=df.drop_duplicates(subset=['title','district','total_price','area'])# 3. 缺失值处理df=df.dropna(subset=['title','total_price','area'])df['unit_price']=df['unit_price'].fillna(0)# 4. 异常值过滤df=df[(df['total_price']>0)&(df['total_price']<10000)]df=df[(df['area']>20)&(df['area']<500)]# 5. 计算缺失的单价mask=(df['unit_price']==0)&(df['total_price']>0)&(df['area']>0)df.loc[mask,'unit_price']=round(df.loc[mask,'total_price']*10000/df.loc[mask,'area'],0)returndf

第四章:数据挖掘算法

4.1 K-Means 聚类分析

4.1.1 算法原理

K-Means 是一种无监督学习算法,用于将数据划分为 K 个簇。算法步骤:

  1. 随机选择 K 个初始质心
  2. 计算每个样本到质心的距离,分配到最近的簇
  3. 更新每个簇的质心(取平均值)
  4. 重复步骤 2-3,直到质心稳定
4.1.2 代码实现
defclustering_analysis(self,n_clusters=5):"""K-Means 聚类分析"""# 特征选择与标准化features=self.df[['unit_price','area','total_price']].dropna()scaler=StandardScaler()scaled_features=scaler.fit_transform(features)# K-Means 聚类kmeans=KMeans(n_clusters=n_clusters,random_state=42)labels=kmeans.fit_predict(scaled_features)# 统计每个簇的特征cluster_stats=[]foriinrange(n_clusters):cluster_data=features[labels==i]cluster_stats.append({'cluster':i,'count':len(cluster_data),'avg_unit_price':round(cluster_data['unit_price'].mean(),2),'avg_area':round(cluster_data['area'].mean(),2),'avg_total_price':round(cluster_data['total_price'].mean(),2)})returncluster_stats

4.2 线性回归分析

4.2.1 算法原理

线性回归用于建立自变量与因变量之间的线性关系:

y = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ

评估指标:

  • MSE(均方误差):衡量预测值与真实值的平均偏差
  • R²(决定系数):衡量模型解释方差的能力(0-1)
4.2.2 代码实现
defregression_analysis(self):"""线性回归分析"""# 特征与目标变量X=self.df[['area','unit_price']].dropna()y=self.df.loc[X.index,'total_price']# 数据分割X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=42)# 训练模型model=LinearRegression()model.fit(X_train,y_train)# 预测与评估y_pred=model.predict(X_test)mse=mean_squared_error(y_test,y_pred)r2=r2_score(y_test,y_pred)return{'coefficients':{'area':model.coef_[0],'unit_price':model.coef_[1]},'r2':r2,'mse':mse}

第五章:数据可视化技术

5.1 后端 API 设计

@app.route('/api/data/district')defget_district_data():"""获取区县房价数据"""analyzer=DataAnalyzer()analyzer.use_csv=Trueresult=analyzer.district_analysis()returnjsonify({'status':'success','data':result})@app.route('/api/data/clustering')defget_clustering():"""获取聚类分析数据"""analyzer=DataAnalyzer()analyzer.use_csv=Trueresult=analyzer.clustering_analysis()returnjsonify({'status':'success','data':result})

5.2 前端 ECharts 集成

// 区县房价对比柱状图functioninitDistrictChart(){fetch('/api/data/district').then(res=>res.json()).then(data=>{constdistricts=data.data.map(item=>item.district);constprices=data.data.map(item=>item.平均单价);constchart=echarts.init(document.getElementById('districtChart'));chart.setOption({title:{text:'各区县二手房平均单价'},xAxis:{type:'category',data:districts},yAxis:{type:'value',name:'单价(元/㎡)'},series:[{type:'bar',data:prices,itemStyle:{color:newecharts.graphic.LinearGradient(0,0,0,1,[{offset:0,color:'#83bff6'},{offset:0.5,color:'#188df0'},{offset:1,color:'#188df0'}])}}]});});}

第六章:增量更新机制

6.1 增量更新策略

classIncrementalUpdater:defupdate(self):"""增量更新主流程"""# 1. 获取上次更新时间last_update_time=self.get_last_update_time()# 2. 爬取新数据(只获取更新时间之后的)new_data=self.crawl_new_data(since=last_update_time)# 3. 去重(与已有数据对比)unique_data=self.remove_duplicates(new_data)# 4. 保存新数据self.save_new_data(unique_data)# 5. 更新时间戳self.update_last_update_time()return{'updated_count':len(unique_data)}

第七章:性能优化技巧

7.1 多线程爬取

fromconcurrent.futuresimportThreadPoolExecutor,as_completeddefcrawl_district(self,district,url):"""爬取单个区县数据"""data_list=[]forpageinrange(1,51):page_url=f"{url}p{page}/"html=self.fetch_page(page_url)data=self.parse_anjuke(html,district)data_list.extend(data)returndata_listdefcrawl_with_threads(self):"""多线程爬取"""withThreadPoolExecutor(max_workers=4)asexecutor:futures=[]fordistrict,urlinself.district_urls.items():future=executor.submit(self.crawl_district,district,url)futures.append(future)forfutureinas_completed(futures):data_list=future.result()self.storage.insert_many(data_list)

7.2 请求缓存与重试

@retry(stop=stop_after_attempt(3),wait=wait_exponential(multiplier=1,min=2,max=10))deffetch_page(self,url):"""带重试机制的页面请求"""response=self.session.get(url,headers=self.headers,timeout=30)response.raise_for_status()returnresponse.text

第八章:常见问题与解决方案

8.1 反爬拦截问题

问题原因解决方案
验证码页面频繁请求被识别使用浏览器模式,人工验证
IP 封禁单 IP 请求过多使用代理 IP 池
Cookie 失效会话过期定期更新 Cookie

8.2 数据解析问题

问题原因解决方案
价格为 0选择器失效多重选择器策略
页面结构变化网站更新动态选择器适配
中文乱码编码不一致指定 UTF-8 编码

8.3 性能问题

问题原因解决方案
爬取速度慢单线程串行多线程/异步爬取
内存溢出数据量大分批处理、流式存储
存储慢频繁 IO批量写入、缓存机制

第九章:扩展建议

9.1 增加更多数据源

  • 贝壳网(Ke.com)
  • 58 同城
  • 房天下

9.2 增强反爬能力

  • 代理 IP 池
  • 浏览器指纹随机化
  • 分布式爬取架构

9.3 深入数据分析

  • 时间序列分析(房价趋势)
  • 地理空间分析(热力图)
  • 文本挖掘(房源描述分析)

9.4 部署优化

  • Docker 容器化
  • 云服务器部署
  • 定时任务自动执行

附录:技术栈版本说明

技术版本用途
Python3.13+编程语言
Flask2.2.5Web 框架
Selenium4.18.1浏览器自动化
BeautifulSoup4.12.2HTML 解析
pandas2.1.4数据处理
numpy1.26.3数值计算
scikit-learn1.3.2机器学习
ECharts5.4.3数据可视化
MongoDB6.0+数据库存储

文档版本: v1.0
创建时间: 2026-07-01
适用场景: 学年设计、课程设计、毕业设计

http://www.gsyq.cn/news/1618305.html

相关文章:

  • 墨香情手游官方下载:2026 国风武侠手游优选正版高速官方下载通道
  • .NET与AI Agent深度集成开发实战
  • 2026年国内热门工艺品设计资讯平台推荐,这份排行榜别错过!
  • 既需要大规模HPC 集群,有需要QPU参与的计算问题
  • 企业 AI 安全防护实战:Prompt Injection、RAG Injection 与 Agent 工具越权排查清单
  • 热榜来袭!外贸工艺品资讯平台哪家强?口碑排行榜揭秘
  • 记录一个免杀的php webshell demo
  • [Remap节点]原理解析与实际应用
  • 数据库SQL查询语句学习心得
  • 用 Python 画三类论文级图表:分组柱状图、双轴折线图与多面板图(解决中文乱码)
  • NFD云解析插件扩展架构深度解析:从接口设计到实战实现
  • 在微服务中使用领域事件
  • 如何快速修复ClusterGVis中箱线图与折线图显示冲突问题
  • 心情值游戏系统实现
  • 【MO三维路径规划】麝牛算法MO多无人机协同集群避障路径规划(目标函数:最低成本:路径、高度、威胁、转角)【含Matlab源码 15684期】
  • [特殊字符] 搬砖的秘密:为什么一次搬 64 块砖最快?
  • 本地化AI漫剧制作:Qwen与ComfyUI实战指南
  • 一个老股民的十年自白十年炒股没亏,但我劝你别学我
  • Rust项目开发完整教程
  • 车间地坪养护秘籍
  • MAX9744与PIC18LF45K50的音频功率放大系统设计
  • 出现“WSL 安装似乎已损坏”的错误通常意味着Windows子系统对于Linux(WSL)的某些组件可能未正确安装或注册。要解决这个问题,你可以尝试以
  • 【新品发布】AI PC快充防护再进阶!艾为电子推出Type‑C OVP系列产品
  • Harness Engineering 实践案例:如何Agent 写一份行为规范
  • Docker网络配置详解
  • Rust模块管理最佳实践
  • 16266350800----wLa6twBAf4yVW4gw----dc_sid=b6eb97905a1c240e1675f230d913b6b5;HMACCOUNT=97C7CB558BC7424
  • 智能体设计范式:Plan-and-Solve
  • C++ 纳秒级交易系统设计
  • 毕业设计项目 基于深度学习的驾驶行为检测(玩手机)