目录
往期精彩内容:
房价分析(0)反爬虫机制_python爬取房价数据-CSDN博客
Python房价分析(三)支持向量机SVM分类模型-CSDN博客
1 数据介绍
1.1 数据来源
我们这里分析三个数据集:
-
数据集1:聚汇网站爬取宜昌市2011年到2021年新房房价均值以及GDP、人口数量数据,来分析影响房价的因素以及相关性;
-
数据集2:聚汇网站爬取宜昌市2011年11月份到2022年11月份的新房房价数据,用作后面预测模型的分析;
-
数据集3:链家网站爬取的宜昌市二手房的房价进行综合分析,用作分类模型的数据集
1.2 爬虫方案
通过对比58同城,安居客,房天下,链家四个网站的信息,不同网站存在一定的反爬机制,因此首先指定破解反爬策略:
- Step1.建立用户代理池,并随机抽取User-Agent;
- Step2.通过天启API获取IP,构建ip代理池,并通过代理ip访问数据网站;
- Step3.通过设置睡眠时间,有一定间隔的访问网站,获取数据;
通过bs4对网站进行解析,结合HTML语法进行网页分析,通过标签和属性去定位页面上的内容,具体步骤如下:
- Step1.获取网页url,利用通过代理池,拿到网页源代码;
- Step2.通过bs4中BeautifulSoup进行解析,拿到数据;
- Step3.最后进行数据存储;
最终数据集为:
-
数据集1:新房数据集有时间、价格两个特征,128个样本量;
-
数据集2:均值数据集有时间、GDP、人口数量、房价均值4个特征,11个样本量;
-
数据集3:二手房数据集有区域、街道、楼房名称、户型、朝向、建筑面积、楼层、装修、结构、关注、价格11个特征,3000个样本量。
2 爬虫代码实现
爬取的网站选取没有爬虫机制的链家网站、汇聚数据网站
2.1 爬取新房时间序列数据
爬取聚汇数据网站 https://www.gotohui.com
第一步,导入相关包
from urllib.request import urlopen
from bs4 import BeautifulSoup
import urllib.request
import re
import pandas as pd
第二步,创建请求头
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54'}
第三步,获取网页信息
def get_page_data(data_url,headers):
req = urllib.request.Request(data_url, headers=headers)
content = urllib.request.urlopen(req).read()#.decode('GBK')
content=content.decode('utf-8') # python3
page = BeautifulSoup(content,'html.parser')
第四步,定义时间序列格式
def get_date(date,year):
date_str = ''
if date == '1月':
date_str = year+'-'+'01'
elif date == '2月':
date_str = year+'-'+'02'
elif date == '3月':
date_str = year+'-'+'03'
elif date == '4月':
date_str = year+'-'+'04'
elif date == '5月':
date_str = year+'-'+'05'
elif date == '6月':
date_str = year+'-'+'06'
elif date == '7月':
date_str = year+'-'+'07'
elif date == '8月':
date_str = year+'-'+'08'
elif date == '9月':
date_str = year+'-'+'09'
elif date == '10月':
date_str = year+'-'+'10'
elif date == '11月':
date_str = year+'-'+'11'
elif date == '12月':
date_str = year+'-'+'12'
return date_str
第五步,解析数据
def analyse_data(page,year):
table = page.find('table',attrs={'class':'ntable table-striped'})
trs = table.find_all('tr')[2:]
df_data = pd.DataFrame(columns=['date','price'])
count = 0
for tr in trs:
tds = tr.find_all('td')
date = tds[0].text
date = get_date(date,year)
new = tds[2].text
new = new[:4]
# print(order+":"+date+"***"+old+"***"+new)
df_data.loc[count] = [date,new]
count += 1
# df_data.set_index('date',inplace=True)
return df_data
第六步,爬取数据
if __name__ == '__main__':
data_url = 'https://fangjia.gotohui.com/fjdata-176'
year = ['2011','2012','2013','2015','2016','2017','2018','2019','2020','2021','2022']
url = 'https://fangjia.gotohui.com/years/176/'+year[9]+'/'
page = get_page_data(url,headers)
df_data = analyse_data(page,year[9])
print(df_data)
2.2 爬取二手房数据
爬取链家网站 https://yichang.lianjia.com
第一步,导入相关包
from urllib.request import urlopen
from bs4 import BeautifulSoup
import urllib.request
import re
import pandas as pd
import requests
第二步,创建请求头
headers = {
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54"
}
第三步,获取网页信息
def get_page_data(data_url):
req = urllib.request.Request(data_url, headers=headers)
content = urllib.request.urlopen(req).read().decode('utf-8') # python3
page = BeautifulSoup(content, 'html.parser')
return page
第四步,数据解析
第五步,爬取数据
if __name__ == '__main__':
page_list = []
# # 页面总页数
ALL_page = 30
for i in range(ALL_page):
page_list.append('{}'.format(i+1))
# # 读取空文件
second_hand_data = pd.read_csv('second_hand_data.csv')
for i in page_list:
url = 'https://yichang.lianjia.com/ershoufang/pg' + i+ '/'
#url = "https://yichang.lianjia.com/ershoufang/pg100/"
page = get_page_data(url)
df_data = analyse_data(page)
# # 打印网页数据
print(f'第{i} 页 , 爬取{len(df_data)}条数据')
# # 写入CSV文件
second_hand_data = pd.concat([second_hand_data, df_data])
second_hand_data.set_index('house_title', inplace=True)
second_hand_data.to_csv('second_hand_data.csv')
print(second_hand_data)
按照区域分析二手房平均价格
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
import numpy as np
matplotlib.rc("font", family='Microsoft YaHei')
house_price = pd.read_csv('second_hand_data.csv')
# 按照城市各个区域的房价均值
data_by_zone = house_price.groupby('zone')
data_df = pd.DataFrame()
zone_list = []
ave_price = []
for zone,data_group in data_by_zone:
# 区域列表
zone_list.append(zone)
# 区域平均值
ave_price.append(data_group['price'].mean())
# 图表分析
plt.figure(figsize=(15,6))
plt.bar(x=zone_list,tick_label=zone_list, height=ave_price,label='房价',color='darkgreen')
plt.xticks(rotation=80)
plt.xlabel('区域')
plt.ylabel('房价')
plt.title('宜昌市各个区域的房价均值走势图')
plt.legend(loc = 'upper center')
plt.tight_layout()
plt.show()
3 基础统计分析
3.1数据归一化
做机器学习时在特征处理上,对特征数据进行归一化处理。如果机器学习模型使用梯度下降法求最优解时,归一化往往非常有必要,否则很难收敛甚至不能收敛;一些分类器需要计算样本之间的距离(如欧氏距离),如果一个特征值域范围非常大,那么距离计算就主要取决于这个特征,从而与实际情况相悖(比如这时实际情况是值域范围小的特征更重要)。我们通过sklearn包的preprocessing来对数据进行标准化处理。
3.2 描述性统计分析
对二手房房价进行正态检验、频数分析以及描述性统计分析;并对影响房价的因素以及相关性进行分析。
#通过除以每个特征的最大值将训练数据特征缩放至 [-1, 1] 范围内
from sklearn import preprocessing
X_train = np.array([
[3],
[-1],
[2]
])
max_abs_scaler = preprocessing.MaxAbsScaler()
scaler = max_abs_scaler.fit(X_train)
# 归一化
X_train = scaler.transform(X_train)
X_train
>> array([[ 1. ],
[-0.33333333],
[ 0.66666667]])
3.2.1 正态性检验
图1
变量名 | 偏度 | 峰度 | S-W检验 | K-S检验 |
Price | 1.156 | 2.499 | 0.915(0.000***) | 0.076(2.721490400428623e-15) |
表1
图1是新房价格数据的正态性检验直方图,正态分布的检验方法有两种,一种是Shapiro-Wilk检验,适用于小样本资料(样本≤5000);另一种是Kolmogorov–Smirnov检验,适用于大样本资料(样本量>5000)。其Shapiro-Wilk检验值为0.915,虽然数据整体不满足整体分布,但结合表1,其样本峰度绝对值小于10并且偏度绝对值小于3,
结合正态分布直方图,基本上呈现出钟形(中间高,两端低),则说明数据虽然不是绝对正态,但基本可接受为正态分布。结合图2正态性检验P-P图,是房价计算观测的累计概率(P)与正态累计概率(P)的拟合情况,拟合程度越高越服从正态分布,可以明显地看出,数据近似服从正态分布的。
图2
3.2.2 频数分析
名称 | 选项 | 频数 | 百分比(%) | 累计百分比(%) |
price | [3095.0,6261.0) | 747 | 25 | 25 |
[6261.0,7513.0) | 747 | 25 | 50 | |
[7513.0,8990.0) | 746 | 24.967 | 74.967 | |
[8990.0,19140.0] | 748 | 25.033 | 100 | |
合计 | 2988 | 100.000 | 100.000 |
表2
图3
表2和图3展示了二手房价格频数分析的结果,包括变量、频数、百分比等,以四分位进行房价分组,[3095.0,6261.0)区间占比25%,[6261.0,7513.0)区间占比25%,[7513.0,8990.0)区间占比24.967%,而[8990.0,19140.0)区间占比25.033%,可见二手房价的价格区间频数分布比较集中。
3.2.3描述性统计
变量名 | 样本量 | 最大值 | 最小值 | 平均值 |
Price | 2988 | 19140 | 3095 | 7840.503 |
变量名 | 标准差 | 中位数 | 方差 | 变异系数(CV) |
Price | 2392.412 | 7513 | 5723637.025 | 0.1224 |
表3
表3展示了二手房价描述性统计的结果,样本量为2988,房价最大值为19140,房价最小值为3095,房价平均值为77840.503,中位数为7513,基于二手价格,变异系数(CV)为0.122,小于0.15,当前数据中较小概率出现异常值。
图4
图4以散点图的形式展示了2011年到2022年新房价格频数分析集中趋势分析的结果,结合图5,可以看出来房价先持续平稳,然后从2016年开始逐步上升,在2018年8月达到最高,后下降,又持续平稳。
图5
图6
图6以柱状图的形式展示了宜昌市各个区域的房价均,可以明显的看出各个区域的房产均价,房价均值最高的是万达区域为10022元,房价均值最小的是宜都市为4105元。
3.3 特征重要性和相关性分析
通过随机森林模型对两个房价数据集进行分析,回归模型对特征重要性的柱状图如图7和图8所示,随机森林回归模型对于多特征的数据集拟合效果良好,人口数量对房价影响的重要性为0.39,GDP对房价影响的重要性为0.43,时间对房价影响的重要性为0.48;分类标签对房价的影响中,街道位置对房价的影响重要性最大,区域和建造面积重要性其次,相比较,房子的构造和户型以及房子朝向对房价的影响重要性较小,装修、关注度以及楼层层次对房价的影响重要性适中。
图7
图8
对模型特征变量的两两数据的相关性进行分析,先对变量之间是否存在统计上的显著关系(p<0.05)进行检验,分析相关系数的正负向以及相关性程度,表4和表5展示了特征变量的相关性和显著性水平,图9和图10用热力图的形式展示了相关系数的值,主要通过颜色深浅去表示值的大小。
图9
图10
结论
通过分析可以发现,宜昌市GDP和时间对宜昌市新房价格变化的相关性显著,是影响新房价格的最主要的因素。GDP和时间与新房价格呈正相关,而宜昌市人口数量与新房价格呈负相关,且人口数量对房价的影响重要性也比较低,相关性也比较低。对于宜昌市新房价格的宏观研究应该把重点放在GDP和时间的影响上;
区域位置和建筑面积对二手房价的相关性最大,建筑结构、房子朝向、以及关注度和区域对房子的相关性较小一些,宜昌市二手房市场价格的影响综合来看还是街道和住房面积的影响最大。
注意:
1. 爬虫的关键是对页面的解析,需要有HTML的基础,因为对应网站的内容和结构在不断变化,所以不存在一个爬虫代码能够爬取一个网站一直用下去,除非网站千年不变
2. 爬虫需谨慎,恶意使用爬虫、或者商业用途都属于违法行为!