本文主要使用Python对链家网广州二手房信息进行数据抓取,并从中提取二手房价格、面积、户型和二手房关注度等数据,然后对提取的数据进行相应的数据分析与及对二手房进行分群聚类。
数据获取
网页分析
由上图可知,我们需要的数据都在网页源代码中,所以不需要抓包对网页进行分析。
提取网页中的特定信息
伪装浏览器
#-*- coding:utf-8 -*-
import urllib.request
from bs4 import BeautifulSoup
import pandas as pd
def Disguise():
'''伪装浏览器访问'''
header = ('User-Agent','Mozilla/5.0 (Windows NT 10.0; WOW64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36')
#@伪装浏览器
opener = urllib.request.build_opener()
opener.addheaders = [header]
#将伪装浏览器设为全局,这样在后续对网页的访问就可以直接使用urlopen
urllib.request.install_opener(opener)
获取网页的内容
def Get_page(url,num):
'''@获取网页内容'''
try:
#获取网页的内容,并使用BeautifulSoup解析以便后面的信息提取
page = urllib.request.urlopen(url).read()
soup = BeautifulSoup(page, 'lxml')
print('--------第%d页抓取成功--------'%num)
return soup
except urllib.request.URLError as e:
if hasattr(e,'code'):
print('错误原因:',e.code)
if hasattr(e,'reason'):
print('错误原因:',e.reason)
提取网页中的信息
这里我们使用python3中BeautifulSoup4模块对网页中的信息进行提取。由于要提取的信息都是以‘|‘或’‘/’相互连接在一起,所以提取的时候需要对信息进行相应的分割。
def Get_House_info(page):
'''@提取网页中的房子信息,并把信息以DataFrame的形式返回'''
item = {}
item['house_name'] = [i.get_text().strip().split('|')[0] for i in page.select('div[class="houseInfo"]')] # 房名
item['house_type'] = [i.get_text().strip().split('|')[1] for i in page.select('div[class="houseInfo"]')] #户型
item['house_area'] = [i.get_text().strip().split('|')[2] for i in page.select('div[class="houseInfo"]')] #面积
item['house_interest'] = [i.get_text().strip().split('/')[0] for i in page.select('div[class="followInfo"]')] #关注人数
item['house_see'] = [i.get_text().strip().split('/')[1] for i in page.select('div[class="followInfo"]')] #带看人数
item['house_issuedate'] = [i.get_text().strip().split('/')[2] for i in page.select('div[class="followInfo"]')] #发布时间
item['house_price'] = [i.get_text().strip() for i in page.select('div[class="totalPrice"] span')] #房价
item['house_unit_price'] = [i.get_text().strip() for i in page.select('div[class="unitPrice"] span')] #单位价格
return pd.DataFrame(item)
将各个模块进行组装,然后对二手房信息进行爬取
def main():
'''@主函数'''
filename = 'E:/py3_project/GZlian_jia_analysis/house_data.csv'
Disguise()
house_data = []
#二手房网页总共只有100页,这里可以使用一个for循环对网址进行更新
for pg in range(1,101):
lianjia_url = 'http://gz.lianjia.com/ershoufang/pg' + str(pg) +'/'
page = Get_page(lianjia_url,pg)
if len(page) > 0:
house_info = Get_House_info(page)
#把每一页提取到的信息都存在一个list里面
house_data.append(house_info)
#对list里的DataFrame进行纵向拼接
data = pd.concat(house_data, ignore_index = True)
#将信息保存到CSV文件中
data.to_csv(filename, encoding = 'gbk', index = False)
print('------写入完毕------')
if __name__ == '__main__':
main()
部分爬取的内容
数据分析
导入储存信息的文件
import pandas as pd
import os
import house_spider
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
def check_file(filename):
'''@检查文件是否存在,不存在则运行爬虫程序获得数据'''
if os.path.exists(filename):
print('------数据文件已存在------')
house_data = pd.read_csv(filename, encoding = 'gbk', sep = ',')
return house_data
else:
print('------文件不存在,运行爬虫程序对信息进行爬取------')
house_spider.main()
house_data = pd.read_csv(filename, encoding = 'gbk', sep= ',')
return house_data
查看数据集的基本信息
def data_info(data_set):
'''@查看数据集的基本信息'''
print('-----数据集基本信息-----')
data_set.info()
print('-----预览数据-----\n',data_set.head())
有上述的部分数据可知,有一些需要的数据是包含在字符串中,所以需要对字符串进行切分。
将数据从字符串提取出来
def data_adj(area_data, str):
'''@将字符串转换成数字'''
if str in area_data :
return float(area_data[0 : area_data.find(str)])
else :
return None
对处理好的数据进行分析
def main():
'''主函数'''
filename = 'E:/py3_project/GZlian_jia_analysis/house_data.csv'
#查看数据文件是否存在
house_data = check_file(filename)
#查看数据基本信息
data_info(house_data)
#将数据从字符串提取出来
house_data['area_adj'] = house_data['house_area'].apply(data_adj,str = '平米')
house_data['interest_adj'] = house_data['house_interest'].apply(data_adj,str = '人')
#画图时显示中文和负号
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False```
###户型和关注人数分析
```python
'''户型和关注人数分布'''
fig, ax1 = plt.subplots(1,1)
type_interest_group = house_data['interest_adj'].groupby(house_data['house_type']).agg([('户型', 'count'), ('关注人数', 'sum')])
#取户型>50的数据进行可视化
ti_sort = type_interest_group[type_interest_group['户型'] > 50].sort_values(by='户型')
ti_sort.plot(kind='barh', alpha=0.7, grid=True, ax=ax1)
plt.title('二手房户型和关注人数分布')
plt.ylabel('户型')
plt.show() ```
![二手房户型和关注人数分布](http://upload-images.jianshu.io/upload_images/4043796-c0dd3dd1c64444e5.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
由上图可以知道,广州二手房户型都集中在3室2厅、2室1厅和2室2厅,而且它们的关注人数也是最多的。其中可以看到2室1厅虽然数量比3室2厅少,但是关注人数却比3室2厅多。
###二手房面积分析
```python
'''面积分布'''
fig,ax2 = plt.subplots(1,1)
area_level = [0, 50, 100, 150, 200, 250, 300, 500]
label_level = ['小于50', '50-100', '100-150', '150-200', '200-250', '250-300', '300-350']
area_cut = pd.cut(house_data['area_adj'], area_level, labels=label_level)
area_cut.value_counts().plot(kind='bar', rot=30, alpha=0.4, grid=True, fontsize='small', ax=ax2)
plt.title('二手房面积分布')
plt.xlabel('面积')
plt.legend(['数量'])
plt.show() ```
![二手房面积分布](http://upload-images.jianshu.io/upload_images/4043796-1bcf27f753f15ff9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
从二手房的面积分布可以知道,广州二手房面积在50平米-100平米的占比最大。
###聚类分析
对二手房价格、关注人数、面积进行Kmeans聚类
```'''聚类分析'''
print('-----开始聚类分析-----')
# 缺失值处理:直接将缺失值去掉
cluster_data = house_data[['interest_adj','area_adj','house_price']].dropna()
#将簇数设为3
K_model = KMeans(n_clusters=3)
alg = K_model.fit(cluster_data)
print('------聚类中心------')
center = pd.DataFrame(alg.cluster_centers_, columns=['关注人数','面积','房价'])
cluster_data['label'] = alg.labels_ print(center)
if __name__ == '__main__':
main()
聚类中心
从聚类中心的结果可知,可以将二手房从房价、关注人数、面积三方面分为3类,分别为
| 类别 | 关注人数 | 面积 |房价|
| : -------- | :-----: | :----: | :----: |
| 1 | 高 | 低 | 低|
| 2 | 中 | 中 | 中|
| 3 | 低 | 高 | 高|
由上述整理结果可以知道,广州二手房面积低(75平米)、房价低(155万)的房源关注人数最高。从侧面也可以推断广州二手房的房价水平大多集中在155万上下。
所以从营销和用户体验的角度来看,网站应该在广告和列表页的默认排序中应该给予总价155万,面积75属性的二手房源更高的权重。这个类别的房源可以吸引最多的用户关注。