大数据毕业设计 住房数据分析与可视化 - python

该文分析了北上广深的租房房源分布、租金水平、地铁距离对租金的影响以及房屋大小与租金的关系。通过可视化展示,揭示了各城市租金热点区域和租房趋势,指出地铁附近房源的租金普遍较高。文章还提供了部分Python爬虫代码用于数据获取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


0 前言

🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

🚩 基于大数据住房数据分析与可视化

🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:3分
  • 工作量:3分
  • 创新点:2分

分析展示

一、北上广租房房源分布可视化

租房分布,也就是租房房源都在城市的哪个区域更多。

我们把北上广深四个城市的房源都以小点的形式投射在地图上,先来看看北京的。

在这里插入图片描述
在这里插入图片描述
结论:
北京的租房房源有18012条,可以看到除了周边的昌平、顺义、通州、大兴、房山、门头沟等区中心有集中房源外,北京的房子主要集中在二环外四环内,当然这片区域也是最贵的。其中朝阳区的房源最多,占了整个北京房源的1/3,要不咋说朝阳群众666呢。海淀、丰台次之。

在这里插入图片描述
在这里插入图片描述
结论:
上海也一样,除了周边的宝山、嘉定、青浦、松江、奉贤等区中心有房源外,房源主要集中在中心城区+浦东(地铁网范围内)。总共27311条房源,浦东就有7000多条,比例超过1/4。

在这里插入图片描述
在这里插入图片描述
结论:
广州房源在四个城市中是最多的,共有39457条,主要集中在白云、天河、越秀、荔湾,以及海珠和番禺。其中白云、天河和番禺房源都超过6000条,选择丰富,不过看图也知道,3号线通勤压力巨大。

在这里插入图片描述
在这里插入图片描述
结论:
深圳的房源共有20054条,更集中在各区,除了四个新区零星分布的房源外,主要还是分布在宝安、南山(科技园)、福田、罗湖、龙岗区中心,以及坂田、布吉、3号线沿线,11号线沿线(是市中心的租金太贵了吧?)

二、北上广内区域租金分布可视化

租房房源分布透露出来的信息其实不多,我们更关心的是各区域的价格。为此我们计算了各房源每平米每月的租金,并绘制了热力地图,先来看北京的。
在这里插入图片描述

可以看到北京市每平米租金大于100元的房子集中在四环以内以及四环东北边。租金最贵的房子集中在西城区(金融街)、东城区(王府井)、朝阳区(朝阳公园)、海淀区(北大)。想要花2000块钱租一间20平的房子,要么去五环外,要么去西南边上。在这里插入图片描述
按商圈来看,每平米平均租金前50的商圈中,北京就占了27个,上海和深圳分别是11和10个,广州最少,只有2个。

在这里插入图片描述
北京每平米平均租金前10的商圈,租金在每平米200元左右徘徊。最贵的商圈东单,每平米要239元,也就意味着,在东单租一个30平的房子,一个月需要7170块钱,租一个80平的房子,一个月需要19120元。

在这里插入图片描述
可见上海每平米租金大于100元的房源主要集中在静安、黄浦、长宁、徐汇和浦东。中心市区几乎没有每平米租金低于100元的。出了市区,房价低于100元可选择的区域还是比较多的。

在这里插入图片描述
上海每平米平均租金前10的商圈较北京要好一些,租金在170元左右徘徊。其中租金最高的商圈新天地,每平米租金为213元。

在这里插入图片描述
相较北京和上海,广州每平米月租金明显以100元以下的房源占主导。100元以上的比较零星,主要分布在体育中心、跑马场、以及岗顶站周围,荔湾、越秀中心也有一些。看来广州还是一个租房比较友好的城市啊。

在这里插入图片描述
另外可以看到位于南边的番禺区,房源多,而且基本每平米租金都在50元以内,2000元内能租一个40平的房子,番禺广场坐地铁到体育西只需半个小时,票价7元(6折4.2元),这也不失为一个选择,只是坐3号线可能被挤扁。

在这里插入图片描述

三、房源距地铁口租金的关系可视化

租房,其中一个终点考虑的因素就是距离地铁的远近。我们把个城市房源距离最近地铁站的距离跟每平米租金进行了回归分析,并且计算了相关系数。
在这里插入图片描述

可以看到,最近地铁距离和每平米租金之间当然是有相关性的,距离地铁越近,租金越贵。北上广深的相关系数分别是-0.13,-0.17,-0.12,-0.13,可见,上海地铁站的距离对租金的影响最大,广州最小。

我们还计算了各城市地铁距离每100米的租金均价。

在这里插入图片描述
可见,北京市只要地铁在900以内,每平米租金变化不大。900米和1000米租金差距为12.5元,也就是说,租一个20平的房子,距离地铁站900米和1000米的租金差距是250元。

上海市只要地铁在700以内,每平米租金变化不大,700以上租金开始明显下降。

广州市每平米租金明显比其它城市低。同样,只要地铁在900以内,租金变化不大。900米和1000米租金差距为12元。

深圳市只要地铁在400以内,租金变化不大。400米和500米租金差距为17.6元。也就是说,租一个20平的房子,距离地铁站400米和500米的租金差距是352元。

四、房屋大小与租金关系可视化

先来看这么一张图:

在这里插入图片描述

我们把各城市房源的面积和每平米均价绘制出关系图。可以看到,不管是哪个城市,出租面积在15平米以内的房子每平米租金都是最贵的,当然这里不排除租金贵的区域有更多单独出租的小房间这个原因。但是还是可以看出来,如果有认识的好友一起租大房子,不仅每平米的租金更便宜,而且还可以有一个大点的公用客厅。

结论

租个人房源好还是公寓好

现在公寓房越来越多,我们在面临选择的时候,都会想是租个人房源好还是公寓好呢?个人房源质量参差不齐,遇上好的真不容易。而公寓统一装修,风格现代,但是却有各种各样的问题(甲醛、隔音、乱收费等)。

这里给大家提供另一维度的思考:价格。
在这里插入图片描述

广州和深圳公寓数量占总房源数量的20%和51%(深圳怎么那么多公寓?)。可见广州和深圳公寓都要比个人房源贵一些,广州平均每平米贵12元,深圳贵2元。

北上广深租房时都看重什么

统计了北上广深各城市房源最多的3种户型。

在这里插入图片描述
可见,北上广都偏爱2室1厅1卫的房子,而深圳却是1室0厅1卫的房子最多,看来,在深圳奋斗的人,能住带厅的房子已经不容易了。不过四个城市都是小户型出租的居多。

最后,我们对每个房源的标签进行了统计,并且绘制了词云图,可以看出各城市租房时思考的侧重点。

数据库爆炸图
在这里插入图片描述

部分实现代码

import os
import re
import time
import requests
from pymongo import MongoClient
from info import rent_type, city_info


class Rent(object):
    """
    初始化函数,获取租房类型(整租、合租)、要爬取的城市分区信息以及连接mongodb数据库
    """
    def __init__(self):
        self.rent_type = rent_type
        self.city_info = city_info

        host = os.environ.get('MONGODB_HOST', '127.0.0.1')  # 本地数据库
        port = os.environ.get('MONGODB_PORT', '27017')  # 数据库端口
        mongo_url = 'mongodb://{}:{}'.format(host, port)
        mongo_db = os.environ.get('MONGODB_DATABASE', 'Lianjia')
        client = MongoClient(mongo_url)
        self.db = client[mongo_db]
        self.db['zufang'].create_index('m_url', unique=True)  # 以m端链接为主键进行去重

    def get_data(self):
        """
        爬取不同租房类型、不同城市各区域的租房信息
        :return: None
        """
        for ty, type_code in self.rent_type.items():  # 整租、合租
            for city, info in self.city_info.items():  # 城市、城市各区的信息
                for dist, dist_py in info[2].items():  # 各区及其拼音
                    res_bc = requests.get('https://m.lianjia.com/chuzu/{}/zufang/{}/'.format(info[1], dist_py))
                    pa_bc = r"data-type=\"bizcircle\" data-key=\"(.*)\" class=\"oneline \">"
                    bc_list = re.findall(pa_bc, res_bc.text)
                    self._write_bc(bc_list)
                    bc_list = self._read_bc()  # 先爬取各区的商圈,最终以各区商圈来爬数据,如果按区爬,每区最多只能获得2000条数据

                    if len(bc_list) > 0:
                        for bc_name in bc_list:
                            idx = 0
                            has_more = 1
                            while has_more:
                                try:
                                    url = 'https://app.api.lianjia.com/Rentplat/v1/house/list?city_id={}&condition={}' \
                                          '/rt{}&limit=30&offset={}&request_ts={}&scene=list'.format(info[0],
                                                                                                     bc_name,
                                                                                                     type_code,
                                                                                                     idx*30,
                                                                                                     int(time.time()))
                                    res = requests.get(url=url, timeout=10)
                                    print('成功爬取{}市{}-{}的{}第{}页数据!'.format(city, dist, bc_name, ty, idx+1))
                                    item = {'city': city, 'type': ty, 'dist': dist}
                                    self._parse_record(res.json()['data']['list'], item)

                                    total = res.json()['data']['total']
                                    idx += 1
                                    if total/30 <= idx:
                                        has_more = 0
                                    # time.sleep(random.random())
                                except:
                                    print('链接访问不成功,正在重试!')

    def _parse_record(self, data, item):
        """
        解析函数,用于解析爬回来的response的json数据
        :param data: 一个包含房源数据的列表
        :param item: 传递字典
        :return: None
        """
        if len(data) > 0:
            for rec in data:
                item['bedroom_num'] = rec.get('frame_bedroom_num')
                item['hall_num'] = rec.get('frame_hall_num')
                item['bathroom_num'] = rec.get('frame_bathroom_num')
                item['rent_area'] = rec.get('rent_area')
                item['house_title'] = rec.get('house_title')
                item['resblock_name'] = rec.get('resblock_name')
                item['bizcircle_name'] = rec.get('bizcircle_name')
                item['layout'] = rec.get('layout')
                item['rent_price_listing'] = rec.get('rent_price_listing')
                item['house_tag'] = self._parse_house_tags(rec.get('house_tags'))
                item['frame_orientation'] = rec.get('frame_orientation')
                item['m_url'] = rec.get('m_url')
                item['rent_price_unit'] = rec.get('rent_price_unit')

                try:
                    res2 = requests.get(item['m_url'], timeout=5)
                    pa_lon = r"longitude: '(.*)',"
                    pa_lat = r"latitude: '(.*)'"
                    pa_distance = r"<span class=\"fr\">(\d*)米</span>"
                    item['longitude'] = re.findall(pa_lon, res2.text)[0]
                    item['latitude'] = re.findall(pa_lat, res2.text)[0]
                    distance = re.findall(pa_distance, res2.text)
                    if len(distance) > 0:
                        item['distance'] = distance[0]
                    else:
                        item['distance'] = None
                except:
                    item['longitude'] = None
                    item['latitude'] = None
                    item['distance'] = None

                self.db['zufang'].update_one({'m_url': item['m_url']}, {'$set': item}, upsert=True)
                print('成功保存数据:{}!'.format(item))

    @staticmethod
    def _parse_house_tags(house_tag):
        """
        处理house_tags字段,相当于数据清洗
        :param house_tag: house_tags字段的数据
        :return: 处理后的house_tags
        """
        if len(house_tag) > 0:
            st = ''
            for tag in house_tag:
                st += tag.get('name') + ' '
            return st.strip()

    @staticmethod
    def _write_bc(bc_list):
        """
        把爬取的商圈写入txt,为了整个爬取过程更加可控
        :param bc_list: 商圈list
        :return: None
        """
        with open('bc_list.txt', 'w') as f:
            for bc in bc_list:
                f.write(bc+'\n')

    @staticmethod
    def _read_bc():
        """
        读入商圈
        :return: None
        """
        with open('bc_list.txt', 'r') as f:
            return [bc.strip() for bc in f.readlines()]


if __name__ == '__main__':
    rent = Rent()
    rent.get_data()

最后

### 安居客出租房(武汉为例)爬虫+数据分析+可视化 这个爬虫是我前段时间在淘宝上做单子的时候遇见的一个客户需求。本来以为就是一个简单的爬虫项目。但后面客户加了数据清洗和数据分析的要求。而后又加了要详细代码解释的需求等等。直到最后客户坦白说这是他们大专的毕设.......但是这个单子坐下来只有200左右,我想了一下,感觉好亏啊。在淘宝上随便找一个做毕设的都要好多钱的,而且客户本身的代码能力、数学、逻辑能力都很差,导致我每行都给注释以及看不懂,在我交付代码后又纠缠了我一个多礼拜。反正总体做下来的感觉就是烦躁。头一次感觉到了客户需求变更带来的巨大麻烦。 总之这是一次不是很愉快的爬虫经历。但是作为我写爬虫以来注释最详细的一次,以及第一次真正使用像matplotlib这种数据分析库的代码,我认为还是有必要分享出来给大家当个参考的(PS:大佬轻拍~)。爬虫本身几乎没有什么难度,写的也比较乱,敬请见谅。 **功能** 爬取安居客上的出租房信息(武汉地区的),并通过爬取的数据进行数据清洗以及数据分析。给出四个不同层面的可视化图。最终结果如下图所示: ![Image text](https://raw.githubusercontent.com/srx-2000/git_spider/master/anjuke_room_rent_info/result/1.png) ![Image text](https://raw.githubusercontent.com/srx-2000/git_spider/master/anjuke_room_rent_info/result/2.png) ![Image text](https://raw.githubusercontent.com/srx-2000/git_spider/master/anjuke_room_rent_info/result/3.png) ![Image text](https://raw.githubusercontent.com/srx-2000/git_spider/master/anjuke_room_rent_info/result/4.png) **环境** 1. Windows 10 2. python3.7 **使用方法** 首先声明该爬虫由于是特定情况下写的,所以本身的通用性特别差,仅可以对安居客网站上的武汉的出租房信息进行爬取,且需要自己手动更新cookie。同时在对数据进行分析可视化的时候由于也是特别针对武汉出租房的进行的,所以针对性也比较强。如果别的需求需要自己进行更改。 1. 访问[安居客网址](https://wuhan.anjuke.com/),获取cookie。 > tip:获取cookie的方法可根据[此链接](https://jingyan.baidu.com/article/5d368d1ea6c6e33f60c057ef.html) 2. 在项目中找到`spider.py`的文件,将第12行的cookie换成你自己的cookie。 3. 运行`spider.py`,获取房源信息。运行后应会产生一个`武汉出租房源情况.csv`的文件。此文件为我们从安居客上爬取的房源信息,其中包含`房屋租住链接、房屋描述、房屋地址、房屋详情(户型)以及经纪人、房屋价格`五个属性。 4. 在获取了数据之后我们运行`matplotlib.py`文件。进行数据清洗,分析可视化。运行后即可获得**功能**中展示四个图片。 **技术栈** 1. request 2. parsel 3. pandas 4. matplotlib **进步(相比之前)** 此次爬虫相比之前的技术上可以说有减无增。但其中注释相当详细,可谓是每行代码都有注释。所以对于初学者应该有一些用处。同时使用matplotlib进行了数据分析可视化等。对于数据处理的代码的注释也是几乎每行都有注释的。
# 1. 数据集说明 这是一份北京的租房数据,总计7000 多 条记录,分为 8 个同样结构的 CSV 数据文件。 # 2. 数据处理 首先通过 pandas 将这些数据文件合并到一起,然后进行数据处理,最后将清洗好的数据写到 sqlite 。 # 3.数据分析可视化 ## 3.1 整体情况 该数据集总共有 6024 个房源信息,平均每平米的租金为 169 元,每套房源的平均出租面积为 15.68 平米。 ## 3.2 地区分析 房源数量分布情况如下,可以看到朝阳和通州这两个地区的房源数量要远大于其它区,说明这两个地方的租赁市场比较活跃,人员流动和人口密度可能也比较大。 房租最贵的小区 TOP 10。半壁街南路 1 号院的房租最高,达到 596 元/平米,是平均值 169 元/平米的 **3** 倍。 从户型的房源数量分布来看,主要集中在 2-4 室的户型。之前也分析了,每套房源的平均出租面积为 15.68 平米,可见大部分房源都是合租,毕竟房租那么贵,生活成本太高了。 国家规定楼层 7 层以上需要装电梯,依据这个规定,我们根据楼层数来判断房源是否有电梯。 从下图可以看到,电梯房的房源数量比较多,毕竟楼层高,建的房子多,此外,电梯房平均每平米的租金也要比非电梯房贵 10 块钱。 在区分出电梯房之后,我们再引入楼层的纬度进行分析。 从租金上看,不管是电梯房还是非电梯房,低楼层的租金都会比较贵一些。因为北京地处北方,天气较干燥,不会有回南天,而且低楼层出行较为方便。电梯房的高楼层,租金也会比较贵,这大概是因为高楼层的风景较好。 > 南方天气潮湿,在春天的时候,有时会出现 回南天 这一气象,导致低楼层会出现地板、墙壁渗水,所以在南方一般都不爱租低层。 从房源数量上看,非电梯房的高层房源最多,低层房源最少。说明非电梯房的高层房源不容易租出去,这点在租金上也有所体现。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值