1. 项目概述
这个基于Python和Django框架开发的租房数据分析平台,是我在指导学生完成毕业设计时开发的一个实战项目。它通过爬虫技术从58同城采集租房数据,经过清洗和分析后,以可视化的方式呈现给用户。这个系统不仅适合作为计算机专业的毕业设计选题,也完全可以作为一个真实可用的租房辅助决策工具。
在实际开发过程中,我发现租房市场存在严重的信息不对称问题。很多租客在选择房源时,往往只能依靠有限的信息和个人经验做判断。这个平台正是为了解决这个问题而生,它能够从海量租房数据中提取有价值的信息,帮助用户更全面地了解市场行情。
2. 技术架构设计
2.1 整体技术栈选择
这个项目采用了典型的Python Web开发技术栈:
- 后端框架:Django (v3.2)
- 数据库:MySQL (v8.0)
- 前端可视化:ECharts (v5.3)
- 爬虫框架:Requests + BeautifulSoup
- 部署环境:Nginx + uWSGI
选择Django而不是Flask的主要考虑是:
- Django自带完善的后台管理系统,非常适合需要数据管理的项目
- ORM功能强大,简化数据库操作
- 内置用户认证系统,节省开发时间
- 社区生态丰富,遇到问题容易找到解决方案
2.2 数据库设计
数据库设计遵循了第三范式,主要包含以下表结构:
- 用户表(user)
- id (主键)
- name (用户名)
- pass (密码,存储MD5哈希值)
- role (角色:1普通用户/2管理员)
- token (登录令牌)
- 房源表(house)
- id (主键)
- name (小区名称)
- city (所在城市)
- area (区域)
- room (户型)
- room_area (面积)
- price (月租)
- type (类型:整租/合租)
- images (图片URL)
- statis (满意度评分)
- 评论表(comment)
- id (主键)
- house_id (关联房源ID)
- user_id (关联用户ID)
- content (评论内容)
- create_time (创建时间)
这种设计保证了数据的一致性和查询效率,特别是在处理复杂条件查询时表现良好。
3. 核心功能实现
3.1 数据采集模块
爬虫部分采用了Requests+BeautifulSoup的组合,而没有选择Scrapy,主要出于以下考虑:
- 58同城反爬机制相对简单,不需要太复杂的爬虫框架
- 项目规模不大,轻量级方案更合适
- 便于与Django项目集成
爬虫核心代码逻辑:
python复制def crawl_58tongcheng(city, max_page=10):
base_url = f"https://{city}.58.com/zufang/"
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit...'
}
house_list = []
for page in range(1, max_page+1):
url = f"{base_url}pn{page}/"
try:
response = requests.get(url, headers=headers)
soup = BeautifulSoup(response.text, 'html.parser')
items = soup.select('.house-list-item')
for item in items:
# 解析房源信息
title = item.select_one('.title a').text.strip()
price = item.select_one('.money b').text
area = item.select_one('.area').text.split('㎡')[0]
# 其他字段解析...
house_data = {
'title': title,
'price': price,
'area': area,
# 其他字段...
}
house_list.append(house_data)
time.sleep(random.uniform(1, 3)) # 随机延迟防止被封
except Exception as e:
print(f"第{page}页抓取失败:", e)
return house_list
在实际运行中,需要注意:
- 设置合理的请求间隔(1-3秒)
- 使用随机User-Agent
- 处理可能出现的异常情况
- 定期更换代理IP(如果需要大规模抓取)
3.2 数据清洗与存储
采集到的原始数据需要经过清洗才能使用:
python复制def clean_house_data(raw_data):
cleaned_data = []
for item in raw_data:
# 价格清洗
price = item['price']
if '万' in price:
price = float(price.replace('万', '')) * 10000
else:
price = float(price)
# 面积清洗
area = float(item['area'])
# 户型解析
room_info = parse_room_type(item['title'])
cleaned_item = {
'name': item['title'],
'price': price,
'room_area': area,
'room': room_info['room'],
'room_type': room_info['type'],
# 其他字段...
}
cleaned_data.append(cleaned_item)
return cleaned_data
清洗后的数据通过Django ORM存入MySQL:
python复制from django.db import models
class House(models.Model):
name = models.CharField(max_length=100)
city = models.CharField(max_length=50)
area = models.CharField(max_length=50)
room = models.CharField(max_length=20)
room_area = models.FloatField()
price = models.FloatField()
type = models.CharField(max_length=10)
images = models.TextField()
statis = models.FloatField(default=0)
class Meta:
db_table = 'house'
3.3 可视化分析模块
前端使用ECharts实现多种可视化图表,后端提供数据接口:
python复制def data(request):
db = mysql().connection(DATABASE)
# 房型价格分析
room = db.table("house").group("room").field("room as name,avg(price) as value").order("value desc").limit(10).select()
# 热门城市分析
hot_city = db.table("house").group("city").field("city as name,count(*) as value").order("value desc").select()
# 北京区域价格分析
bj_area_price = db.table("house").where("city = '北京'").field("area as name,price as value").order("value desc").select()
bj_area_price = [[i["name"].split(",")[0], i["value"]] for i in bj_area_price]
# 面积分布分析
room_area_line = db.table("house").field("room_area as name,count(*) as value").group("room_area").select()
data = {
"room": room,
"hot_city": hot_city,
"bj_area_price": bj_area_price,
"room_area_line": room_area_line
}
return jsonResponse(0, '成功', data)
前端通过AJAX获取数据后渲染图表:
javascript复制// 初始化北京区域价格散点图
function initBjAreaPriceChart(data) {
const chart = echarts.init(document.getElementById('bj-area-price-chart'));
const option = {
title: { text: '北京各区域租金分布' },
tooltip: {},
xAxis: { type: 'category' },
yAxis: { type: 'value', name: '价格(元)' },
series: [{
type: 'scatter',
symbolSize: function (data) {
return Math.sqrt(data[1]) / 5;
},
data: data,
itemStyle: {
color: function(params) {
const colorList = ['#c23531','#2f4554','#61a0a8','#d48265','#91c7ae'];
return colorList[params.dataIndex % colorList.length];
}
}
}]
};
chart.setOption(option);
}
4. 系统特色功能实现
4.1 智能条件搜索
房源搜索功能支持多条件组合查询:
python复制def house(request):
if request.method == "GET":
page = request.GET.get("page", 1)
limit = request.GET.get("limit", 10)
keyword = request.GET.get("keyword")
area = request.GET.get("area")
price = request.GET.get("price")
room = request.GET.get("room")
type = request.GET.get("type")
condition = {}
db = mysql().connection(DATABASE)
if keyword:
condition["city"] = ["LIKE", "%{}%".format(parse.unquote_plus(keyword)), "", "e"]
if area:
if "以上" in area:
condition["room_area"] = ["GT", area.replace("以上", ""), "", "e"]
else:
min_area = area.split("-")[0]
max_area = area.split("-")[1].replace("㎡", "").replace("以上", "")
condition["room_area"] = ["BETWEEN", [min_area, max_area], '', 'e']
if price:
if "以上" in price:
condition["price"] = ["GT", price.replace("万", "").replace("以上", ""), "", "e"]
else:
min_price = price.split("-")[0]
max_price = price.split("-")[1].replace("/月", "")
condition["price"] = ["BETWEEN", [min_price, max_price], '', 'e']
if room:
condition["room"] = ["LIKE", "%{}%".format(room.replace("以上", "")), "", "e"]
if type:
condition["type"] = type
if len(condition) > 0:
count = db.table('house').where(condition).count()
data = db.table('house').where(condition).page(page, limit).order("id desc").select()
else:
count = db.table('house').count()
data = db.table('house').page(page, limit).order('id desc').select()
return jsonResponse(0, 'success', data, count)
4.2 用户评论与互动
评论系统实现了以下功能:
- 评论发布
- 评论列表展示
- 评论分页
- 评论统计
核心代码实现:
python复制def comment(request):
db = mysql().connection(DATABASE)
if request.method == "GET":
page = request.GET.get("page", 1)
limit = request.GET.get("limit", 10)
house_id = request.GET.get("house_id")
condition = {"house_id": house_id} if house_id else {}
count = db.table('comment').where(condition).count()
data = db.table('comment').where(condition)
.page(page, limit)
.order('id desc')
.select()
return jsonResponse(0, 'success', data, count)
elif request.method == "POST":
data = json.loads(request.body)
user_id = get_user_id_from_token(request)
if not user_id:
return jsonResponse(1, '请先登录')
comment_data = {
'house_id': data['house_id'],
'user_id': user_id,
'content': data['content'],
'create_time': datetime.now()
}
result = db.table('comment').add(comment_data)
if result:
# 更新房源评论数
db.table('house').where({"id": data['house_id']}).setInc('comment_count')
return jsonResponse(0, '评论成功')
return jsonResponse(1, '评论失败')
4.3 后台管理系统
后台管理采用Django Admin二次开发,主要功能包括:
- 用户管理
- 房源管理
- 评论管理
- 数据统计
关键实现点:
python复制from django.contrib import admin
from .models import House, User, Comment
class HouseAdmin(admin.ModelAdmin):
list_display = ('name', 'city', 'area', 'room', 'price')
list_filter = ('city', 'type')
search_fields = ('name', 'city')
list_per_page = 20
fieldsets = (
('基本信息', {
'fields': ('name', 'city', 'area')
}),
('房源详情', {
'fields': ('room', 'room_area', 'price', 'type', 'images')
}),
)
admin.site.register(House, HouseAdmin)
admin.site.register(User)
admin.site.register(Comment)
5. 部署与优化
5.1 系统部署方案
项目采用Nginx + uWSGI + Django的生产环境部署方案:
- Nginx配置示例:
nginx复制server {
listen 80;
server_name yourdomain.com;
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8000;
}
location /static/ {
alias /path/to/your/static/files/;
}
}
- uWSGI配置(uwsgi.ini):
ini复制[uwsgi]
chdir = /path/to/your/project
module = project.wsgi:application
master = true
processes = 4
socket = 127.0.0.1:8000
vacuum = true
5.2 性能优化措施
- 数据库优化:
- 为常用查询字段添加索引
- 使用select_related/prefetch_related减少查询次数
- 合理使用缓存
- 前端优化:
- 使用CDN加载静态资源
- 图表数据懒加载
- 合理使用浏览器缓存
- 爬虫优化:
- 使用代理池防止IP被封
- 实现断点续爬功能
- 分布式爬虫架构(如需大规模采集)
6. 项目扩展方向
这个项目还有很大的扩展空间:
- 增加更多数据源:除了58同城,可以接入链家、贝壳等平台的租房数据
- 实现个性化推荐:基于用户浏览历史和偏好推荐合适房源
- 增加价格预测功能:利用机器学习算法预测未来租金走势
- 开发移动端应用:提供更便捷的移动访问体验
- 实现自动化监控:对异常价格变动进行预警
在实际教学中,我发现学生们对这个项目特别感兴趣,因为它结合了爬虫、Web开发和数据分析等多个热门技术方向。通过完成这个项目,学生能够掌握完整的Web系统开发流程,对未来的就业或深造都有很大帮助。