网站做招聘需要什么资质,布吉做棋牌网站建设哪家技术好,凡客诚品官方网站,winserver安装Wordpress摘要
本文设计并实现了一个基于 Python 的二手房源信息爬取与分析系统。该系统通过网络爬虫技术自动从房地产网站获取二手房源信息#xff0c;经过数据清洗、存储后进行多维度分析#xff0c;并通过可视化界面展示分析结果。系统采用模块化设计#xff0c;包括爬虫模块、数…摘要
本文设计并实现了一个基于 Python 的二手房源信息爬取与分析系统。该系统通过网络爬虫技术自动从房地产网站获取二手房源信息经过数据清洗、存储后进行多维度分析并通过可视化界面展示分析结果。系统采用模块化设计包括爬虫模块、数据处理模块、存储模块、分析模块和展示模块。实验结果表明该系统能够有效收集和分析二手房市场数据为购房者、卖房者和房地产从业者提供决策支持。
1 引言
1.1 研究背景与意义
随着房地产市场的不断发展二手房交易在整个房地产市场中所占的比重越来越大。对于购房者来说了解市场行情、比较不同房源的价格和特点是做出明智决策的关键对于卖房者来说掌握市场动态、合理定价是成功交易的前提对于房地产从业者来说深入分析市场数据、把握市场趋势是提供专业服务的基础。 然而目前房地产市场信息分散在各个网站购房者、卖房者和房地产从业者需要花费大量的时间和精力去收集和整理这些信息。此外由于信息不透明和不对称市场上存在着价格虚高、虚假房源等问题给消费者带来了很大的困扰。 因此开发一个能够自动收集、整理和分析二手房源信息的系统具有重要的现实意义。该系统可以帮助用户快速获取全面、准确的市场信息提高决策效率和准确性可以促进市场信息的透明化和对称化减少市场乱象可以为房地产研究提供数据支持推动房地产市场的健康发展。
1.2 国内外研究现状
1.2.1 网络爬虫技术研究现状
网络爬虫是一种自动获取网页内容的程序它可以按照一定的规则自动地抓取万维网上的信息。网络爬虫技术的研究始于 20 世纪 90 年代经过多年的发展已经取得了很大的进展。目前网络爬虫技术主要应用于搜索引擎、数据挖掘、信息检索等领域。 在房地产领域网络爬虫技术也得到了广泛的应用。例如一些房地产网站利用网络爬虫技术收集其他网站的房源信息以扩大自己的房源数据库一些房地产研究机构利用网络爬虫技术收集房地产市场数据以进行市场分析和预测。
1.2.2 房地产数据分析研究现状
房地产数据分析是指利用统计学、机器学习等方法对房地产市场数据进行分析和挖掘以发现市场规律、预测市场趋势。房地产数据分析技术的研究始于 20 世纪 70 年代经过多年的发展已经取得了很大的进展。目前房地产数据分析技术主要应用于市场分析、价格预测、投资决策等领域。 在房地产数据分析方面国内外学者已经开展了大量的研究工作。例如一些学者利用时间序列分析、回归分析等方法对房价走势进行预测一些学者利用聚类分析、关联规则挖掘等方法对房地产市场进行细分和分析一些学者利用空间分析、地理信息系统等方法对房地产市场进行空间分析和可视化。
1.2.3 现有系统存在的问题
虽然国内外已经开发了一些房地产信息系统但这些系统仍然存在一些问题 数据获取不全面大多数系统只能获取部分网站的房源信息无法获取整个市场的信息。数据质量不高由于网络爬虫技术的局限性获取的房源信息可能存在噪声、缺失值等问题。分析功能单一大多数系统只能提供简单的统计分析功能无法进行深入的数据分析和挖掘。可视化效果不佳大多数系统的可视化效果较差无法直观地展示分析结果。用户体验不好大多数系统的界面设计不够友好操作不够便捷用户体验较差。
1.3 研究内容与目标
1.3.1 研究内容
本论文的研究内容主要包括以下几个方面 二手房源信息爬取技术研究研究如何从房地产网站自动获取二手房源信息包括网页解析、数据提取、反爬虫策略等。二手房源信息处理技术研究研究如何对爬取的房源信息进行清洗、去重、标准化等处理提高数据质量。二手房源信息存储技术研究研究如何设计数据库结构将处理后的房源信息存储到数据库中方便后续查询和分析。二手房源信息分析技术研究研究如何对存储的房源信息进行多维度分析包括价格分析、区域分析、户型分析、面积分析等。二手房源信息可视化技术研究研究如何将分析结果以图表、地图等形式直观地展示出来提高用户体验。系统架构设计与实现研究如何设计系统架构将各个模块有机地结合起来实现一个完整的二手房源信息爬取与分析系统。
1.3.2 研究目标
本论文的研究目标是开发一个基于 Python 的二手房源信息爬取与分析系统该系统应具有以下特点 数据获取全面能够从多个房地产网站自动获取二手房源信息覆盖整个市场。数据质量高能够对爬取的房源信息进行清洗、去重、标准化等处理提高数据质量。分析功能丰富能够对存储的房源信息进行多维度分析包括价格分析、区域分析、户型分析、面积分析等。可视化效果好能够将分析结果以图表、地图等形式直观地展示出来提高用户体验。用户体验好界面设计友好操作便捷用户体验好。系统稳定可靠系统运行稳定可靠能够满足大规模数据处理和分析的需求。
2 相关技术与理论基础
2.1 Python 编程语言
Python 是一种高级、解释型、通用编程语言具有以下特点 语法简洁Python 的语法简洁明了代码可读性高开发效率高。丰富的库支持Python 拥有丰富的第三方库如 Scrapy、BeautifulSoup、Pandas、NumPy、Matplotlib、Seaborn 等这些库可以大大简化开发工作。跨平台Python 可以在 Windows、Linux、Mac OS 等多种操作系统上运行。开源免费Python 是开源免费的用户可以自由使用、修改和分发。 在本系统中Python 主要用于开发网络爬虫、数据处理、数据分析和可视化等模块。
2.2 网络爬虫技术
网络爬虫是一种自动获取网页内容的程序它可以按照一定的规则自动地抓取万维网上的信息。网络爬虫技术主要包括以下几个方面 网页下载从互联网上下载网页内容。网页解析解析网页内容提取有用信息。数据存储将提取的信息存储到数据库中。反爬虫策略应对网站的反爬虫机制保证爬虫的正常运行。 在本系统中使用 Python 的 Scrapy 框架开发网络爬虫Scrapy 是一个为了爬取网站数据、提取结构性数据而编写的应用框架它可以应用在数据挖掘、信息处理或存储历史数据等一系列的程序中。
2.3 数据处理技术
数据处理是指对原始数据进行清洗、转换、整合等操作以提高数据质量和可用性的过程。数据处理技术主要包括以下几个方面 数据清洗去除数据中的噪声、缺失值、重复值等。数据转换将数据从一种格式转换为另一种格式如将文本数据转换为数值数据。数据整合将来自不同数据源的数据整合到一起。数据标准化将数据按照一定的标准进行规范化如将数据进行归一化处理。 在本系统中使用 Python 的 Pandas 库进行数据处理Pandas 是一个开源的 Python 数据分析库它提供了高效、灵活的数据结构和数据分析工具可以帮助用户快速处理和分析大量数据。
2.4 数据分析技术
数据分析是指利用统计学、机器学习等方法对数据进行分析和挖掘以发现数据中隐藏的模式和规律的过程。数据分析技术主要包括以下几个方面 描述性统计分析对数据的基本特征进行描述如均值、中位数、标准差等。相关性分析分析变量之间的相关性如皮尔逊相关系数、斯皮尔曼相关系数等。回归分析建立变量之间的回归模型如线性回归、逻辑回归等。聚类分析将数据按照相似性进行分组如 K-means 聚类、层次聚类等。分类分析将数据按照一定的规则进行分类如决策树、支持向量机等。 在本系统中使用 Python 的 NumPy、SciPy 等库进行数据分析NumPy 是一个开源的 Python 科学计算库它提供了高效的多维数组对象和计算工具SciPy 是一个基于 NumPy 的科学计算库它提供了许多科学计算算法和工具。
2.5 数据可视化技术
数据可视化是指将数据以图表、地图等形式直观地展示出来以帮助用户更好地理解和分析数据的过程。数据可视化技术主要包括以下几个方面 图表可视化将数据以柱状图、折线图、饼图等形式展示出来。地图可视化将数据以地图的形式展示出来如热力图、气泡图等。交互式可视化提供交互式界面让用户可以自由地探索和分析数据。 在本系统中使用 Python 的 Matplotlib、Seaborn、Plotly 等库进行数据可视化Matplotlib 是一个开源的 Python 绘图库它提供了丰富的绘图功能Seaborn 是一个基于 Matplotlib 的统计数据可视化库它提供了更高级的绘图功能Plotly 是一个交互式数据可视化库它提供了丰富的交互式绘图功能。
2.6 数据库技术
数据库是指按照一定的数据模型组织、存储和管理数据的仓库。数据库技术主要包括以下几个方面 关系型数据库以关系模型为基础的数据库如 MySQL、Oracle、SQL Server 等。非关系型数据库不以关系模型为基础的数据库如 MongoDB、Redis 等。数据库设计设计数据库的结构和关系包括表结构、字段类型、索引等。数据库操作对数据库进行增删改查等操作。 在本系统中使用 MySQL 作为数据库MySQL 是一个开源的关系型数据库管理系统它具有高性能、可靠性和易用性等特点。
3 系统需求分析
3.1 功能需求
3.1.1 数据爬取模块
支持多网站爬取能够从多个房地产网站爬取二手房源信息。定时爬取支持定时自动爬取确保数据的及时性和准确性。增量爬取只爬取新的或更新的房源信息避免重复爬取。反爬虫策略能够应对网站的反爬虫机制如 IP 代理、User-Agent 轮换等。爬取进度监控能够监控爬取进度及时发现和处理爬取过程中出现的问题。
3.1.2 数据处理模块
数据清洗去除爬取数据中的噪声、缺失值、重复值等。数据转换将爬取数据转换为统一的格式便于后续处理和分析。数据标准化对数据进行标准化处理如将价格、面积等数据进行归一化处理。数据验证验证数据的有效性和合法性如验证价格、面积等数据是否在合理范围内。数据存储将处理后的数据存储到数据库中。
3.1.3 数据分析模块
价格分析分析不同区域、不同户型、不同面积的房价走势和分布情况。区域分析分析不同区域的房源数量、价格水平、供需关系等。户型分析分析不同户型的房源数量、价格水平、受欢迎程度等。面积分析分析不同面积段的房源数量、价格水平、供需关系等。趋势预测基于历史数据预测房价走势和市场趋势。相关性分析分析房价与区域、户型、面积等因素之间的相关性。
3.1.4 数据可视化模块
图表可视化将分析结果以柱状图、折线图、饼图等形式展示出来。地图可视化将房源信息以地图的形式展示出来支持按区域、价格等条件进行筛选。交互式可视化提供交互式界面让用户可以自由地探索和分析数据。报表生成支持生成分析报表如 PDF、Excel 等格式。
3.1.5 用户管理模块
用户注册与登录支持用户注册和登录系统。用户权限管理支持不同角色的用户拥有不同的权限。用户收藏管理支持用户收藏感兴趣的房源信息。用户分析报告支持为用户生成个性化的分析报告。
3.1.6 系统管理模块
爬虫配置管理支持配置爬虫的参数如爬取频率、爬取范围等。数据备份与恢复支持定期备份数据并在需要时恢复数据。系统日志管理记录系统的运行日志便于排查问题。系统监控监控系统的运行状态如 CPU 使用率、内存使用率等。
3.2 非功能需求
3.2.1 性能需求
响应时间系统的平均响应时间应不超过 3 秒最大响应时间应不超过 10 秒。并发用户数系统应支持至少 100 个并发用户同时访问。数据处理能力系统应能够处理每天至少 10 万条房源信息的爬取和处理。数据分析效率系统应能够在 5 分钟内完成对 100 万条房源信息的分析。
3.2.2 可靠性需求
系统可用性系统的可用性应不低于 99.9%。数据完整性系统应保证数据的完整性避免数据丢失或损坏。容错能力系统应具备一定的容错能力能够处理异常情况。恢复能力系统应具备快速恢复能力在发生故障后能够尽快恢复正常运行。
3.2.3 安全性需求
数据安全系统应保证数据的安全性避免数据泄露。用户认证系统应提供用户认证机制确保只有授权用户才能访问系统。权限控制系统应提供权限控制机制确保用户只能访问其权限范围内的资源。数据加密系统应对敏感数据进行加密处理如用户密码、支付信息等。
3.2.4 易用性需求
界面友好系统的界面应简洁、美观、易用符合用户的使用习惯。操作简单系统的操作应简单、直观用户无需过多的培训即可上手使用。帮助文档系统应提供详细的帮助文档帮助用户解决使用过程中遇到的问题。反馈机制系统应提供反馈机制及时响应用户的意见和建议。
3.2.5 可扩展性需求
模块扩展系统应支持模块扩展能够方便地添加新的功能模块。数据扩展系统应支持数据扩展能够方便地处理新的数据源和数据类型。性能扩展系统应支持性能扩展能够通过增加硬件资源来提高系统的性能。
4 系统设计
4.1 总体架构设计
系统采用分层架构设计主要包括以下几层 系统的核心模块包括 数据爬取模块负责从房地产网站爬取二手房源信息。数据处理模块负责对爬取的房源信息进行清洗、转换、标准化等处理。数据分析模块负责对处理后的房源信息进行多维度分析。数据可视化模块负责将分析结果以图表、地图等形式直观地展示出来。用户管理模块负责用户的注册、登录、权限管理等。系统管理模块负责系统的配置、监控、备份等管理工作。
4.2 数据库设计
4.2.1 数据库表结构
房源信息表 (house_info) sql
CREATE TABLE house_info (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 房源ID,house_code varchar(50) NOT NULL COMMENT 房源编码,title varchar(255) NOT NULL COMMENT 房源标题,price decimal(10,2) NOT NULL COMMENT 价格(万元),unit_price int(11) DEFAULT NULL COMMENT 单价(元/平方米),area decimal(10,2) DEFAULT NULL COMMENT 面积(平方米),house_type varchar(50) DEFAULT NULL COMMENT 户型,floor varchar(50) DEFAULT NULL COMMENT 楼层,build_year varchar(20) DEFAULT NULL COMMENT 建造年份,orientation varchar(20) DEFAULT NULL COMMENT 朝向,decoration varchar(20) DEFAULT NULL COMMENT 装修情况,community varchar(100) DEFAULT NULL COMMENT 小区名称,region varchar(50) DEFAULT NULL COMMENT 区域,subway varchar(100) DEFAULT NULL COMMENT 地铁信息,address varchar(255) DEFAULT NULL COMMENT 详细地址,longitude decimal(10,7) DEFAULT NULL COMMENT 经度,latitude decimal(10,7) DEFAULT NULL COMMENT 纬度,house_url varchar(255) DEFAULT NULL COMMENT 房源URL,publish_time datetime DEFAULT NULL COMMENT 发布时间,crawl_time datetime NOT NULL COMMENT 爬取时间,source varchar(50) NOT NULL COMMENT 数据源,status tinyint(4) NOT NULL DEFAULT 1 COMMENT 状态(1:有效,0:无效),update_time datetime NOT NULL COMMENT 更新时间,PRIMARY KEY (id),UNIQUE KEY idx_house_code (house_code),KEY idx_price (price),KEY idx_area (area),KEY idx_region (region),KEY idx_community (community),KEY idx_crawl_time (crawl_time),KEY idx_source (source)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT房源信息表;小区信息表 (community_info) sql
CREATE TABLE community_info (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 小区ID,name varchar(100) NOT NULL COMMENT 小区名称,region varchar(50) NOT NULL COMMENT 区域,address varchar(255) DEFAULT NULL COMMENT 详细地址,build_year varchar(20) DEFAULT NULL COMMENT 建造年份,developer varchar(100) DEFAULT NULL COMMENT 开发商,property_company varchar(100) DEFAULT NULL COMMENT 物业公司,property_fee decimal(5,2) DEFAULT NULL COMMENT 物业费(元/平方米·月),building_count int(11) DEFAULT NULL COMMENT 楼栋总数,house_count int(11) DEFAULT NULL COMMENT 房屋总数,longitude decimal(10,7) DEFAULT NULL COMMENT 经度,latitude decimal(10,7) DEFAULT NULL COMMENT 纬度,avg_price decimal(10,2) DEFAULT NULL COMMENT 均价(元/平方米),crawl_time datetime NOT NULL COMMENT 爬取时间,source varchar(50) NOT NULL COMMENT 数据源,status tinyint(4) NOT NULL DEFAULT 1 COMMENT 状态(1:有效,0:无效),update_time datetime NOT NULL COMMENT 更新时间,PRIMARY KEY (id),UNIQUE KEY idx_name_region (name,region),KEY idx_region (region),KEY idx_build_year (build_year),KEY idx_avg_price (avg_price),KEY idx_crawl_time (crawl_time),KEY idx_source (source)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT小区信息表;区域信息表 (region_info) sql
CREATE TABLE region_info (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 区域ID,name varchar(50) NOT NULL COMMENT 区域名称,parent_id bigint(20) DEFAULT NULL COMMENT 父区域ID,level tinyint(4) NOT NULL COMMENT 区域级别(1:城市,2:区县,3:街道/乡镇),longitude decimal(10,7) DEFAULT NULL COMMENT 经度,latitude decimal(10,7) DEFAULT NULL COMMENT 纬度,area decimal(10,2) DEFAULT NULL COMMENT 面积(平方公里),population bigint(20) DEFAULT NULL COMMENT 人口,gdp decimal(15,2) DEFAULT NULL COMMENT GDP(亿元),avg_price decimal(10,2) DEFAULT NULL COMMENT 均价(元/平方米),house_count int(11) DEFAULT NULL COMMENT 房源数量,update_time datetime NOT NULL COMMENT 更新时间,PRIMARY KEY (id),UNIQUE KEY idx_name_parent_id (name,parent_id),KEY idx_parent_id (parent_id),KEY idx_level (level),KEY idx_avg_price (avg_price),KEY idx_house_count (house_count)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT区域信息表;地铁信息表 (subway_info) sql
CREATE TABLE subway_info (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 地铁ID,name varchar(50) NOT NULL COMMENT 地铁名称,line varchar(50) NOT NULL COMMENT 线路,region varchar(50) DEFAULT NULL COMMENT 所在区域,longitude decimal(10,7) DEFAULT NULL COMMENT 经度,latitude decimal(10,7) DEFAULT NULL COMMENT 纬度,update_time datetime NOT NULL COMMENT 更新时间,PRIMARY KEY (id),UNIQUE KEY idx_name_line (name,line),KEY idx_line (line),KEY idx_region (region)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT地铁信息表;用户信息表 (user_info) sql
CREATE TABLE user_info (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 用户ID,username varchar(50) NOT NULL COMMENT 用户名,password varchar(100) NOT NULL COMMENT 密码(加密),email varchar(100) DEFAULT NULL COMMENT 邮箱,phone varchar(20) DEFAULT NULL COMMENT 手机号,real_name varchar(50) DEFAULT NULL COMMENT 真实姓名,id_card varchar(20) DEFAULT NULL COMMENT 身份证号,avatar varchar(255) DEFAULT NULL COMMENT 头像,role tinyint(4) NOT NULL DEFAULT 1 COMMENT 角色(1:普通用户,2:管理员),status tinyint(4) NOT NULL DEFAULT 1 COMMENT 状态(1:正常,0:禁用),create_time datetime NOT NULL COMMENT 创建时间,update_time datetime NOT NULL COMMENT 更新时间,PRIMARY KEY (id),UNIQUE KEY idx_username (username),UNIQUE KEY idx_email (email),UNIQUE KEY idx_phone (phone)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户信息表;用户收藏表 (user_favorite) sql
CREATE TABLE user_favorite (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 收藏ID,user_id bigint(20) NOT NULL COMMENT 用户ID,house_id bigint(20) NOT NULL COMMENT 房源ID,create_time datetime NOT NULL COMMENT 收藏时间,PRIMARY KEY (id),UNIQUE KEY idx_user_id_house_id (user_id,house_id),KEY idx_house_id (house_id),KEY idx_create_time (create_time)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户收藏表;系统配置表 (system_config) sql
CREATE TABLE system_config (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 配置ID,config_key varchar(100) NOT NULL COMMENT 配置键,config_value text NOT NULL COMMENT 配置值,description varchar(255) DEFAULT NULL COMMENT 描述,create_time datetime NOT NULL COMMENT 创建时间,update_time datetime NOT NULL COMMENT 更新时间,PRIMARY KEY (id),UNIQUE KEY idx_config_key (config_key)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT系统配置表;爬虫日志表 (crawl_log) sql
CREATE TABLE crawl_log (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 日志ID,source varchar(50) NOT NULL COMMENT 数据源,url varchar(255) DEFAULT NULL COMMENT URL,status tinyint(4) NOT NULL DEFAULT 1 COMMENT 状态(1:成功,0:失败),message text DEFAULT NULL COMMENT 消息,start_time datetime NOT NULL COMMENT 开始时间,end_time datetime NOT NULL COMMENT 结束时间,duration int(11) DEFAULT NULL COMMENT 耗时(毫秒),create_time datetime NOT NULL COMMENT 创建时间,PRIMARY KEY (id),KEY idx_source (source),KEY idx_status (status),KEY idx_start_time (start_time),KEY idx_end_time (end_time)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT爬虫日志表;分析报告表 (analysis_report) sql
CREATE TABLE analysis_report (id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 报告ID,user_id bigint(20) DEFAULT NULL COMMENT 用户ID,title varchar(255) NOT NULL COMMENT 报告标题,type varchar(50) NOT NULL COMMENT 报告类型,content text NOT NULL COMMENT 报告内容,start_date date DEFAULT NULL COMMENT 开始日期,end_date date DEFAULT NULL COMMENT 结束日期,region varchar(50) DEFAULT NULL COMMENT 区域,create_time datetime NOT NULL COMMENT 创建时间,update_time datetime NOT NULL COMMENT 更新时间,PRIMARY KEY (id),KEY idx_user_id (user_id),KEY idx_type (type),KEY idx_create_time (create_time),KEY idx_region (region)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT分析报告表;4.3 系统架构图 4.4 部署架构图 4.5 用例图 4.6 界面原型
4.6.1 首页
首页展示热门房源、价格趋势、区域分布等信息用户可以进行搜索、筛选等操作。
4.6.2 房源列表页
展示符合条件的房源列表包括房源基本信息、价格、面积等用户可以进行排序、筛选等操作。
4.6.3 房源详情页
展示房源的详细信息包括房源描述、户型图、小区信息、周边配套等用户可以进行收藏、分享等操作。
4.6.4 数据分析页
展示房价趋势、区域分析、户型分析、面积分析等数据可视化图表用户可以进行筛选、导出等操作。
4.6.5 地图找房页
以地图形式展示房源分布用户可以通过地图浏览房源查看房源详情。
4.6.6 用户中心页
展示用户的个人信息、收藏房源、分析报告等用户可以进行个人信息修改、密码修改等操作。
4.6.7 管理后台首页
展示系统概览信息包括房源总数、新增房源数、爬虫状态等。
4.6.8 爬虫管理页
管理员可以配置爬虫参数、启动 / 停止爬虫、查看爬虫日志等。
4.6.9 数据管理页
管理员可以进行数据清洗、转换、分析等操作查看数据统计信息。
4.6.10 用户管理页
管理员可以查看、编辑、禁用用户信息分配用户权限等。
4.6.11 系统配置页
管理员可以配置系统参数如数据库连接、缓存配置、邮件配置等。
4.6.12 系统监控页
管理员可以监控系统的运行状态如 CPU 使用率、内存使用率、网络流量等。
5 系统实现
5.1 后端实现
5.1.1 项目结构
plaintext
house-analysis-system/
├── src/
│ ├── main/
│ │ ├── python/
│ │ │ └── house_analysis/
│ │ │ ├── __init__.py
│ │ │ ├── app.py # Flask应用入口
│ │ │ ├── config.py # 配置文件
│ │ │ ├── models/ # 数据模型
│ │ │ │ ├── __init__.py
│ │ │ │ ├── house_info.py
│ │ │ │ ├── community_info.py
│ │ │ │ ├── region_info.py
│ │ │ │ ├── subway_info.py
│ │ │ │ ├── user_info.py
│ │ │ │ ├── user_favorite.py
│ │ │ │ ├── system_config.py
│ │ │ │ ├── crawl_log.py
│ │ │ │ └── analysis_report.py
│ │ │ ├── controllers/ # 控制器
│ │ │ │ ├── __init__.py
│ │ │ │ ├── house_controller.py
│ │ │ │ ├── community_controller.py
│ │ │ │ ├── region_controller.py
│ │ │ │ ├── subway_controller.py
│ │ │ │ ├── user_controller.py
│ │ │ │ ├── analysis_controller.py
│ │ │ │ └── admin_controller.py
│ │ │ ├── services/ # 服务层
│ │ │ │ ├── __init__.py
│ │ │ │ ├── house_service.py
│ │ │ │ ├── community_service.py
│ │ │ │ ├── region_service.py
│ │ │ │ ├── subway_service.py
│ │ │ │ ├── user_service.py
│ │ │ │ ├── crawl_service.py
│ │ │ │ ├── data_processing_service.py
│ │ │ │ ├── analysis_service.py
│ │ │ │ └── report_service.py
│ │ │ ├── spiders/ # 爬虫
│ │ │ │ ├── __init__.py
│ │ │ │ ├── base_spider.py
│ │ │ │ ├── lianjia_spider.py
│ │ │ │ ├── ke_spider.py
│ │ │ │ ├── anjuke_spider.py
│ │ │ │ └── community_spider.py
│ │ │ ├── utils/ # 工具类
│ │ │ │ ├── __init__.py
│ │ │ │ ├── db_utils.py
│ │ │ │ ├── security_utils.py
│ │ │ │ ├── date_utils.py
│ │ │ │ ├── file_utils.py
│ │ │ │ ├── http_utils.py
│ │ │ │ ├── log_utils.py
│ │ │ │ └── spider_utils.py
│ │ │ ├── auth/ # 认证授权
│ │ │ │ ├── __init__.py
│ │ │ │ ├── jwt_utils.py
│ │ │ │ └── auth_middleware.py
│ │ │ ├── scheduler/ # 定时任务
│ │ │ │ ├── __init__.py
│ │ │ │ ├── daily_tasks.py
│ │ │ │ └── hourly_tasks.py
│ │ │ └── api/ # API路由
│ │ │ ├── __init__.py
│ │ │ ├── v1/
│ │ │ │ ├── __init__.py
│ │ │ │ ├── house_api.py
│ │ │ │ ├── community_api.py
│ │ │ │ ├── region_api.py
│ │ │ │ ├── subway_api.py
│ │ │ │ ├── user_api.py
│ │ │ │ ├── analysis_api.py
│ │ │ │ └── admin_api.py
│ │ ├── static/ # 静态资源
│ │ │ ├── css/
│ │ │ ├── js/
│ │ │ ├── images/
│ │ │ └── reports/
│ │ └── templates/ # HTML模板
│ │ ├── index.html
│ │ ├── house_list.html
│ │ ├── house_detail.html
│ │ ├── analysis.html
│ │ ├── map.html
│ │ ├── user_center.html
│ │ ├── login.html
│ │ ├── register.html
│ │ └── admin/
│ │ ├── dashboard.html
│ │ ├── spiders.html
│ │ ├── data_management.html
│ │ ├── users.html
│ │ ├── system_config.html
│ │ └── system_monitor.html
│ └── test/ # 测试代码
├── requirements.txt # 依赖包
├── run.py # 运行入口
└── README.md # 项目说明5.1.2 核心代码实现
爬虫模块实现 python
运行
import scrapy
import re
import time
import random
import logging
from datetime import datetime
from scrapy.http import Request
from scrapy.selector import Selector
from house_analysis.models import HouseInfo, CommunityInfo, CrawlLog
from house_analysis.utils import db_utils, date_utils, spider_utils
from house_analysis.services import house_service, community_serviceclass BaseSpider(scrapy.Spider):基础爬虫类def __init__(self, *args, **kwargs):初始化爬虫super(BaseSpider, self).__init__(*args, **kwargs)self.logger logging.getLogger(self.name)self.headers {User-Agent: spider_utils.get_random_user_agent(),Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,*/*;q0.8,Accept-Language: zh-CN,zh;q0.8,zh-TW;q0.7,zh-HK;q0.5,en-US;q0.3,en;q0.2,Connection: keep-alive,Upgrade-Insecure-Requests: 1,}self.proxies spider_utils.get_proxies()self.current_proxy Noneself.switch_proxy_count 0self.max_switch_proxy_count 100def get_proxy(self):获取代理if not self.proxies:return Noneif self.current_proxy is None or self.switch_proxy_count self.max_switch_proxy_count:self.current_proxy random.choice(self.proxies)self.switch_proxy_count 0else:self.switch_proxy_count 1return self.current_proxydef start_requests(self):开始请求start_urls self.get_start_urls()for url in start_urls:yield Request(urlurl,headersself.headers,meta{proxy: self.get_proxy()},callbackself.parse,errbackself.handle_error)def parse(self, response):解析响应raise NotImplementedError(子类必须实现parse方法)def handle_error(self, failure):处理错误request failure.requestself.logger.error(fRequest failed: {request.url}, error: {failure})# 记录错误日志crawl_log CrawlLog()crawl_log.source self.namecrawl_log.url request.urlcrawl_log.status 0crawl_log.message str(failure)crawl_log.start_time datetime.fromtimestamp(request.meta.get(start_time, time.time()))crawl_log.end_time datetime.now()crawl_log.duration int((crawl_log.end_time - crawl_log.start_time).total_seconds() * 1000)crawl_log.create_time datetime.now()db_utils.db.session.add(crawl_log)db_utils.db.session.commit()# 切换代理self.current_proxy None# 重试请求if retry_times not in request.meta or request.meta[retry_times] 3:retry_times request.meta.get(retry_times, 0) 1self.logger.info(fRetrying request: {request.url}, retry_times: {retry_times})yield Request(urlrequest.url,headersself.headers,meta{proxy: self.get_proxy(),retry_times: retry_times,start_time: time.time()},callbackself.parse,errbackself.handle_error,dont_filterTrue)def get_start_urls(self):获取起始URLraise NotImplementedError(子类必须实现get_start_urls方法)def save_house_info(self, house_data):保存房源信息# 创建房源对象house HouseInfo()house.house_code house_data.get(house_code)house.title house_data.get(title)house.price house_data.get(price)house.unit_price house_data.get(unit_price)house.area house_data.get(area)house.house_type house_data.get(house_type)house.floor house_data.get(floor)house.build_year house_data.get(build_year)house.orientation house_data.get(orientation)house.decoration house_data.get(decoration)house.community house_data.get(community)house.region house_data.get(region)house.subway house_data.get(subway)house.address house_data.get(address)house.longitude house_data.get(longitude)house.latitude house_data.get(latitude)house.house_url house_data.get(house_url)house.publish_time house_data.get(publish_time)house.crawl_time datetime.now()house.source self.namehouse.status 1house.update_time datetime.now()# 保存房源信息house_service.save_house(house)# 记录爬取日志crawl_log CrawlLog()crawl_log.source self.namecrawl_log.url house.house_urlcrawl_log.status 1crawl_log.start_time house_data.get(start_time, datetime.now())crawl_log.end_time datetime.now()crawl_log.duration int((crawl_log.end_time - crawl_log.start_time).total_seconds() * 1000)crawl_log.create_time datetime.now()db_utils.db.session.add(crawl_log)db_utils.db.session.commit()def save_community_info(self, community_data):保存小区信息# 创建小区对象community CommunityInfo()community.name community_data.get(name)community.region community_data.get(region)community.address community_data.get(address)community.build_year community_data.get(build_year)community.developer community_data.get(developer)community.property_company community_data.get(property_company)community.property_fee community_data.get(property_fee)community.building_count community_data.get(building_count)community.house_count community_data.get(house_count)community.longitude community_data.get(longitude)community.latitude community_data.get(latitude)community.avg_price community_data.get(avg_price)community.crawl_time datetime.now()community.source self.namecommunity.status 1community.update_time datetime.now()# 保存小区信息community_service.save_community(community)# 记录爬取日志crawl_log CrawlLog()crawl_log.source self.namecrawl_log.url community_data.get(community_url)crawl_log.status 1crawl_log.start_time community_data.get(start_time, datetime.now())crawl_log.end_time datetime.now()crawl_log.duration int((crawl_log.end_time - crawl_log.start_time).total_seconds() * 1000)crawl_log.create_time datetime.now()db_utils.db.session.add(crawl_log)db_utils.db.session.commit()class LianjiaSpider(BaseSpider):链家爬虫name lianjiaallowed_domains [lianjia.com]base_url https://bj.lianjia.com/ershoufang/def get_start_urls(self):获取起始URL# 获取区域列表regions self.get_regions()# 构建起始URL列表start_urls []for region in regions:for page in range(1, 101): # 最多爬取100页url f{self.base_url}{region}/pg{page}/start_urls.append(url)return start_urlsdef get_regions(self):获取区域列表# 这里简化处理实际应从页面解析获取regions [dongcheng, xicheng, chaoyang, haidian, fengtai, shijingshan, tongzhou, changping, daxing, yizhuangkaifaqu, shunyi, fangshan]return regionsdef parse(self, response):解析房源列表页# 记录开始时间start_time datetime.now()# 解析房源列表sel Selector(response)house_items sel.css(.sellListContent li.clear)for item in house_items:# 解析房源信息house_url item.css(.title a::attr(href)).extract_first()if not house_url:continue# 访问房源详情页yield Request(urlhouse_url,headersself.headers,meta{proxy: self.get_proxy(),start_time: start_time},callbackself.parse_house_detail,errbackself.handle_error)# 解析下一页next_page sel.css(.next::attr(href)).extract_first()if next_page:next_page_url response.urljoin(next_page)yield Request(urlnext_page_url,headersself.headers,meta{proxy: self.get_proxy(),start_time: start_time},callbackself.parse,errbackself.handle_error)def parse_house_detail(self, response):解析房源详情页# 记录开始时间start_time response.meta.get(start_time, datetime.now())# 解析房源信息sel Selector(response)# 提取房源编码house_code response.url.split(/)[-1].split(.)[0]# 提取标题title sel.css(.title .main::text).extract_first()# 提取价格total_price sel.css(.price .total::text).extract_first()if total_price:total_price float(total_price)else:total_price 0unit_price sel.css(.unitPriceValue::text).extract_first()if unit_price:unit_price int(re.sub(r[^\d], , unit_price))else:unit_price 0# 提取基本信息base_info sel.css(.base .content li)area 0house_type floor orientation decoration build_year for info in base_info:label info.css(::text).extract_first()value info.css(::text).extract()[1] if len(info.css(::text).extract()) 1 else if 建筑面积 in label:area float(re.sub(r[^\d.], , value))elif 房屋户型 in label:house_type valueelif 所在楼层 in label:floor valueelif 房屋朝向 in label:orientation valueelif 装修情况 in label:decoration valueelif 建成年代 in label:build_year value# 提取小区信息community sel.css(.communityName .info::text).extract_first()# 提取区域信息region sel.css(.areaName .info a::text).extract_first()# 提取地铁信息subway sel.css(.subway .info::text).extract_first()# 提取地址address sel.css(.areaName .info a::text).extract()address .join(address) if address else # 提取经纬度longitude 0latitude 0map_info sel.css(.around .info a::attr(href)).extract_first()if map_info and resblockPosition in map_info:position map_info.split(resblockPosition)[1].split()[0]if , in position:longitude, latitude position.split(,)longitude float(longitude)latitude float(latitude)# 提取发布时间publish_time sel.css(.transaction .content li:nth-child(3) span:nth-child(2)::text).extract_first()if publish_time:publish_time date_utils.parse_date(publish_time)# 保存房源信息house_data {house_code: house_code,title: title,price: total_price,unit_price: unit_price,area: area,house_type: house_type,floor: floor,build_year: build_year,orientation: orientation,decoration: decoration,community: community,region: region,subway: subway,address: address,longitude: longitude,latitude: latitude,house_url: response.url,publish_time: publish_time,start_time: start_time}self.save_house_info(house_data)# 提取小区链接并爬取小区信息community_url sel.css(.communityName .info::attr(href)).extract_first()if community_url:community_url response.urljoin(community_url)yield Request(urlcommunity_url,headersself.headers,meta{proxy: self.get_proxy(),start_time: datetime.now()},callbackself.parse_community_detail,errbackself.handle_error)def parse_community_detail(self, response):解析小区详情页# 记录开始时间start_time response.meta.get(start_time, datetime.now())# 解析小区信息sel Selector(response)# 提取小区名称name sel.css(.detailHeader .title::text).extract_first()# 提取区域信息region sel.css(.areaName a::text).extract()region .join(region) if region else # 提取地址address sel.css(.detailHeader .subTitle::text).extract_first()# 提取基本信息base_info sel.css(.xiaoquInfoItem)build_year developer property_company property_fee 0building_count 0house_count 0for info in base_info:label info.css(.xiaoquInfoLabel::text).extract_first()value info.css(.xiaoquInfoContent::text).extract_first()if 建成年代 in label:build_year valueelif 开发商 in label:developer valueelif 物业公司 in label:property_company valueelif 物业费 in label:if value:property_fee float(re.sub(r[^\d.], , value))elif 楼栋总数 in label:if value:building_count int(re.sub(r[^\d], , value))elif 房屋总数 in label:if value:house_count int(re.sub(r[^\d], , value))# 提取均价avg_price sel.css(.xiaoquUnitPrice::text).extract_first()if avg_price:avg_price int(re.sub(r[^\d], , avg_price))else:avg_price 0# 提取经纬度longitude 0latitude 0map_info sel.css(.mapContainer::attr(data-coord)).extract_first()if map_info and , in map_info:longitude, latitude map_info.split(,)longitude float(longitude)latitude float(latitude)# 保存小区信息community_data {name: name,region: region,address: address,build_year: build_year,developer: developer,property_company: property_company,property_fee: property_fee,building_count: building_count,house_count: house_count,longitude: longitude,latitude: latitude,avg_price: avg_price,community_url: response.url,start_time: start_time}self.save_community_info(community_data)数据分析模块实现 python
运行
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import datetime, timedelta
from sqlalchemy import func
from matplotlib.font_manager import FontProperties
from house_analysis.models import HouseInfo, CommunityInfo, RegionInfo, AnalysisReport
from house_analysis.utils import db_utils, date_utils, file_utilsclass AnalysisService:数据分析服务def __init__(self):初始化分析服务self.font FontProperties(fnamesimhei.ttf, size12)plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签plt.rcParams[axes.unicode_minus] False # 用来正常显示负号sns.set(fontSimHei) # 解决Seaborn中文显示问题def get_house_data(self, start_dateNone, end_dateNone, regionNone, min_priceNone, max_priceNone, min_areaNone, max_areaNone, house_typeNone):获取房源数据query HouseInfo.query# 筛选日期范围if start_date and end_date:query query.filter(HouseInfo.crawl_time.between(start_date, end_date))# 筛选区域if region:query query.filter(HouseInfo.region region)# 筛选价格范围if min_price:query query.filter(HouseInfo.price min_price)if max_price:query query.filter(HouseInfo.price max_price)# 筛选面积范围if min_area:query query.filter(HouseInfo.area min_area)if max_area:query query.filter(HouseInfo.area max_area)# 筛选户型if house_type:query query.filter(HouseInfo.house_type.like(f%{house_type}%))# 获取数据houses query.all()# 转换为DataFramedata []for house in houses:data.append({id: house.id,house_code: house.house_code,title: house.title,price: house.price,unit_price: house.unit_price,area: house.area,house_type: house.house_type,floor: house.floor,build_year: house.build_year,orientation: house.orientation,decoration: house.decoration,community: house.community,region: house.region,subway: house.subway,address: house.address,longitude: house.longitude,latitude: house.latitude,publish_time: house.publish_time,crawl_time: house.crawl_time,source: house.source})return pd.DataFrame(data)def get_community_data(self, start_dateNone, end_dateNone, regionNone):获取小区数据query CommunityInfo.query# 筛选日期范围if start_date and end_date:query query.filter(CommunityInfo.crawl_time.between(start_date, end_date))# 筛选区域if region:query query.filter(CommunityInfo.region region)# 获取数据communities query.all()# 转换为DataFramedata []for community in communities:data.append({id: community.id,name: community.name,region: community.region,address: community.address,build_year: community.build_year,developer: community.developer,property_company: community.property_company,property_fee: community.property_fee,building_count: community.building_count,house_count: community.house_count,longitude: community.longitude,latitude: community.latitude,avg_price: community.avg_price,crawl_time: community.crawl_time,source: community.source})return pd.DataFrame(data)def analyze_price_trend(self, df, date_fieldcrawl_time, price_fieldprice):分析价格趋势if df.empty:return None# 按日期分组计算平均价格df[date_field] pd.to_datetime(df[date_field])df[date] df[date_field].dt.dateprice_trend df.groupby(date)[price_field].mean().reset_index()# 按日期排序price_trend price_trend.sort_values(date)return price_trenddef analyze_region_price(self, df, region_fieldregion, price_fieldprice):分析区域价格if df.empty:return None# 按区域分组计算平均价格region_price df.groupby(region_field)[price_field].mean().reset_index()# 按价格排序region_price region_price.sort_values(price_field, ascendingFalse)return region_pricedef analyze_house_type_price(self, df, house_type_fieldhouse_type, price_fieldprice):分析户型价格if df.empty:return None# 按户型分组计算平均价格house_type_price df.groupby(house_type_field)[price_field].mean().reset_index()# 按价格排序house_type_price house_type_price.sort_values(price_field, ascendingFalse)return house_type_pricedef analyze_area_price(self, df, area_fieldarea, price_fieldprice):分析面积价格if df.empty:return None# 创建面积区间bins [0, 50, 70, 90, 110, 130, 150, float(inf)]labels [0-50, 50-70, 70-90, 90-110, 110-130, 130-150, 150]df[area_range] pd.cut(df[area_field], binsbins, labelslabels)# 按面积区间分组计算平均价格area_price df.groupby(area_range)[price_field].mean().reset_index()return area_pricedef analyze_correlation(self, df, columns[price, area, unit_price]):分析相关性if df.empty:return None# 选择需要分析的列corr_df df[columns]# 计算相关性矩阵correlation corr_df.corr()return correlationdef generate_price_trend_chart(self, price_trend, title房价趋势分析, xlabel日期, ylabel平均价格(万元), output_pathNone):生成价格趋势图表if price_trend is None or price_trend.empty:return Noneplt.figure(figsize(12, 6))plt.plot(price_trend[date], price_trend[price], markero)plt.title(title, fontpropertiesself.font)plt.xlabel(xlabel, fontpropertiesself.font)plt.ylabel(ylabel, fontpropertiesself.font)plt.grid(True)plt.xticks(rotation45)plt.tight_layout()if output_path:plt.savefig(output_path)return pltdef generate_region_price_chart(self, region_price, title区域房价分析, xlabel区域, ylabel平均价格(万元), output_pathNone):生成区域价格图表if region_price is None or region_price.empty:return Noneplt.figure(figsize(12, 6))plt.bar(region_price[region], region_price[price])plt.title(title, fontpropertiesself.font)plt.xlabel(xlabel, fontpropertiesself.font)plt.ylabel(ylabel, fontpropertiesself.font)plt.grid(True, axisy)plt.xticks(rotation45)plt.tight_layout()if output_path:plt.savefig(output_path)return pltdef generate_house_type_price_chart(self, house_type_price, title户型房价分析, xlabel户型, ylabel平均价格(万元), output_pathNone):生成户型价格图表if house_type_price is None or house_type_price.empty:return Noneplt.figure(figsize(12, 6))plt.bar(house_type_price[house_type], house_type_price[price])plt.title(title, fontpropertiesself.font)plt.xlabel(xlabel, fontpropertiesself.font)plt.ylabel(ylabel, fontpropertiesself.font)plt.grid(True, axisy)plt.xticks(rotation45)plt.tight_layout()if output_path:plt.savefig(output_path)return pltdef generate_area_price_chart(self, area_price, title面积段房价分析, xlabel面积区间(平方米), ylabel平均价格(万元), output_pathNone):生成面积价格图表if area_price is None or area_price.empty:return Noneplt.figure(figsize(12, 6))plt.bar(area_price[area_range], area_price[price])plt.title(title, fontpropertiesself.font)plt.xlabel(xlabel, fontpropertiesself.font)plt.ylabel(ylabel, fontpropertiesself.font)plt.grid(True, axisy)plt.tight_layout()if output_path:plt.savefig(output_path)return pltdef generate_correlation_heatmap(self, correlation, title相关性分析, output_pathNone):生成相关性热力图if correlation is None or correlation.empty:return Noneplt.figure(figsize(10, 8))sns.heatmap(correlation, annotTrue, cmapcoolwarm, fmt.2f)plt.title(title, fontpropertiesself.font)plt.tight_layout()if output_path:plt.savefig(output_path)return pltdef generate_region_price_map(self, region_price, title区域房价分布图, output_pathNone):生成区域价格地图# 这里简化处理实际应使用地图库如folium、pyecharts等# 生成区域房价分布图的代码passdef generate_analysis_report(self, user_idNone, title房价分析报告, start_dateNone, end_dateNone, regionNone, min_priceNone, max_priceNone, min_areaNone, max_areaNone, house_typeNone):生成分析报告# 获取房源数据df self.get_house_data(start_date, end_date, region, min_price, max_price, min_area, max_area, house_type)if df.empty:return None, 没有找到符合条件的数据# 分析数据price_trend self.analyze_price_trend(df)region_price self.analyze_region_price(df)house_type_price self.analyze_house_type_price(df)area_price self.analyze_area_price(df)correlation self.analyze_correlation(df)# 生成图表report_dir fsrc/main/static/reports/{int(time.time())}file_utils.create_dir(report_dir)price_trend_chart self.generate_price_trend_chart(price_trend, output_pathf{report_dir}/price_trend.png)region_price_chart self.generate_region_price_chart(region_price, output_pathf{report_dir}/region_price.png)house_type_price_chart self.generate_house_type_price_chart(house_type_price, output_pathf{report_dir}/house_type_price.png)area_price_chart self.generate_area_price_chart(area_price, output_pathf{report_dir}/area_price.png)correlation_heatmap self.generate_correlation_heatmap(correlation, output_pathf{report_dir}/correlation.png)# 关闭图表plt.close(all)# 生成报告内容report_content {title: title,start_date: start_date.strftime(%Y-%m-%d) if start_date else 无,end_date: end_date.strftime(%Y-%m-%d) if end_date else 无,region: region if region else 全部,house_count: len(df),avg_price: df[price].mean(),max_price: df[price].max(),min_price: df[price].min(),avg_area: df[area].mean(),max_area: df[area].max(),min_area: df[area].min(),price_trend: price_trend.to_dict(records),region_price: region_price.to_dict(records),house_type_price: house_type_price.to_dict(records),area_price: area_price.to_dict(records),correlation: correlation.to_dict(),charts: {price_trend: freports/{int(time.time())}/price_trend.png,region_price: freports/{int(time.time())}/region_price.png,house_type_price: freports/{int(time.time())}/house_type_price.png,area_price: freports/{int(time.time())}/area_price.png,correlation: freports/{int(time.time())}/correlation.png}}# 保存报告report AnalysisReport()report.user_id user_idreport.title titlereport.type house_analysisreport.content json.dumps(report_content)report.start_date start_datereport.end_date end_datereport.region regionreport.create_time datetime.now()report.update_time datetime.now()db_utils.db.session.add(report)db_utils.db.session.commit()return report, 报告生成成功API 接口实现 python
运行
from flask import Blueprint, request, jsonify, make_response
from flask_jwt_extended import jwt_required, get_jwt_identity
from house_analysis.models import HouseInfo, CommunityInfo, UserInfo, UserFavorite, AnalysisReport
from house_analysis.services import house_service, community_service, user_service, analysis_service, report_service
from house_analysis.utils import db_utils, date_utils, security_utils, file_utils
import json
import pandas as pd
from datetime import datetime, timedeltaapi Blueprint(house_api, __name__, url_prefix/api/v1)api.route(/houses, methods[GET])
def get_houses():获取房源列表# 获取查询参数page int(request.args.get(page, 1))page_size int(request.args.get(page_size, 20))region request.args.get(region, None)min_price request.args.get(min_price, None)max_price request.args.get(max_price, None)min_area request.args.get(min_area, None)max_area request.args.get(max_area, None)house_type request.args.get(house_type, None)sort_by request.args.get(sort_by, price)sort_order request.args.get(sort_order, asc)# 转换参数类型if min_price:min_price float(min_price)if max_price:max_price float(max_price)if min_area:min_area float(min_area)if max_area:max_area float(max_area)# 获取房源列表houses, total house_service.get_houses(page, page_size, region, min_price, max_price, min_area, max_area, house_type, sort_by, sort_order)# 转换为字典列表house_list []for house in houses:house_dict {id: house.id,house_code: house.house_code,title: house.title,price: house.price,unit_price: house.unit_price,area: house.area,house_type: house.house_type,floor: house.floor,build_year: house.build_year,orientation: house.orientation,decoration: house.decoration,community: house.community,region: house.region,subway: house.subway,address: house.address,longitude: house.longitude,latitude: house.latitude,house_url: house.house_url,publish_time: house.publish_time.strftime(%Y-%m-%d) if house.publish_time else None,crawl_time: house.crawl_time.strftime(%Y-%m-%d %H:%M:%S),source: house.source}house_list.append(house_dict)# 返回结果return jsonify({code: 200,message: success,data: {houses: house_list,total: total,page: page,page_size: page_size}})api.route(/houses/house_id, methods[GET])
def get_house_detail(house_id):获取房源详情# 获取房源信息house house_service.get_house_by_id(house_id)if not house:return jsonify({code: 404,message: 房源不存在}), 404# 获取小区信息community community_service.get_community_by_name(house.community)# 转换为字典house_dict {id: house.id,house_code: house.house_code,title: house.title,price: house.price,unit_price: house.unit_price,area: house.area,house_type: house.house_type,floor: house.floor,build_year: house.build_year,orientation: house.orientation,decoration: house.decoration,community: house.community,region: house.region,subway: house.subway,address: house.address,longitude: house.longitude,latitude: house.latitude,house_url: house.house_url,publish_time: house.publish_time.strftime(%Y-%m-%d) if house.publish_time else None,crawl_time: house.crawl_time.strftime(%Y-%m-%d %H:%M:%S),source: house.source}# 添加小区信息if community:house_dict[community_info] {id: community.id,name: community.name,region: community.region,address: community.address,build_year: community.build_year,developer: community.developer,property_company: community.property_company,property_fee: community.property_fee,building_count: community.building_count,house_count: community.house_count,avg_price: community.avg_price,crawl_time: community.crawl_time.strftime(%Y-%m-%d %H:%M:%S)}# 返回结果return jsonify({code: 200,message: success,data: house_dict})api.route(/communities, methods[GET])
def get_communities():获取小区列表# 获取查询参数page int(request.args.get(page, 1))page_size int(request.args.get(page_size, 20))region request.args.get(region, None)min_price request.args.get(min_price, None)max_price request.args.get(max_price, None)build_year request.args.get(build_year, None)sort_by request.args.get(sort_by, avg_price)sort_order request.args.get(sort_order, desc)# 转换参数类型if min_price:min_price float(min_price)if max_price:max_price float(max_price)# 获取小区列表communities, total community_service.get_communities(page, page_size, region, min_price, max_price, build_year, sort_by, sort_order)# 转换为字典列表community_list []for community in communities:community_dict {id: community.id,name: community.name,region: community.region,address: community.address,build_year: community.build_year,developer: community.developer,property_company: community.property_company,property_fee: community.property_fee,building_count: community.building_count,house_count: community.house_count,longitude: community.longitude,latitude: community.latitude,avg_price: community.avg_price,crawl_time: community.crawl_time.strftime(%Y-%m-%d %H:%M:%S),source: community.source}community_list.append(community_dict)# 返回结果return jsonify({code: 200,message: success,data: {communities: community_list,total: total,page: page,page_size: page_size}})api.route(/regions, methods[GET])
def get_regions():获取区域列表# 获取区域列表regions house_service.get_regions()# 返回结果return jsonify({code: 200,message: success,data: regions})api.route(/house_types, methods[GET])
def get_house_types():获取户型列表# 获取户型列表house_types house_service.get_house_types()# 返回结果return jsonify({code: 200,message: success,data: house_types})api.route(/博主介绍硕士研究生专注于信息化技术领域开发与管理会使用java、标准c/c等开发语言以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年拥有近12年的管理工作经验拥有较丰富的技术架构思想、较扎实的技术功底和资深的项目管理经验。 先后担任过技术总监、部门经理、项目经理、开发组长、java高级工程师及c工程师等职位在工业互联网、国家标识解析体系、物联网、分布式集群架构、大数据通道处理、接口开发、远程教育、办公OA、财务软件工资、记账、决策、分析、报表统计等方面、企业内部管理软件(ERP、CRM等)、arggis地图等信息化建设领域有较丰富的实战工作经验拥有BS分布式架构集群、数据库负载集群架构、大数据存储集群架构以及高并发分布式集群架构的设计、开发和部署实战经验拥有大并发访问、大数据存储、即时消息等瓶颈解决方案和实战经验。 拥有产品研发和发明专利申请相关工作经验完成发明专利构思、设计、编写、申请等工作并获得发明专利1枚。 ----------------------------------------------------------------------------------- 大家在毕设选题、项目升级、论文写作就业毕业等相关问题都可以给我留言咨询非常乐意帮助更多的人或加w 908925859。 相关博客地址 csdn专业技术博客https://blog.csdn.net/mr_lili_1986?typeblog Iteye博客: https://www.iteye.com/blog/user/mr-lili-1986-163-com 门户http://www.petsqi.cn 七、其他案例