实现爬虫、数据分析及可视化


1、 实现爬虫

步骤

  1. 数据所在的url

  2. 发送网络请求

  3. 数据的解析(我们需要的数据)

  4. 数据的保存

下面分步进行详细的实现

(完整代码放在最后)

1.1、数据所在的url

爬取的网站:https://gl.lianjia.com/zufang/

  • 分析需要爬取的数据是否是静态数据,查看网页源码

    # URL地址
    url = 'https://gl.lianjia.com/zufang/'

    发现我们需要爬取的数据(地区、户型、面积等)是静态的

    image-20211030112057112

    image-20211030112109944

     

  • 构建一个请求头,进行伪装,伪装成一个浏览器用户。

    因为要是不写的话,访问某些网站的时候会被认出来爬虫,显示错误,错误代码。

    # 请求头,键值对形式
    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,它的内容就是我们需要的,其他的那些是浏览器自带的、可以不管。

    image-20211030112857062

     

1.2、发送网络请求

  • 导入发送网络请求的模块,使用其来发送请求

    import requests

    下载该模块的依赖,在控制台中输入pip install requests

    image-20211030123902008

  • 实现发送请求,带上请求头。使用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解析,进行数据的采集

分析我们需要采集的数据(地区、小区、户型、面积、价格、朝向、出租方式等)

image-20211030132312231

 

使用以下方法需要对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 多页的采集?

image-20211030154154799

 

点击翻页,找规律,发现url是有规律的。

那么我们将页面的规律构建出来,便可以实现循环查询了

image-20211030154112617

 

那我们只需要在最外层加循环,改变url的路径即可。

因为是只有100页,所以范围设置为101

image-20211030162009499

image-20211030162032471

image-20211030162201582

 

会出现乱码,百度搜索如何解决csv乱码问题

处理一下文档,因为没有添加标题栏,可以打开爬取好的文件手动加上。方便后面进行数据处理,你也可以尝试使在代码中添加

出租方式,地区,小区,出租面积,朝向,户型,租金,租房详情地址

image-20211031182114424

 

完整代码

爬取一页数据的完整代码

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、数据分析及可视化

步骤

探索性数据分析流程:

  1. 安装数据分析及可视化的工具

  2. 获取原始数据(即爬虫爬到的代码,可以是excel或者数据库)

  3. 数据处理

  4. 数据可视化

  5. 分析、得出结论

 

2.1、Jupyter Notebook工具安装

这里使用工具Jupyter Notebook对数据进行可视化分析

Jupyter Notebook的安装(结合该教程:https://www.jianshu.com/p/91365f343585

补充几点:

我是使用pip命令安装

在使用安装命令的时候需要管理员权限,所以我们按下win+x,选择管理员的控制台

image-20211031133704563

然后再执行把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 (推荐使用镜像)

image-20211031134052163

然后等执行完毕,再pycharm的控制台或者管理员控制台中输入

jupyter notebook

就能自动打开jupyter notebook了,如图,安装成功

image-20211031134309090

新建一个操作窗口

image-20211031165535029

导入工具,在新窗口的命令行中执行,先下载依赖,在控制台中执行

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 # 查看全部

image-20211031182321492

2.3、数据处理

1、查看数据类型

df.dtypes

数据类型是因为我们在爬取的时候加上了单位,所以都是object(字符串)类型。如果不加,那有可能是其他类型,比如int

2、查看表格丢失数据

df.isnull()

image-20211031182522279

对应的数据丢失为true,否则为false

 

但这样并不直观,对他进行一个求和统计,能更清楚的看到缺失情况

3、删除重复值

df.drop_duplicates(inplace=True)

输出结果为空,说明无重复值

 

2.4、数据可视化

要求:计算桂林各个地区的不同户型的:

  • 平均价格

  • 最低价格

  • 最高价格

并进行可视化

  • 不同户型价格前25%中不同地区的占比并进行可视化。

  • 结合桂林实际情况和获取的数据,分析不同地区租金最高的小区。

思路:

  1. 统计出桂林的地区数量

  2. 在每个地区统计出该地区的不同户型的三种价格

 

1、总体分析(多做的一部分,满足要求的在户型分析)

统计每个区的房源数量(第一条表示七星区有555套房源)

df.groupby('地区').count()

image-20211031185516675

结果分析:

临桂区的房源数量是最多的,灵川是最少的。

而且最多地区的房源数量是最少的8倍多。

可推测地区人口分布的情况

  • 统计每个地区的平均租金价格

df_means = df.groupby('地区')['租金'].mean()
df_means

image-20211031183056560

可视化:

获取x轴:df_means.index.tolist()

image-20211031184046591

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()

image-20211031185437116

结果分析:

秀峰区的房源数量不多,但是平均租金最高。

临桂区的房源数量少,租金反而是最低的。

可以推测消费水平

  • 最低价格最高价格

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()

image-20211031214156429

结果分析:

房源的最高价和最低价相差最大的是七星区

七星区房源的最高价是几个区中最高的

灵川房源的最低价是几个区中最低的

秀峰区房源的最低价是几个区中最高的

推测秀峰区最低住房消费水平是几个区中最高的,灵川是最低的,七星区住房消费水平都有,要高有高,要低有低。

 

2、户型分析

  • 计算桂林各个地区的不同户型的平均价格、最低价格和最高价格并进行可视化

  • 不同户型价格前25%中不同地区的占比并进行可视化。

思路:

  1. 统计出桂林的地区数量

  2. 在每个地区统计出该地区的不同户型的三种价格

 

统计出不同地区的不同户型

df.groupby(['地区','户型']).count()

image-20211031220341999

 

因为这里有146个数据,说明x轴会有146.如果将平均值、最大值、最小值放在一张图中会看不清楚。

image-20211031221832557

将其拆开了。。。

 

不同地区、不同户型的平均值

bar = (
Bar()
.add_xaxis(df.groupby(['地区','户型']).count().index.tolist())
.add_yaxis('租金平均值',df.groupby(['地区','户型'])['租金'].mean().values.astype('int64').tolist())
)
bar.render_notebook()

image-20211031222013997

 

最大值

image-20211031222640004

最小值

image-20211031222705560

 

不同户型价格前25%中不同地区的占比并进行可视化。

 

 

分析不同地区租金最高的小区

根据地区分组,求出每个地区租金最高的小区(小区可能包含多个房源)

 

每个地区租金最低的小区

df.groupby('地区')['小区','租金'].max()

 

image-20211101110153009

 

大概知道每个区的哪一片区域的消费水平比较高

每个地区租金最低的小区

image-20211101110101401

 

大概知道每个区的哪一片区域的消费水平比较高

2.5、分析得出结论

结果分析:

临桂区的房源数量是最多的,灵川是最少的。

而且最多地区的房源数量是最少的8倍多。

可推测地区人口分布的情况

 

结果分析:

秀峰区的房源数量不多,但是平均租金最高。

临桂区的房源数量少,租金反而是最低的。

可以推测消费水平

 

结果分析:

房源的最高价和最低价相差最大的是七星区

七星区房源的最高价是几个区中最高的

灵川房源的最低价是几个区中最低的

秀峰区房源的最低价是几个区中最高的

推测秀峰区最低住房消费水平是几个区中最高的,灵川是最低的,七星区住房消费水平都有,要高有高,要低有低。

 

可以根据小区的租房金额来推测该区域的消费水平

 

 

参考资料

爬取数据:https://www.bilibili.com/video/BV13N411o7GQ?from=search&seid=11800879190972678496&spm_id_from=333.337.0.0

数据分析及可视化:https://www.bilibili.com/video/BV1xP4y1x7wp?spm_id_from=333.999.0.0

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM