Python宜昌房源数据获取与分析

一、写在前面
周末闲来无事,最近在关心房子的问题,就突发奇想写个博客,正好把之前学习的知识复习整理一下,也为需要买房的同事提供一点点启发。整个搞完工作量不小,算是一个小项目。过程有两大部分,一是宜昌(夷陵区)房源数据获取,二是对获取的数据进行分析,发现一些有趣问题与现象。
二、数据获取
在网上获取数据首先想到的肯定是写爬虫。关于爬虫目前我只会写一些简单的,大神专属Scrapy框架暂时不会用,但对于常规数据爬取(电影信息、图片、评论等)已经够了。这里需要友情感谢一下链家网,对于爬虫新手简直不要太友好,不会担心把人家网站搞崩溃,相当于链家在告诉你:“没事,我网站里的资源你随便爬,网站崩了算我输”。爬虫代码如下,这里就不多bb了,熟悉的能看懂,不熟悉的童鞋就来看热闹吧O(∩_∩)O~

import requests
from lxml import etree
import pandas as pd
import re

headers={
    
    
        'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3741.400 QQBrowser/10.5.3868.400'
        }
class House_price_analyze:
    def __init__(self,city_name,district_name,house_num):
        self.city_name = city_name
        self.district_name = district_name
        self.house_num = house_num
        self.urls = []
  
    def Page_urls(self):
        for i in range(1, int(self.house_num / 30) + 1):
            out_url = 'https://'+self.city_name+'.lianjia.com/ershoufang/'+self.district_name+'/pg' + str(i) + '/'
            response = requests.get(out_url,headers=headers)
            res_xpath = etree.HTML(response.text)
            inner_url = res_xpath.xpath("//ul[@class='sellListContent']/li/a/@href")
            for item in inner_url:
                self.urls.append(item)

    def Basic_information(self):
        self.Data = []
        self.success_count = 0
        self.fail_count = 0
        for url in self.urls:
            response = requests.get(url,headers=headers)
            try:
                introduce = re.findall(r"<title>(.*?)</title>", response.text)[0]
                community_name =  re.findall(r'class="info no_resblock_a">(.*?)</a>', response.text)[0]
                main_info =  re.findall(r'<div class="mainInfo">(.*?)</div>', response.text)[0]
                area = re.findall(r'</div><div class="area"><div class="mainInfo">(.*?)</div>', response.text)[0]
                sub_info =  ''.join(re.findall(r'<div class="subInfo">(.*?)</div>', response.text))
                unit_price = re.findall(r'<span class="unitPriceValue">(.*?)<i>', response.text)[0]
                total_price = re.findall(r'<span class="total">(.*?)</span>', response.text)[0]
                pattern = re.findall(r"resblockPosition:'(.*?)'", response.text)[0]
                longitude = pattern.split(',')[0]
                latitude  = pattern.split(',')[1]
                               
                data = {
    
    
                    'introduce':introduce,
                    'community_name':community_name,
                    'main_info':main_info,
                    'area':area,
                    'sub_info':sub_info,
                    'unit_price':unit_price,
                    'total_price':total_price,
                    'longitude':longitude,
                    'latitude':latitude
                    }
                self.success_count += 1
                print(data,'第' + str(self.success_count) + '个爬取成功')
                self.Data.append(data)
            except:                
                self.fail_count += 1
                print('第' + str(self.fail_count) + '个数据产生异常')
                pass
        
        house_data = pd.DataFrame(self.Data)
        house_data.to_csv(self.city_name + '_' + self.district_name + '_Basic_infomation.csv')

Yichang = House_price_analyze('yichang', 'yilingqu', 1200)
Yichang.Page_urls()
data = Yichang.Basic_information()
print('抓取成功,共成功抓取抓取{}条信息,失败{}条'.format(Yichang.success_count,Yichang.fail_count))

这里采集了1200条夷陵区的房源数据,数据内容包括有(房东描述、小区名字、户型、楼高、建筑结构、是否精装、面积、总价、均价、地理位置(经纬度))。下图展示的数据其实不是爬取的原始数据,我在去掉area列尾部的“平米”字符时不小心把sub_info列给删掉了,不想重新爬(爬一下得半个多小时(┭┮﹏┭┮)),又考虑到对后面数据分析的影响不大,所以就用这个来分析。
获取的房源数据

二、数据分析
首先用drop_duplicates方法去掉重复44条重复数据,剩下1156条。
1、看一下我们关心的房屋面积、均价、总价数据的整体情况。

import pandas as pd
import seaborn as sns

house_data = pd.read_csv(r'yichang_yilingqu_Basic_infomation.csv')
house_data = house_data.drop_duplicates(subset = 'introduce')
house_data_describe = house_data[['area','unit_price','total_price']]
print(house_data_describe.describe())

运行结果如下:可以发现目前夷陵区房价的均值为每平米6841元,总价均值为87.14万元。

              area    unit_price  total_price
count  1156.000000   1156.000000  1156.000000
mean    126.142189   6841.746540    87.146946
std      52.835946   1403.095185    49.650589
min      34.000000   3424.000000    16.000000
25%      96.460000   5938.750000    63.000000
50%     122.000000   6792.500000    79.800000
75%     137.025000   7613.250000    95.650000
max     738.680000  16322.000000   665.000000

2、绘制面积与总价的散点图观察总体数据。如下图,我们可以观察到一些比较特殊(离散)的样本,比如面积超过了700平米或者总价超过400万的样本,看到这些样本,我不禁纳闷,面积超过了700平米的是什么房子?夷陵区还会有房价过400万的吗?

sns.scatterplot(x = 'area',y = 'total_price',data = house_data)

房屋总价与面积散点图
我们把面积大于400平米,房价大于400万的房子揪出来看看怎么回事。

house_data = house_data[(house_data['area'] > 400) | (house_data['total_price'] > 400)]
print(house_data['introduce'])

运行结果:

266    国宾一号别墅,诚心出售,独栋独院_宜昌夷陵区夷陵区国宾一号A区二手房(宜昌链家)
320    夷陵万达旁 稀有独栋别墅 户型好 有大花园_宜昌夷陵区夷陵区国宾一号A区二手房(宜昌链家)
465    私房整栋出售,一楼门面,二..四楼可出租可居住_宜昌夷陵区夷陵区黄金路25号二手房(宜昌链家)
600    国宾一号联排别墅 精装修业主自住房出租 可看一线湖景_宜昌夷陵区夷陵区国宾一号A区二手房(...
963    长江市场繁华地段,独栋别墅.大花园大露台_宜昌夷陵区夷陵区玛歌庄园二手房(宜昌链家)
1199   昌耀电力别墅区三层别墅 全新毛坯可以几代同堂_宜昌夷陵区夷陵区昌耀沁园二手房(宜昌链家)

从结果可以看到基本上都是别墅,所以房价高在情理之中。但其中有一个(465号)是整栋楼一起出售,还真是活久见,果然贫穷限制了我的想象。

3、看到这里,也许有的小伙伴会比较好奇别墅、精装房的面积与价格会如何分布?下面用图直观展示给大家(这里我去除了一些离散的样本,这样更直观)。

f, [ax1,ax2] = plt.subplots(1,2,figsize=(10,5))
sns.set_style({
    
    'font.sans-serif':['simhei','Arial']})
sns.scatterplot(x = 'area',y = 'total_price',hue = 'villa',data = house_data,ax = ax1)
ax1.set_title('房屋面积与总价的关系(别墅与商品房)',fontsize = 10)
ax1.set_xlabel('房屋面积')
ax1.set_ylabel('房屋总价')

sns.scatterplot(x = 'area',y = 'total_price',hue = 'hardcover',data = house_data,ax = ax2)
ax2.set_title('房屋面积与总价的关系(精装与简装)',fontsize = 10)
ax2.set_xlabel('房屋面积')
ax2.set_ylabel('房屋总价')

运行结果:可以发现别墅(villa)是真的贵,最便宜的也得150万,绝大多数都是200w+。接下来看精装房(hardcover)的样本:在面积相同的情况下,精装房的整体总价在非精装房之上,这点可以很直观地发现,也很好理解,人家装修也得花钱对不对,装修不花钱,那建筑工人吃饭总得花钱吧 (`・ω・´)
在这里插入图片描述
4、使用热力图来看看夷陵区房子的总体面积与售价情况。

g = sns.jointplot(x=house_data['area'], y=house_data['total_price'], kind="hex", color="b")
g.add_legend()

运行结果:可以发现夷陵区房子面积有两个集中的区间,分别是85到95,125到135。房价多集中在75w~100w之间。
在这里插入图片描述
5、采用分类数据来观察样本分布。主要回答了“夷陵区各种户型的占比情况如何?”以及“哪些小区房源比较充足?”两个问题。

f, [ax1,ax2] = plt.subplots(1,2,figsize=(30,5))
sns.set_style({
    
    'font.sans-serif':['simhei','Arial']})
df_house_count_1 = house_data.groupby('main_info')['total_price'].count().sort_values(ascending=False).to_frame().reset_index()
df_house_count_2 = house_data.groupby('community_name')['total_price'].count().sort_values(ascending=False).to_frame().reset_index()

sns.barplot(x='main_info',y='total_price',data = df_house_count_1[df_house_count_2['total_price'] > 30],ax = ax1)
ax1.set_title('各户型在售数量',fontsize = 10)
ax1.set_xlabel('户型')
ax1.set_ylabel('数量(个)')

sns.barplot(x='community_name',y='total_price',data = df_house_count_2[df_house_count_2['total_price'] > 30],ax = ax2)
ax2.set_title('各小区在售数量',fontsize = 10)
ax2.set_xlabel('小区')
ax2.set_ylabel('数量(个)')

运行结果如下:可以发现有超过600套的户型是3室2厅,整体占比超过了在售数量的50%。在各小区房源数量上看,恒大绿洲的房源最充足,有70多套,其他几个主要小区(清江润城、钓鱼台等)在售都在50套左右,数量尚可。
在这里插入图片描述
6、我们知道,市场价格与房源数量肯定是存在关系的,那么问题就来了:到底哪些小区的房价最高呢?

df = house_data[house_data['total_price'] > 80][['unit_price','community_name','total_price']]
df_1 = df.groupby(df['community_name'])['total_price'].mean().sort_values(ascending = False)[3:10]

df_1.plot(kind = 'bar')
plt.title('总价最高小区')
plt.ylabel('均价(万)')

运行结果:(这里我未考虑一些房源较少的小区(比如在售数量 < 5 ),因其定价主观偏差较大,价格不具有代表性)可以看出,小区均价最高前四是国宾一号、湖锦花园、无石山庄、花语墅。在下面的百度地图中我们可以看到,貌似这些住宅区都在湖岸、江岸边,加上别墅加持,房价想跌也跌不下来,大家看看就好╮(╯﹏╰)╭。
在这里插入图片描述
8、用百度地图展示夷陵区房价区域分布热力图。这部分比较复杂,当然最后的展示效果会很好。
首先要将数据中的经纬度和总价信息调出来,并修改成json格式才可以在百度地图API中调用。

import pandas as pd
file = open('经纬度总价.json','w')
data = pd.read_csv("yichang_yilingqu_Basic_infomation.csv")
df = data.copy()
columns = ['total_price','longitude','latitude']
df = pd.DataFrame(df,columns=columns)

for i in df.values:
    total_price = i[0]
    lng = i[1]#获取经度
    lat = i[2]#获取纬度
    str_temp = '{"lat":' + str(lat) + ',"lng":' + str(lng) +',"total_price":'+str(total_price) +'},'
    file.write(str_temp)
file.close()

转换完成后可以在当前文件夹看见名为“经纬度总价.json”的文件。接下来就开始调用百度地图API。首先你需要去百度地图官网注册一个密匙,这样才能有调用入口。注册完成后,打开这里,复制源码编辑器中的所有内容,将密匙修改为自己注册的,在var points中将自己json中的所有数据传进去,后续还可以修改一些参数,使热力图更美观。这里就不想赘述了,如果有小伙伴不清楚,麻烦点个赞,然后私聊我吧,O(∩_∩)O~
(1)填入密匙
在这里插入图片描述

(2)填入坐标及价格数据

在这里插入图片描述
(3)修改参数
在这里插入图片描述
运行结果:颜色越深房价越高,但是这其中我不知道会不会产生多个样本重叠加在同一地方造成数据变深的问题。例如:假如钓鱼台一号小区房子的均价是6500,因为这里样本较多,本来房价不是很高,但叠加在一起会不会意外使其颜色变深?搞不懂,暂时先这样,如果有知道的欢迎指正!

从图中可以看到,夷陵区的房子大量集中在黄柏河附近,因为这里是老城区。但同时也可以看到发展大道上的房子不少,房价也不低,可能这里也是夷陵区未来的发展的重点吧,当然,这也是我从房价方面妄加猜测的。

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

三、结语
我的天终终终于写完了!其实这里面的许多内容以前自己零散得摸索过,只是现在用总结的方式码出来了,其实码的过程中非常恼火,一些看起来很容易的操作就是不容易实现,例如怎么都搞不懂Dataframe的groupby函数,又只能面向百度编程,自己摸着石头过河,码起来实属不易。但再回头看看这些图,顿时觉得码代码是一个既枯燥又有趣的过程。当然,这个过程中也在不断学习成长,写完之后对爬虫、Dataframe操作、seaborn绘图熟悉多了,也算是不小的收获了。之后的学习计划多研究一下数据结构与算法,希望能早一天学习到写博客、分享经验的程度。任何幸福都来自平凡的努力与坚持,大家加油~!

猜你喜欢

转载自blog.csdn.net/weixin_44086712/article/details/113087604