蛋壳公寓深圳区域数据爬取与可视化分析

基于爬虫技术抓取深圳蛋壳公寓在租房源数据,利用 Pandas 进行清洗,并通过 PyEcharts 实现多维度可视化分析。涵盖区域分布、租金区间、面积户型、楼层及地铁距离等特征,结合相关性分析探究影响定价的关键因素。结果显示房源主要集中在龙岗等行政区,租金多在 1000-2000 元,面积以 10-20㎡为主,地铁配套对价格有显著影响。


最近蛋壳公寓频频暴雷,这篇文章将深圳蛋壳的住房数据的爬取下来进行实战分析。
2020 年以来,受疫情冲击、政策监管收紧等多重因素影响,长租公寓可谓路途坎坷。根据中国房地产报不完全统计,今年最近几个月时间里,暴雷的长租公寓累计达到 20 多家,数十万租客受到影响。
蛋壳公寓,凭借着长租公寓风口,用 5 年时间,做到了分散式长租公寓第二,仅次于自如。于 2020 年 1 月 17 日在纽约证券交易所正式挂牌上市,成为 2020 年登陆纽交所的中国第一股。然而,风口退去,加之突如其来的疫情,于近日暴雷,已有很多文章对蛋壳公寓的商业模式、租金贷、管理方式等进行了深入分析。
本文仅从数据角度出发,爬取了蛋壳公寓深圳区域所有在租公寓信息,清洗数据,并进行可视化分析,为大家了解蛋壳公寓提供一个新的视角。

通过绘制深圳市蛋壳公寓分布地图,我们可以很直观的看出,蛋壳公寓主要分布在深圳的发展中心以及轴线上,前海中心与福田罗湖中心的公寓租金价格明显高于其他区域。轴线基于便捷的轨道交通串联,周边配套较为齐全,满足了广大年轻白领的租住需求。

具体从行政区分布来看,龙岗区虽然整体公寓租金相对更低,但公寓数量高于福田和南山区。蛋壳公寓的分布与贝壳找房较为类似,但贝壳在租房源数量上远高于蛋壳。

从小区分布来看,位于龙岗区的锦荟 PARK 在租公寓最多,共有 83 个房源。

锦荟 PARK 周边配套齐全,地铁上盖,靠近大生体育公园,1 公里内产业配套有金辉工业园、志华工业园、中和盛世珠宝文化创意创新产业园等,对劳动力具有一定吸引力。同时还有医院、文体广场等,可以满足都市白领生活一站式服务需求。

深圳蛋壳公寓平均租金为 1911 元/月,第一、第二、第三四分位数分别为 1530,1870,2192,说明房租还是比较集中的。

对深圳蛋壳公寓租金进行分段,我们发现公寓的价格主要集中在 1000-2000 元/月之间,共计 2995 个,占比 59.71%。其次是 2000-3000 元/月,数量为 1798,占比 35.84%。

深圳蛋壳公寓面积集中在 10㎡以下和 10-20㎡,10-20㎡的公寓共有 2415 个,占比达 48.14%,10㎡以下的公寓也不少,数量为 2206 个,占比 43.98%。

深圳蛋壳公寓在租的房屋户型大部分为 4 室 1 卫,占比高达 58.64%,其次是 5 室 1 卫,占比 18.72%。

从深圳蛋壳公寓所在楼层分布来看,其南山区和福田区的公寓所在楼层相对更高。

大多数的公寓分布在 10 层以下,占比 58.59%,40 层以上的公寓仅有 42 个,占比 0.84%。

深圳蛋壳公寓普遍距离地铁较近,平均距离为 592 米,距离地铁最远的公寓也不到 2 公里,完全可以步行解决轨道出行问题。

从相关系数表可以看出,深圳蛋壳公寓的面积、周边地铁数对公寓的价格有较大的的影响,相关系数分别为 0.54 和 0.22。蛋壳公寓在进行房屋定价时,对公寓的面积以及公寓的地铁配套有较大权重的考虑。由于深圳蛋壳所有的公寓距离地铁都不到 2 公里,距离的远近对公寓的价格影响有限。另外,所在楼层也不是蛋壳主要考虑的定价因素。

蛋壳公寓网页结构相对简单,数据结构统一,简单的 url 翻页构造即可。本文用 request 请求到数据,用 xpath 对返回的数据进行解析,最后以追加模式将数据存储为 csv 文件。爬虫核心代码如下:
def get_danke(href):
time.sleep(random.uniform(0, 1)) # 设置延时,避免对服务器产生压力
response = requests.get(url=href, headers=headers)
if response.status_code == 200:
# 部分网页会跳转 404,需要做判断
res = response.content.decode('utf-8')
div = etree.HTML(res)
items = div.xpath("/html/body/div[3]/div[1]/div[2]/div[2]")
for item in items:
house_price = item.xpath("./div[3]/div[2]/div/span/div/text()")[0]
house_area = item.xpath("./div[4]/div[1]/div[1]/label/text()")[0].replace('建筑面积:约', '').replace('㎡(以现场勘察为准)', '')
house_id = item.xpath("./div[4]/div[1]/div[2]/label/text()")[0].replace('编号:', '')
house_type = item.xpath("./div[4]/div[1]/div[3]/label/text()")[0].replace('\n', '').replace(' ', '').replace('户型:', '')
house_floor = item.xpath("./div[4]/div[2]/div[3]/label/text()")[0].replace('楼层:', '')
house_postion_1 = item.xpath("./div[4]/div[2]/div[4]/label/div/a[1]/text()")[0]
house_postion_2 = item.xpath("./div[4]/div[2]/div[4]/label/div/a[2]/text()")[0]
house_postion_3 = item.xpath("./div[4]/div[2]/div[4]/label/div/a[3]/text()")[0]
house_subway = item.xpath("./div[4]/div[2]/div[5]/label/text()")[0]
else:
house_price = ""
house_area = ""
house_id = ""
house_type = ""
house_floor = ""
house_postion_1 = ""
house_postion_2 = ""
house_postion_3 = ""
house_subway = ""
import pandas as pd
import re
df = pd.read_csv('/菜 J 学 Python/数据分析/蛋壳公寓/sz_danke.csv')
df.sample(10)
数据预览
df.info()
数据信息
# 租金分段
df['租金分段'] = pd.cut(df['价格'], [0, 1000, 2000, 3000, 4000, 1000000], labels=['1000 元以下', '1000-2000 元', '2000-3000 元', '3000-4000 元', '4000 元以上'], right=False)
# 面积分段
df['面积分段'] = pd.cut(df['面积'], [0, 10, 20, 30, 40, 1000000], labels=['10㎡以下', '10-20㎡', '20-30㎡', '30-40㎡', '40㎡以上'], right=False)
# 楼层分段
df['所在楼层'] = df['楼层'].apply(lambda x: x.split('/')[0])
df['所在楼层'] = df['所在楼层'].astype("int")
df['楼层分段'] = pd.cut(df['所在楼层'], [0, 10, 20, 30, 40, 1000000], labels=['10 层以下', '10-20 层', '20-30 层', '30-40 层', '40 层以上'], right=False)
def get_subway_num(row):
subway_num = row.count('号线')
return subway_num
def get_subway_distance(row):
distance = re.search(r'\d+(?=米)', row)
if distance == None:
return -1
else:
return distance.group()
df['地铁数'] = df['地铁'].apply(get_subway_num)
df['距离地铁距离'] = df['地铁'].apply(get_subway_distance)
df['距离地铁距离'] = df['距离地铁距离'].astype("int")
# 柱状图
df3 = df["位置 1"].value_counts()
df3 = df3.sort_values(ascending=False)
df3 = df3.round(2)
c = (Bar(init_opts=opts.InitOpts(theme=ThemeType.WALDEN))
.add_xaxis(df3.index.to_list())
.add_yaxis("", df3.to_list())
.set_global_opts(title_opts=opts.TitleOpts(title="各行政区公寓数量", subtitle="数据来源:蛋壳公寓", pos_left='left'),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=14)),
yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=14)))
.set_series_opts(label_opts=opts.LabelOpts(font_size=16)))
c.render_notebook()
# 条形图
df7 = df["小区"].value_counts()[:10]
df7 = df7.sort_values(ascending=True)
df7 = df7.tail(10)
print(df7.index.to_list())
print(df7.to_list())
c = (Bar(init_opts=opts.InitOpts(theme=ThemeType.WALDEN))
.add_xaxis(df7.index.to_list())
.add_yaxis("", df7.to_list()).reversal_axis() # X 轴与 y 轴调换顺序
.set_global_opts(title_opts=opts.TitleOpts(title="小区公寓数量 TOP10", subtitle="数据来源:蛋壳公寓", pos_left='left'),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)),
yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(font_size=13)))
.set_series_opts(label_opts=opts.LabelOpts(font_size=16, position='right')))
c.render_notebook()
# 玫瑰图
df11 = df["租金分段"].value_counts()
df11 = df11.sort_values(ascending=False)
df11 = df11.round(2)
print(df11)
c = (Pie(init_opts=opts.InitOpts(theme=ThemeType.WALDEN))
.add("", [list(z) for z in zip(df11.index.to_list(), df11.to_list())], radius=["30%", "70%"], rosetype='area')
.set_global_opts(legend_opts=opts.LegendOpts(is_show=False), title_opts=opts.TitleOpts(title="蛋壳公寓租金分布", subtitle="数据来源:蛋壳公寓", pos_top="0.5%", pos_left='left'))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%", font_size=16)))
c.render_notebook()
# 漏斗图
count = df['楼层分段'].value_counts()
job = list(count.index)
job_count = count.values.tolist()
from pyecharts.charts import Funnel
c = (Funnel(init_opts=opts.InitOpts(theme=ThemeType.WALDEN))
.add("", [list(i) for i in zip(job, job_count)])
.set_global_opts(title_opts=opts.TitleOpts(title="蛋壳公寓楼层分布", subtitle="数据来源:蛋壳公寓", pos_top="0.1%", pos_left='left'), legend_opts=opts.LegendOpts(is_show=False))
.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}:{d}%", font_size=16)))
c.render_notebook()

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
暂无推荐文章,稍后可再来查看。
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online
基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online
解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online