爬虫数据清洗可视化案例之全球灾害数据

目标网站: 全球灾害数据平台
温馨提示: 仅供学习交流使用

|----------------|-------------|
| requests() | lxml |
| pandas | numpy |
| matplotlib | seaborn |
| pprint | |
[本案例所使用的库]

明确需要爬取的内容:

国家地区

所属洲

总频次

受影响人口(万人)

死亡人口(人)

经济损失(千美元)

爬取步骤:

发送请求 模拟浏览器向服务器 发送请求

解析数据 提取想要的数据

保存数据 持久化保存 csv excel 数据库

一.发送请求

确定网页的构造 静态数据 or 动态数据
右击查看网页源代码 Ctrl+F 再搜索框中输入要获取的信息

返回的结果是没有 说明是动态的数据 需要抓包分析

此时 到网页主界面 快捷键(F12) or 右击 检查

点击网络 接着刷新当前界面 或 Ctrl+R(快捷键刷新)

同样地 Ctrl+F 打开搜索框 输入想获取的数据 在返回中的数据包中筛选 找到符合的那个

然后 点击标头 这里有请求的一些基本信息 可以查看

我们使用爬虫工具 快速构建 爬虫请求代码

右击相应的数据包 点击复制cURL(bash) 如上图所示 注意是bash

之后打开 工具 爬虫工具库-spidertools.cn

复制右边的代码 到Pycharm中

运行代码 检查想爬取的数据是否在返回的数据中

二. 解析数据

因为返回的是Json格式的数据 需要获取 返回的Json

这里我们可以使用 python 模块 pprint 可以让Json 格式的数据更加美观

python 复制代码
import pprint


pprint.pprint(response.json())

这样输出就会如下图所示

对比页面 找到想要爬取数据的位置 字段名

接着我们从 字典套列表的格式中提取数据 通过键值对取值 For循环遍历列表 取值

python 复制代码
json_data = response.json()['data']['content']


# 拿到想要的数据
for li in json_data:
    country = li['countryCn']
    state = li['continentCn']
    total = li['sum']
    death_people = li['death']
    influence_people = li['population']
    found_lose = li['loss']


# 可以输出打印 对比数据是否符合

三. 保存数据

保存数据为 Excel文件

python 复制代码
# 先将数据存储到 字典中
# 再定义一个列表  将数据添加进去
dit = {
        '国家': country,
        '州': state,
        '总频次': total,
        '死亡人数': death_people,
        '影响人数': influence_people,
        '损失': found_lose
    }

# 保存数据 为excel
pd.DataFrame(lis).to_excel('global_disaster.xlsx',index=False)

多页爬取 查看请求体里面的data参数 直接 修改 循环即可 我这里写它全部的数据

温馨提示: 它这个 "Authorization" 参数具有时效性 逆向可解决 但不影响我们获取数据

这样就爬取到了我们想要的数据

以下是爬虫部分的全部代码

python 复制代码
import pprint

import pandas as pd
import requests
import json

headers = {
    "Accept": "application/json, text/plain, */*",
    "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
    "Authorization": "Bearer b81b81e2-da54-4548-ac4f-4504ba437b51",
    "Cache-Control": "no-cache",
    "Connection": "keep-alive",
    "Content-Type": "application/json;charset=UTF-8",
    "Origin": "https://www.gddat.cn",
    "Pragma": "no-cache",
    "Referer": "https://www.gddat.cn/newGlobalWeb/",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/141.0.0.0 Safari/537.36 Edg/141.0.0.0",
    "sec-ch-ua": "\"Microsoft Edge\";v=\"141\", \"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"141\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"Windows\""
}
cookies = {
    "你的cookie"
}
url = "https://www.gddat.cn/gw/application-base-ris-portal/featureAnalysis/idisasterEmdatStandard/getIHistoryByCountry"
data = {
    "continentCn": "",
    "frequency": "10",
    "continent": [],
    "countryCode": [],
    "eventTypeCode": [],
    "maxaffected": "",
    "maxdeaths": "",
    "maxloss": "",
    "minaffected": "",
    "mindeaths": "",
    "minloss": "",
    "orderby": "sum",
    "fromYear": "",
    "toYear": "",
    "Year": "",
    "page": 0,
    "size": 204,
}
data = json.dumps(data, separators=(',', ':'))
response = requests.post(url, headers=headers, cookies=cookies, data=data)

lis = []
json_data = response.json()['data']['content']
for li in json_data:
    country = li['countryCn']
    state = li['continentCn']
    total = li['sum']
    death_people = li['death']
    influence_people = li['population']
    found_lose = li['loss']

    dit = {
        '国家': country,
        '州': state,
        '总频次': total,
        '死亡人数': death_people,
        '影响人数': influence_people,
        '损失': found_lose
    }
    lis.append(dit)

pd.DataFrame(lis).to_excel('global_disaster.xlsx',index=False)

数据清洗:

这里我们选择直接将缺失值删除

python 复制代码
import pandas as pd

# 读取文件
df = pd.read_excel('global_disaster.xlsx')

# 将损失为缺失值的国家名字 展示出来
country_lose = df[df['损失'].isna()]['国家'].tolist()
# 删除缺失值
df.dropna(subset='损失', inplace=True)

# 统计缺失值的数量
total = df['损失'].isna().sum()
# 展示处理后的前五条记录
print(df.head())

python 复制代码
state_num = df['州'].unique()

没有不符合要求的命名


python 复制代码
# iqr 处理异常值
lo = df['死亡人数'].quantile(0.25)
up = df['死亡人数'].quantile(0.75)
iqr = up - lo
lower = lo - 1.5 * iqr
upper = up + 1.5 * iqr

# 未清理前的数据长度
before_clean = len(df)

# df = df[(df['死亡人数'] > lower) & (df['死亡人数'] < upper)]
# 异常值 展示
# 异常值
false_death = df[(df['死亡人数'] < lower) | (df['死亡人数'] > upper)]
df['死亡人数'] = np.where(
    (df['死亡人数'] < lower) | (df['死亡人数'] > upper),
    None,
    df['死亡人数']
)

df.dropna(subset='死亡人数',inplace=True)

print(len(df))

# 思路是 将异常值用None值代替  后续删除

python 复制代码
df['影响人数'] = pd.to_numeric(df['影响人数'], errors='coerce')
df['损失'] = pd.to_numeric(df['损失'], errors='coerce')
# print(df.info())
# print(df.head(5))


python 复制代码
duplicated = df.duplicated().sum()
df.drop_duplicates(inplace=True)

# print(len(df))

python 复制代码
df['损失'] = (df['损失'] / 1000000).round(2)
print(df.head())


python 复制代码
consistent_check = df[(df['总频次'] == 0) & (df['死亡人数'] > 0)]

print(consistent_check)

数据可视化:

画出各州灾害总频次热力图 经济损失热力图 死亡人数热力图 平均灾害频次热力图

python 复制代码
# 导包
import matplotlib.pyplot as plt
from matplotlib import rcParams
import seaborn as sns
import pandas as pd

df = pd.read_excel('cleaned_global_disaster.xlsx')

# 设置字体 为默认的黑体
rcParams['font.family'] = 'SimHei'

region_summery = df.groupby(['州']).agg({
    '总频次': 'sum',
    '死亡人数': 'sum',
    '损失': 'sum',
    '国家': 'count',
}).rename(columns={'国家': '国家数量', '损失': '损失(万元)'}).sort_values(by=['总频次', '损失(万元)'],
                                                                          ascending=[False, False])

# 画子图
plt.subplot(2, 2, 1)
# annot = True  表示在热力图中显示对应的数值
# fmt = '.0f' 表示将数值类型的格式化为整数
# colormap的缩写 cmap   指定用红色系的颜色映射  Reds
# 设置cbar_Kws 用于设置颜色条的属性
# shrink 用于设置颜色条的大小
# annot_kws 用于设置注解的属性 字体 大小
# linewidths  设置单元格边框
sns.heatmap(region_summery[['总频次']], annot=True, fmt='.0f', cmap='Reds', linewidths=0.5,
            annot_kws={'size': 12, 'weight': 'bold'}, cbar_kws={'label': '灾害频次', 'shrink': 0.8})
plt.title('各州灾害总频次热力图')

plt.subplot(2, 2, 2)
sns.heatmap(region_summery[['损失(万元)']],
            annot=True,
            annot_kws={'size': 12, 'weight': 'bold'},
            linewidths=0.5,
            fmt='.0f',
            cmap='Oranges',
            cbar_kws={'label': '损失(百万美元)', 'shrink': 0.8}
            )

plt.title('各州经济损失热力图')

plt.subplot(2, 2, 3)
sns.heatmap(region_summery[['死亡人数']],
            annot=True,
            annot_kws={'size': 12, 'weight': 'bold'},
            linewidths=0.5,
            fmt='.0f',
            cmap='Purples',
            cbar_kws={'label': '死亡人数', 'shrink': 0.8}
            )
plt.title('各州死亡人数热力图')

plt.subplot(2, 2, 4)

region_summery['平均频次'] = region_summery['总频次'] / region_summery['国家数量']
sns.heatmap(region_summery[['平均频次']],
            annot=True,
            annot_kws={'size': 12, 'weight': 'bold'},
            fmt='.1f',
            cmap='Blues',
            linewidths=0.5,
            cbar_kws={'label': '平均灾害频次', 'shrink': 0.8}
            )
plt.title('各州平均灾害频次热力图')

plt.tight_layout()
plt.show()
# print(region_summery)

如下图:

本次的案例分享到此结束 如果觉得还不错 你的点赞关注是我更新进步的动力 谢谢!

相关推荐
路边草随风5 小时前
milvus向量数据库使用尝试
人工智能·python·milvus
newobut5 小时前
vscode远程调试python程序,基于debugpy库
vscode·python·调试·debugpy
APIshop6 小时前
用 Python 把“API 接口”当数据源——从找口子到落库的全流程实战
开发语言·python
一点晖光7 小时前
Docker 作图咒语生成器搭建指南
python·docker
smj2302_796826527 小时前
解决leetcode第3768题.固定长度子数组中的最小逆序对数目
python·算法·leetcode
木头左7 小时前
位置编码增强法在量化交易策略中的应用基于短期记忆敏感度提升
python
Acc1oFl4g7 小时前
详解Java反射
java·开发语言·python
NocoBase7 小时前
6 个最佳开源 AI 仪表盘工具
低代码·开源·数据可视化
ney187819024748 小时前
分类网络LeNet + FashionMNIST 准确率92.9%
python·深度学习·分类
Data_agent9 小时前
1688获得1688店铺列表API,python请求示例
开发语言·python·算法