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

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

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

如下图:

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

相关推荐
Hgfdsaqwr3 小时前
Django全栈开发入门:构建一个博客系统
jvm·数据库·python
开发者小天3 小时前
python中For Loop的用法
java·服务器·python
老百姓懂点AI4 小时前
[RAG实战] 向量数据库选型与优化:智能体来了(西南总部)AI agent指挥官的长短期记忆架构设计
python
喵手6 小时前
Python爬虫零基础入门【第九章:实战项目教学·第15节】搜索页采集:关键词队列 + 结果去重 + 反爬友好策略!
爬虫·python·爬虫实战·python爬虫工程化实战·零基础python爬虫教学·搜索页采集·关键词队列
Suchadar6 小时前
if判断语句——Python
开发语言·python
ʚB҉L҉A҉C҉K҉.҉基҉德҉^҉大6 小时前
自动化机器学习(AutoML)库TPOT使用指南
jvm·数据库·python
喵手6 小时前
Python爬虫零基础入门【第九章:实战项目教学·第14节】表格型页面采集:多列、多行、跨页(通用表格解析)!
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·表格型页面采集·通用表格解析
0思必得07 小时前
[Web自动化] 爬虫之API请求
前端·爬虫·python·selenium·自动化
莫问前路漫漫7 小时前
WinMerge v2.16.41 中文绿色版深度解析:文件对比与合并的全能工具
java·开发语言·python·jdk·ai编程
木头左7 小时前
Backtrader框架下的指数期权备兑策略资金管理实现与风险控制
python