广东省租房可视化与推荐系统:基于Django的全栈开发实践

摘要

本文详细介绍了一个基于Python的web框架(Django)开发的广东省租房可视化与推荐系统的完整开发过程。系统集成了数据爬取、可视化分析、个性化推荐等核心功能,为租房用户提供全面的信息服务。


第一章:项目背景与需求分析

1.1 项目背景

随着广东省城市化进程的加快,租房市场需求日益增长。传统租房平台存在信息分散、数据分析不足、推荐不精准等问题。本项目旨在构建一个集数据采集、可视化分析和智能推荐于一体的综合性租房平台。

1.2 核心需求

  • 数据采集需求:实时获取广东省主要城市的租房信息
  • 可视化需求:提供多维度全方位的数据可视化动态图表分析
  • 推荐需求:基于用户行为实现个性化房源推荐
  • 用户体验需求:简洁直观的界面设计和流畅的交互体验

第二章:技术选型与系统架构

2.1 技术栈选择

后端技术
  • 框架:Django 5.2.11
  • 数据库:MySQL 8.0+
  • ORM:Django内置ORM(用户直接对数据库操作)
前端技术
  • UI框架:Bootstrap 5
  • 可视化库:ECharts
  • 模板引擎:Django模板
  • JavaScript:原生JS + jQuery
爬虫技术
  • 请求库:Requests
  • 解析库:lxml
  • 数据存储:CSV + MySQL双存储

2.2 系统架构设计

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   数据采集层     │    │   业务逻辑层     │    │   表现层        │
│  - 网络爬虫     │───▶│  - Django视图   │───▶│  - 前端模板     │
│  - 数据清洗     │    │  - 推荐算法     │    │  - 可视化图表   │
│  - 数据存储     │    │  - 业务逻辑     │    │  - 用户界面     │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                        │                        │
         ▼                        ▼                        ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   数据存储层     │    │   服务层         │    │   客户端        │
│  - MySQL数据库  │    │  - Web服务器    │    │  - 浏览器       │
│  - 静态文件     │    │  - 缓存服务     │    │  - 移动设备     │
└─────────────────┘    └─────────────────┘    └─────────────────┘

第三章:数据库设计与实现

3.1 核心数据模型

用户表(User)
class User(models.Model):
    id = models.AutoField('id', primary_key=True)
    username = models.CharField(verbose_name="姓名", max_length=22)
    password = models.CharField(verbose_name="密码", max_length=32)
    phone = models.CharField(verbose_name="手机号", max_length=11)
    email = models.CharField(verbose_name="邮箱", max_length=22)
    time = models.DateField(verbose_name="创建时间", auto_now_add=True)
    avatar = models.FileField(verbose_name="头像", upload_to="user/")
房源表(Rental)
class Rental(models.Model):
    title = models.CharField(max_length=255, verbose_name='标题')
    type = models.CharField(max_length=50, verbose_name='类型')
    layout = models.CharField(max_length=50, verbose_name='布局')
    orientation = models.CharField(max_length=50, verbose_name='朝向')
    city = models.CharField(max_length=50, verbose_name='城市')
    district = models.CharField(max_length=50, verbose_name='行政区')
    street = models.CharField(max_length=100, verbose_name='街道')
    area = models.FloatField(verbose_name='面积')
    price = models.IntegerField(verbose_name='价格')
    tags = models.TextField(verbose_name='标签')
    detail = models.TextField(verbose_name='详情')
    imgs = models.TextField(verbose_name='图片链接')
    oid = models.CharField(unique=True, max_length=100, verbose_name='房源ID')
用户行为表
# 浏览历史表
class BrowseHistory(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    house = models.ForeignKey(Rental, on_delete=models.CASCADE)
    browse_time = models.DateTimeField('浏览时间', auto_now_add=True)

# 用户收藏表
class Favorites(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    house = models.ForeignKey(Rental, on_delete=models.CASCADE)
    count = models.IntegerField("点击次数", default=1)

第四章:数据采集模块实现

4.1 爬虫架构设计

爬虫工作流程

初始化爬虫

设置请求头

分页爬取数据

解析HTML内容

提取房源信息

数据清洗处理

保存到CSV文件

导入数据库

数据验证

4.2 核心爬虫代码

import requests
from lxml import etree
import csv
import time

class LianjiaSpider:
    def __init__(self):
        self.headers = {
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
            'cookie': '完整的cookie信息'
        }
        self.base_url = 'https://zh.lianjia.com/zufang/pg{}/#contentList'
    
    def crawl_data(self, start_page=1, end_page=50):
        """主爬取函数"""
        for page in range(start_page, end_page + 1):
            url = self.base_url.format(page)
            try:
                response = requests.get(url, headers=self.headers)
                html = etree.HTML(response.text)
                self.parse_page(html, page)
                time.sleep(2)  # 延时防止被封
            except Exception as e:
                print(f"第{page}页爬取失败: {e}")
    
    def parse_page(self, html, page_num):
        """解析单页数据"""
        house_list = html.xpath('//div[@class="content__list"]/div')
        
        with open('guangdong_house.csv', 'a+', encoding='utf-8-sig', newline='') as f:
            writer = csv.writer(f)
            
            for house in house_list:
                try:
                    # 提取房源详细信息
                    title_info = house.xpath('.//a[@class="twoline"]/text()')[0].strip().split()
                    
                    data = {
                        'title': title_info[0].split('·')[-1],
                        'type': title_info[0].split('·')[0],
                        'layout': title_info[1],
                        'orientation': title_info[2],
                        'city': '珠海市',
                        'district': house.xpath('.//p[@class="content__list--item--des"]/a/text()')[0],
                        'street': house.xpath('.//p[@class="content__list--item--des"]/a/text()')[1],
                        'area': house.xpath('.//p[@class="content__list--item--des"]/text()')[4].strip(),
                        'price': house.xpath('.//span[@class="content__list--item-price"]/em/text()')[0],
                        'tags': house.xpath('.//p[@class="content__list--item--bottom oneline"]/i/text()'),
                        'detail_url': 'https://hz.lianjia.com/' + house.xpath('.//a[@class="content__list--item--aside"]/@href')[0],
                        'image_url': house.xpath('.//a[@class="content__list--item--aside"]/img/@data-src')[0]
                    }
                    
                    # 写入CSV文件
                    writer.writerow(list(data.values()))
                    
                except Exception as e:
                    print(f"解析房源信息失败: {e}")

4.3 数据清洗与处理

数据清洗策略
  1. 缺失值处理:删除关键信息缺失的记录
  2. 格式统一:统一价格、面积等数值格式
  3. 去重处理:基于房源ID去除重复记录
  4. 异常值检测:识别并处理异常价格和面积数据

第五章:数据可视化模块

5.1 可视化架构设计

可视化组件分类
  • 统计图表:柱状图、饼图、折线图
  • 地理信息:热力图、分布图
  • 文本分析:词云图、标签云
  • 交互组件:筛选器、排序器

5.2 ECharts集成实现

价格分布可视化
// 价格区间分布图
function renderPriceDistribution(data) {
    const chart = echarts.init(document.getElementById('price-chart'));
    
    const option = {
        title: { text: '房源价格分布' },
        tooltip: { trigger: 'axis' },
        xAxis: { 
            type: 'category',
            data: ['0-1000', '1000-2000', '2000-3000', '3000-5000', '5000+']
        },
        yAxis: { type: 'value' },
        series: [{
            data: data,
            type: 'bar',
            itemStyle: { color: '#5470c6' }
        }]
    };
    
    chart.setOption(option);
}
地理分布热力图
// 城市房源分布热力图
function renderCityHeatMap(data) {
    const chart = echarts.init(document.getElementById('city-map'));
    
    const option = {
        title: { text: '广东省各城市房源分布' },
        tooltip: { trigger: 'item' },
        visualMap: {
            min: 0,
            max: Math.max(...data.map(item => item.value)),
            calculable: true,
            inRange: { color: ['#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#fee090', '#fdae61', '#f46d43', '#d73027'] }
        },
        series: [{
            type: 'heatmap',
            coordinateSystem: 'geo',
            data: data
        }]
    };
    
    chart.setOption(option);
}

5.3 实时数据更新机制

数据更新策略
  1. 定时刷新:设置定时器定期更新数据
  2. 事件驱动:用户操作触发数据更新
  3. 增量更新:只更新变化的数据部分
  4. 缓存机制:合理使用缓存减少服务器压力

第六章:推荐算法实现

6.1 推荐系统架构

推荐算法分类
  • 基于内容的推荐:房源特征相似度匹配
  • 协同过滤推荐:用户行为模式分析
  • 混合推荐:多种算法结果融合
  • 热门推荐:基于流行度的推荐

6.2 核心推荐算法

基于内容的推荐
def content_based_recommendation(user_preferences, house_features, top_n=10):
    """基于内容的房源推荐"""
    
    # 计算房源与用户偏好的相似度
    similarities = []
    for house in house_features:
        similarity = calculate_similarity(user_preferences, house)
        similarities.append((house['id'], similarity))
    
    # 按相似度排序并返回前N个
    similarities.sort(key=lambda x: x[1], reverse=True)
    return [item[0] for item in similarities[:top_n]]

def calculate_similarity(preferences, features):
    """计算相似度"""
    # 使用余弦相似度或欧几里得距离
    # 考虑价格、面积、位置、户型等多个维度
    pass
协同过滤推荐
def collaborative_filtering(user_id, top_n=10):
    """基于用户的协同过滤推荐"""
    
    # 获取目标用户的浏览历史
    target_history = get_user_browse_history(user_id)
    
    # 找到相似用户
    similar_users = find_similar_users(user_id)
    
    # 基于相似用户的行为推荐房源
    recommendations = []
    for similar_user in similar_users:
        user_history = get_user_browse_history(similar_user.id)
        # 推荐目标用户未浏览过的房源
        new_houses = set(user_history) - set(target_history)
        recommendations.extend(new_houses)
    
    return recommendations[:top_n]

截图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

结语

广东省租房可视化与推荐系统是一个功能完整、技术先进的全栈Web应用项目。通过本项目的开发实践,我们不仅掌握了Django全栈开发的技术要点,还深入理解了数据采集、可视化分析和推荐算法的实际应用。

本项目为租房市场的数字化转型提供了有益参考,也为类似项目的开发积累了宝贵经验。未来,我们将继续优化系统性能,扩展功能模块,为用户提供更优质的租房信息服务。

最后需要该项目的同学可以私信我或者添加我下方名片获取!

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐