基于Python+爬虫的租房数据可视化分析平台设计与实现
今天带来的是基于Python+爬虫的租房数据可视化分析平台,随着互联网技术的飞速发展和租房市场的日益繁荣,租房信息呈现出海量、分散且格式多样的特点。对于租房者来说,从众多平台和网站中筛选和比较合适的房源信息成为一项耗时且繁琐的任务。同时,租房市场的信息不对称现象也增加了租房者的决策难度。因此,本研究旨在开发一个基于Python和爬虫技术的租房数据可视化分析平台,通过自动化抓取和整合租房数据,并以直
💗博主介绍:✌全网粉丝15W+,CSDN全栈领域优质创作者,博客之星、掘金/知乎/b站/华为云/阿里云等平台优质作者、专注于Java、小程序/APP、python、大数据等技术领域和毕业项目实战,以及程序定制化开发、文档编写、答疑辅导等。
👇🏻 精彩专栏 推荐订阅👇🏻
计算机毕业设计精品项目案例(持续更新)
🌟文末获取源码+数据库+文档🌟
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以和学长沟通,希望帮助更多的人
一.前言
随着互联网技术的飞速发展和租房市场的日益繁荣,租房信息呈现出海量、分散且格式多样的特点。对于租房者来说,从众多平台和网站中筛选和比较合适的房源信息成为一项耗时且繁琐的任务。同时,租房市场的信息不对称现象也增加了租房者的决策难度。因此,本研究旨在开发一个基于Python和爬虫技术的租房数据可视化分析平台,通过自动化抓取和整合租房数据,并以直观、易懂的图表形式展示给租房者,帮助他们更高效地获取租房信息,更准确地理解租房市场动态,从而做出更明智的租房决策。
租房数据可视化分析系统是通过采用B/S架构,Django框架以及MySQL数据库技术,旨在为用户提供全面的租房信息和数据支持。该系统具备丰富的功能,包括管理员端的系统首页、个人中心、用户管理、房屋信息管理、租房数据管理和系统管理,以及前台端的首页、房屋信息、租房数据、房屋资讯和个人中心等模块。通过这些功能,用户可以方便地查找合适的房源,了解租金走势和热门区域等信息,同时管理员可以对用户和房屋信息进行有效管理,保证系统的正常运行和数据的安全性。
二.技术环境
开发语言:Python
python框架:django
软件版本:python3.7/python3.8
数据库:mysql 5.7或更高版本
数据库工具:Navicat11
爬虫框架:Scrapy
大数据框架:Hadoop
开发软件:PyCharm/vs code
前端框架:vue.js
三.功能设计
租房数据可视化分析系统主要有管理员和用户两个功能模块。以下将对这两个功能的作用进行详细的剖析。
管理员模块:管理员是系统中的核心用户,管理员登录后,可以对后台系统进行管理。主要功能有系统首页、个人中心、用户管理、房屋信息管理、租房数据管理、系统管理等功能。管理员用例如图所示。
用户:用户进入系统可以实现对首页、房屋信息、租房数据、房屋资讯、个人中心等信息进行操作。用户用例如图所示。
四.数据设计
概念模型的设计是为了抽象真实世界的信息,并对信息世界进行建模。它是数据库设计的强大工具。数据库概念模型设计可以通过E-R图描述现实世界的概念模型,
根据系统需求在系统中将对“用户、房屋信息、租房数据、房屋资讯、系统简介、收藏表”等作为实体,它们的局部E-R如图所示:
五.部分效果展示
5.1前台用户功能实现效果
当人们打开系统的网址后,首先看到的就是首页界面。在这里,人们能够看到租房数据可视化分析系统的导航条,通过导航条导航进入各功能展示页面进行操作。系统首页界面如图所示:

在注册流程中,用户在Vue前端填写必要信息(如用户名、密码等)并提交。前端将这些信息通过HTTP请求发送到Python后端。后端处理这些信息,检查用户名是否唯一,并将新用户数据存入MySQL数据库。完成后,后端向前端发送注册成功的确认,前端随后通知用户完成注册。这个过程实现了新用户的数据收集、验证和存储。系统注册页面如图所示:
房屋信息:在房屋信息页面的输入栏中输入房屋名称和房屋地址进行查询,可以查看到房屋详细信息,并根据需要进行评论或收藏操作;房屋信息页面如图所示:
个人中心:在个人中心页面输入个人信息可以进行信息更新操作,并可以根据需要对修改密码和我的收藏进行详细操作;如图所示:
5.2后台管理员功能实现效果
在登录流程中,用户首先在Vue前端界面输入用户名和密码。这些信息通过HTTP请求发送到Python后端。后端接收请求,通过与MySQL数据库交互验证用户凭证。如果认证成功,后端会返回给前端,允许用户访问系统。这个过程涵盖了从用户输入到系统验证和响应的全过程。管理员登录界面图所示。
管理员进入主页面,主要功能包括对系统首页、个人中心、用户管理、房屋信息管理、租房数据管理、系统管理等进行操作。管理员主页面如图所示:
房屋信息管理功能实现是在Django后端部分,您需要创建一个新的应用,然后在该应用下创建一个模型(models.py)来定义用户的数据结构,使用Django的ORM来处理与MySQL数据库的交互,包括房屋信息的查询、添加或删除等操作。接着,在views.py中编写视图逻辑来处理前端请求,使用Django的URL路由(urls.py)将请求映射到相应的视图函数。对于数据的验证和序列化,可以使用Django的表单或序列化器来实现。在前端Vue.js部分,将创建相应的Vue组件,在这些组件中使用axios或其他HTTP库与Django后端的API进行交互,实现房屋信息的查看、修改、查看评论或删除等功能。状态管理可以通过Vuex来维护,比如在store目录下定义房屋信息模块的状态、突变、动作和获取器。房屋信息管理界面如图所示
租房数据管理功能实现是在Django后端部分,您需要创建一个新的应用,然后在该应用下创建一个模型(models.py)来定义租房数据的数据结构,使用Django的ORM来处理与MySQL数据库的交互,包括租房数据信息的查询、添加、删除或爬取数据等操作。接着,在views.py中编写视图逻辑来处理前端请求,使用Django的URL路由(urls.py)将请求映射到相应的视图函数。对于数据的验证和序列化,可以使用Django的表单或序列化器来实现。在前端Vue.js部分,将创建相应的Vue组件,在这些组件中使用axios或其他HTTP库与Django后端的API进行交互,实现租房数据信息的查看、修改或删除等功能。状态管理可以通过Vuex来维护,比如在store目录下定义租房数据模块的状态、突变、动作和获取器。租房数据管理界面如图所示
管理员点击系统管理。在房屋资讯页面输入标题进行查询、添加或删除房屋资讯列表,并根据需要对房屋资讯详情信息进行查看、修改或删除操作;还可以对系统简介、轮播图管理、房屋资讯分类和关于我们进行详细操作;如图所示:
5.3可视化大屏展示功能实现效果
管理员进行爬取数据后可以在看板页面查看到系统简介、价格统计、面积统计、楼层统计、地址统计、格局统计、租房数据总数、租房数据详情等实时的分析图进行可视化管理;看板大屏选择了Echart作为数据可视化工具,它是一个使用JavaScript实现的开源可视化库,能够无缝集成到python应用中。Echart的强大之处在于其丰富的图表类型和高度的定制化能力,使得管理人员可以通过直观的图表清晰地把握租房的各项数据。
看板页面如图所示:

六.部分功能代码
# # -*- coding: utf-8 -*-
# 数据爬取文件
import scrapy
import pymysql
import pymssql
from ..items import ZufangItem
import time
from datetime import datetime,timedelta
import datetime as formattime
import re
import random
import platform
import json
import os
import urllib
from urllib.parse import urlparse
import requests
import emoji
import numpy as np
import pandas as pd
from sqlalchemy import create_engine
from selenium.webdriver import ChromeOptions, ActionChains
from scrapy.http import TextResponse
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
# 租房
class ZufangSpider(scrapy.Spider):
name = 'zufangSpider'
spiderUrl = 'https://m.anjuke.com/zufang/m/house/api_houselist_data_Jgs?page={}&search_firstpage=1&search_param=%7B%22city_id%22%3A3%2C%22platform%22%3A3%2C%22select_type%22%3A1%2C%22page_size%22%3A30%2C%22cityDomain%22%3A%22gz%22%2C%22cityListName%22%3A%22gz%22%2C%22sid%22%3A%22d0548cba8e891a9978f6c74d3fafb675%22%7D&font_encrypt='
start_urls = spiderUrl.split(";")
protocol = ''
hostname = ''
realtime = False
headers = {
"Cookie":"输入自己的cookie"
}
def __init__(self,realtime=False,*args, **kwargs):
super().__init__(*args, **kwargs)
self.realtime = realtime=='true'
def start_requests(self):
plat = platform.system().lower()
if not self.realtime and (plat == 'linux' or plat == 'windows'):
connect = self.db_connect()
cursor = connect.cursor()
if self.table_exists(cursor, '9krj0476_zufang') == 1:
cursor.close()
connect.close()
self.temp_data()
return
pageNum = 1 + 1
for url in self.start_urls:
if '{}' in url:
for page in range(1, pageNum):
next_link = url.format(page)
yield scrapy.Request(
url=next_link,
headers=self.headers,
callback=self.parse
)
else:
yield scrapy.Request(
url=url,
headers=self.headers,
callback=self.parse
)
# 列表解析
def parse(self, response):
_url = urlparse(self.spiderUrl)
self.protocol = _url.scheme
self.hostname = _url.netloc
plat = platform.system().lower()
if not self.realtime and (plat == 'linux' or plat == 'windows'):
connect = self.db_connect()
cursor = connect.cursor()
if self.table_exists(cursor, '9krj0476_zufang') == 1:
cursor.close()
connect.close()
self.temp_data()
return
data = json.loads(response.body)
try:
list = data["data"]["list"]
except:
pass
for item in list:
fields = ZufangItem()
try:
fields["title"] = str( item["property"]["base"]["title"])
except:
pass
try:
fields["photo"] = str( item["property"]["base"]["default_photo"])
except:
pass
try:
fields["postdate"] = str( item["property"]["base"]["post_date"])
except:
pass
try:
fields["renttype"] = str( item["property"]["base"]["rent_type"])
except:
pass
try:
fields["price"] = float( item["property"]["base"]["attribute"]["price"])
except:
pass
try:
fields["areanum"] = float( item["property"]["base"]["attribute"]["area_num"])
except:
pass
try:
fields["floor"] = int( item["property"]["base"]["attribute"]["floor"])
except:
pass
try:
fields["geju"] = str( item["property"]["base"]["attribute"]["room_num"]+"室"+item["property"]["base"]["attribute"]["toilet_num"]+"厅")
except:
pass
try:
fields["address"] = str( item["community"]["base"]["name"])
except:
pass
try:
fields["laiyuan"] = str("https://gz.zu.anjuke.com/fangyuan/"+str( item["property"]["base"]["house_id"]))
except:
pass
yield fields
# 详情解析
def detail_parse(self, response):
fields = response.meta['fields']
return fields
# 数据清洗
def pandas_filter(self):
engine = create_engine('mysql+pymysql://root:123456@localhost/spider9krj0476?charset=UTF8MB4')
df = pd.read_sql('select * from zufang limit 50', con = engine)
# 重复数据过滤
df.duplicated()
df.drop_duplicates()
#空数据过滤
df.isnull()
df.dropna()
# 填充空数据
df.fillna(value = '暂无')
# 异常值过滤
# 滤出 大于800 和 小于 100 的
a = np.random.randint(0, 1000, size = 200)
cond = (a<=800) & (a>=100)
a[cond]
# 过滤正态分布的异常值
b = np.random.randn(100000)
# 3σ过滤异常值,σ即是标准差
cond = np.abs(b) > 3 * 1
b[cond]
# 正态分布数据
df2 = pd.DataFrame(data = np.random.randn(10000,3))
# 3σ过滤异常值,σ即是标准差
cond = (df2 > 3*df2.std()).any(axis = 1)
# 不满⾜条件的⾏索引
index = df2[cond].index
# 根据⾏索引,进⾏数据删除
df2.drop(labels=index,axis = 0)
# 去除多余html标签
def remove_html(self, html):
if html == None:
return ''
pattern = re.compile(r'<[^>]+>', re.S)
return pattern.sub('', html).strip()
# 数据库连接
def db_connect(self):
type = self.settings.get('TYPE', 'mysql')
host = self.settings.get('HOST', 'localhost')
port = int(self.settings.get('PORT', 3306))
user = self.settings.get('USER', 'root')
password = self.settings.get('PASSWORD', '123456')
try:
database = self.databaseName
except:
database = self.settings.get('DATABASE', '')
if type == 'mysql':
connect = pymysql.connect(host=host, port=port, db=database, user=user, passwd=password, charset='utf8')
else:
connect = pymssql.connect(host=host, user=user, password=password, database=database)
return connect
# 断表是否存在
def table_exists(self, cursor, table_name):
cursor.execute("show tables;")
tables = [cursor.fetchall()]
table_list = re.findall('(\'.*?\')',str(tables))
table_list = [re.sub("'",'',each) for each in table_list]
if table_name in table_list:
return 1
else:
return 0
# 数据缓存源
def temp_data(self):
connect = self.db_connect()
cursor = connect.cursor()
sql = '''
insert into `zufang`(
id
,title
,photo
,postdate
,renttype
,price
,areanum
,floor
,geju
,address
,laiyuan
)
select
id
,title
,photo
,postdate
,renttype
,price
,areanum
,floor
,geju
,address
,laiyuan
from `9krj0476_zufang`
where(not exists (select
id
,title
,photo
,postdate
,renttype
,price
,areanum
,floor
,geju
,address
,laiyuan
from `zufang` where
`zufang`.id=`9krj0476_zufang`.id
))
'''
cursor.execute(sql)
connect.commit()
connect.close()
源码及文档获取
文章下方名片联系我即可~
大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻
精彩专栏推荐订阅:在下方专栏👇🏻
最新计算机毕业设计选题篇-选题推荐
小程序毕业设计精品项目案例-200套
Java毕业设计精品项目案例-200套
Python毕业设计精品项目案例-200套
大数据毕业设计精品项目案例-200套
💟💟如果大家有任何疑虑,欢迎在下方位置详细交流。
更多推荐
所有评论(0)