步骤
-
数据所在的url
-
发送网络请求
-
数据的解析(我们需要的数据)
-
数据的保存
下面分步进行详细的实现
(完整代码放在最后)
爬取的网站:https://gl.lianjia.com/zufang/
-
分析需要爬取的数据是否是静态数据,查看网页源码
# URL地址
url = 'https://gl.lianjia.com/zufang/'发现我们需要爬取的数据(地区、户型、面积等)是静态的
-
构建一个请求头,进行伪装,伪装成一个浏览器用户。
因为要是不写的话,访问某些网站的时候会被认出来爬虫,显示错误,错误代码。
# 请求头,键值对形式
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30'}获得请求头的方式:
在URL下按下
F12
,打开开发者工具,来到网络(network),可以看到该页面的所有的网络请求,我们随意点击一个,找到标头下的User-Agent
,它的内容就是我们需要的,其他的那些是浏览器自带的、可以不管。
1.2、发送网络请求
-
导入发送网络请求的模块,使用其来发送请求
import requests
下载该模块的依赖,在控制台中输入
pip install requests
-
实现发送请求,带上请求头。使用response接收返回值
# 发送网络请求
response = requests.get(url=url, headers=headers)
# print(response) # 响应码为200代表成功
# html_data = response.text # 这是网页源码
# print(html_data) # 可以打印到控制台看看是否和网页源码一致
至此,response是我们拿到的网页的所有数据。下面就是对其进行解析,获得我们需要的数据
1.3、数据的解析
-
导入数据解析模块(步骤和上面一样)
import parsel
pip install parsel
转换数据类型
将其转为一个对象,才可以用于解析
selector = parsel.Selector(html_data)
这里使用xpath解析,进行数据的采集
分析我们需要采集的数据(地区、小区、户型、面积、价格、朝向、出租方式等)
使用以下方法需要对html 、css有一定的了解。也可以直接搬过去使用
# 将其转为一个对象
selector = parsel.Selector(html_data)
lis = selector.xpath('//div[@class="content__list"]/div') # 定位到每一条信息的标签
for li in lis:
detail_hire = li.xpath('.//div/p/a/text()').get() # 出租方式
detail_hire = detail_hire.strip()[0:2] # 去除前后空格,截取出租方式
detail_url = 'https://gl.lianjia.com' + li.xpath('.//a/@href').get() # 租房详情地址,需要拼接
detail_area = li.xpath('.//div/p[2]/text()[5]').get().strip() # 出租面积
detail_direction = li.xpath('.//div/p[2]/text()[6]').get().strip() # 朝向
detail_type = li.xpath('.//div/p[2]/text()[7]').get().strip() # 户型
detail_region = li.xpath('.//div/p[2]/a[2]/text()').get() # 地区
detail_village = li.xpath('.//div/p[2]/a[3]/text()').get() # 小区
detail_rent = li.xpath('.//div/span/em/text()').get() # 租金
# 运行,看是否能打印出结果
print(detail_hire, detail_region, detail_village, detail_area,
detail_direction, detail_type, detail_rent, detail_url, sep=' | ')
1.4、数据的保存
# 数据的保存,第一个参数:保存的文件名 ; a:追加写,
with open('租房网(桂林)数据.csv', mode='a', encoding='UTF-8', newline='') as f:
csv_write = csv.writer(f)
csv_write.writerow([detail_hire, detail_region, detail_village, detail_area, detail_direction, detail_type, detail_rent, detail_url])
到这里,完成了一个页面的采集,那如何完成这100 多页的采集?
点击翻页,找规律,发现url是有规律的。
那么我们将页面的规律构建出来,便可以实现循环查询了
那我们只需要在最外层加循环,改变url的路径即可。
因为是只有100页,所以范围设置为101
会出现乱码,百度搜索如何解决csv乱码问题
处理一下文档,因为没有添加标题栏,可以打开爬取好的文件手动加上。方便后面进行数据处理,你也可以尝试使在代码中添加
出租方式,地区,小区,出租面积,朝向,户型,租金,租房详情地址
完整代码
爬取一页数据的完整代码
import csv
import requests
import parsel
# URL地址
url = 'https://gl.lianjia.com/zufang/pg1'
# 请求头,键值对形式
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30'}
# 发送网络请求
response = requests.get(url=url, headers=headers)
# print(response) # 响应码为200代表成功
html_data = response.text # 这是网页源码
# print(html_data) # 可以打印到控制台看看是否和网页源码一致
# 将其转为一个对象
selector = parsel.Selector(html_data)
lis = selector.xpath('//div[@class="content__list"]/div') # 定位到每一条信息的标签
for li in lis:
detail_hire = li.xpath('.//div/p/a/text()').get() # 出租方式
detail_hire = detail_hire.strip()[0:2] # 去除前后空格,截取出租方式
detail_url = 'https://gl.lianjia.com' + li.xpath('.//a/@href').get() # 租房详情地址,需要加上前缀
detail_area = li.xpath('.//div/p[2]/text()[5]').get().strip() # 出租面积
detail_direction = li.xpath('.//div/p[2]/text()[6]').get().strip() # 朝向
detail_type = li.xpath('.//div/p[2]/text()[7]').get().strip() # 户型
detail_region = li.xpath('.//div/p[2]/a[2]/text()').get() # 地区
detail_village = li.xpath('.//div/p[2]/a[3]/text()').get() # 小区
detail_rent = li.xpath('.//div/span/em/text()').get()# 租金
print(detail_hire, detail_region, detail_village, detail_area,
detail_direction, detail_type, detail_rent, detail_url, sep=' | ')
# 数据的保存,a追加写
with open('租房网(桂林)数据.csv', mode='a', encoding='UTF-8', newline='') as f:
csv_write = csv.writer(f)
csv_write.writerow([detail_hire, detail_region, detail_village, detail_area, detail_direction, detail_type, detail_rent, detail_url])
爬取该站点的全部(区别只是多了一层循环)
import csv
import requests
import parsel
for page in range(1, 101):
# URL地址
print(f'\n=================正在爬取第{page}页的数据=======================')
url = f'https://gl.lianjia.com/zufang/pg{page}'
# 请求头,键值对形式
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36 Edg/95.0.1020.30'}
# 发送网络请求
response = requests.get(url=url, headers=headers)
# print(response) # 响应码为200代表成功
html_data = response.text # 这是网页源码
# print(html_data) # 可以打印到控制台看看是否和网页源码一致
# 将其转为一个对象
selector = parsel.Selector(html_data)
lis = selector.xpath('//div[@class="content__list"]/div') # 定位到每一条信息的标签
for li in lis:
detail_hire = li.xpath('.//div/p/a/text()').get() # 出租方式
detail_hire = detail_hire.strip()[0:2] # 去除前后空格,截取出租方式
detail_url = 'https://gl.lianjia.com' + li.xpath('.//a/@href').get() # 租房详情地址,需要加上前缀
detail_area = li.xpath('.//div/p[2]/text()[5]').get().strip() # 出租面积
detail_direction = li.xpath('.//div/p[2]/text()[6]').get().strip() # 朝向
detail_type = li.xpath('.//div/p[2]/text()[7]').get().strip() # 户型
detail_region = li.xpath('.//div/p[2]/a[2]/text()').get() # 地区
detail_village = li.xpath('.//div/p[2]/a[3]/text()').get() # 小区
detail_rent = li.xpath('.//div/span/em/text()').get() # 租金
# print(detail_hire, detail_region, detail_village, detail_area, detail_direction, detail_type, detail_rent, detail_url, sep=' | ')
# 数据的保存,a追加写
with open('租房网(桂林)数据all.csv', mode='a', encoding='UTF-8', newline='') as f:
csv_write = csv.writer(f)
csv_write.writerow([detail_hire, detail_region, detail_village, detail_area, detail_direction, detail_type, detail_rent, detail_url])
2、数据分析及可视化
步骤
探索性数据分析流程:
-
安装数据分析及可视化的工具
-
获取原始数据(即爬虫爬到的代码,可以是excel或者数据库)
-
数据处理
-
数据可视化
-
分析、得出结论
2.1、Jupyter Notebook工具安装
这里使用工具Jupyter Notebook
对数据进行可视化分析
Jupyter Notebook的安装(结合该教程:https://www.jianshu.com/p/91365f343585)
补充几点:
我是使用pip命令安装
在使用安装命令的时候需要管理员权限,所以我们按下win+x
,选择管理员的控制台
然后再执行把pip升级到最新版本
-
Python 3.x
pip3 install --upgrade pip
-
Python 2.x
pip install --upgrade pip
-
注意:老版本的pip在安装Jupyter Notebook过程中或面临依赖项无法同步安装的问题。因此强烈建议先把pip升级到最新版本。
同样的也是在这里执行Jupyter Notebook的安装命令,加上 -i 表示使用镜像, 后面接着镜像地址,我这里是阿里云的,如果不使用镜像下载,下载会很慢。上面的命令也可以使用镜像
pip install jupyter
pip install jupyter -i https://mirrors.aliyun.com/pypi/simple (推荐使用镜像)
然后等执行完毕,再pycharm的控制台或者管理员控制台中输入
jupyter notebook
就能自动打开jupyter notebook了,如图,安装成功
新建一个操作窗口
导入工具,在新窗口的命令行中执行,先下载依赖,在控制台中执行
pip install pandas -i https://mirrors.aliyun.com/pypi/simple
pip install pyecharts -i https://mirrors.aliyun.com/pypi/simple
import pandas as pd
from pyecharts.charts import *
到这里,完成了数据分析的前期准备
2.2、导入原始数据
df = pd.read_csv(r'D:\learningappDataSave\python\homework\com\yong\pc\租房网(桂林)数据all.csv',engine='python')
df.head() # 查看前五条
# df # 查看全部
2.3、数据处理
1、查看数据类型
df.dtypes
数据类型是因为我们在爬取的时候加上了单位,所以都是object(字符串)类型。如果不加,那有可能是其他类型,比如int
2、查看表格丢失数据
df.isnull()
对应的数据丢失为true,否则为false
但这样并不直观,对他进行一个求和统计,能更清楚的看到缺失情况
3、删除重复值
df.drop_duplicates(inplace=True)
输出结果为空,说明无重复值
2.4、数据可视化
要求:计算桂林各个地区的不同户型的:
-
平均价格
-
最低价格
-
最高价格
并进行可视化
-
不同户型价格前25%中不同地区的占比并进行可视化。
-
结合桂林实际情况和获取的数据,分析不同地区租金最高的小区。
思路:
统计出桂林的地区数量
在每个地区统计出该地区的不同户型的三种价格
1、总体分析(多做的一部分,满足要求的在户型分析)
统计每个区的房源数量(第一条表示七星区有555套房源)
df.groupby('地区').count()
结果分析:
临桂区的房源数量是最多的,灵川是最少的。
而且最多地区的房源数量是最少的8倍多。
可推测地区人口分布的情况
-
统计每个地区的平均租金价格
df_means = df.groupby('地区')['租金'].mean()
df_means
可视化:
获取x轴:df_means.index.tolist()
y轴同理
画出x、y轴。y轴可添加多个
bar = (
Bar()
.add_xaxis(df_means.index.tolist())
.add_yaxis('平均值',df_means.values.astype('int64').tolist())
.add_yaxis('房源数量',df_counts['租金'].values.tolist())
)
bar.render_notebook()
结果分析:
秀峰区的房源数量不多,但是平均租金最高。
临桂区的房源数量少,租金反而是最低的。
可以推测消费水平
-
最低价格、最高价格
bar = (
Bar()
.add_xaxis(df_means.index.tolist())
.add_yaxis('租金最大值',df.groupby('地区')['租金'].max().values.astype('int64').tolist())
.add_yaxis('租金最小值',df.groupby('地区')['租金'].min().values.astype('int64').tolist())
)
bar.render_notebook()
结果分析:
房源的最高价和最低价相差最大的是七星区
七星区房源的最高价是几个区中最高的
灵川房源的最低价是几个区中最低的
秀峰区房源的最低价是几个区中最高的
推测秀峰区最低住房消费水平是几个区中最高的,灵川是最低的,七星区住房消费水平都有,要高有高,要低有低。
2、户型分析
-
计算桂林各个地区的不同户型的平均价格、最低价格和最高价格并进行可视化
-
不同户型价格前25%中不同地区的占比并进行可视化。
思路:
-
统计出桂林的地区数量
-
在每个地区统计出该地区的不同户型的三种价格
统计出不同地区的不同户型
df.groupby(['地区','户型']).count()
因为这里有146个数据,说明x轴会有146.如果将平均值、最大值、最小值放在一张图中会看不清楚。
将其拆开了。。。
不同地区、不同户型的平均值
bar = (
Bar()
.add_xaxis(df.groupby(['地区','户型']).count().index.tolist())
.add_yaxis('租金平均值',df.groupby(['地区','户型'])['租金'].mean().values.astype('int64').tolist())
)
bar.render_notebook()
最大值
最小值
不同户型价格前25%中不同地区的占比并进行可视化。
分析不同地区租金最高的小区
根据地区分组,求出每个地区租金最高的小区(小区可能包含多个房源)
每个地区租金最低的小区
df.groupby('地区')['小区','租金'].max()
大概知道每个区的哪一片区域的消费水平比较高
每个地区租金最低的小区
大概知道每个区的哪一片区域的消费水平比较高
2.5、分析得出结论
结果分析:
临桂区的房源数量是最多的,灵川是最少的。
而且最多地区的房源数量是最少的8倍多。
可推测地区人口分布的情况
结果分析:
秀峰区的房源数量不多,但是平均租金最高。
临桂区的房源数量少,租金反而是最低的。
可以推测消费水平
结果分析:
房源的最高价和最低价相差最大的是七星区
七星区房源的最高价是几个区中最高的
灵川房源的最低价是几个区中最低的
秀峰区房源的最低价是几个区中最高的
推测秀峰区最低住房消费水平是几个区中最高的,灵川是最低的,七星区住房消费水平都有,要高有高,要低有低。
可以根据小区的租房金额来推测该区域的消费水平
参考资料
数据分析及可视化:https://www.bilibili.com/video/BV1xP4y1x7wp?spm_id_from=333.999.0.0