【python爬虫+数分+可视化】基于广州近年天气数据
今天给大家带来的是python数据分析的全流程实战
首先通过爬虫技术获取数据,然后通过pandas清洗和分析数据,最后通过pyecharts进行数据的可视化。这次的爬虫采用的是蚂蚁老师课程介绍的selenium相关技术,它的操作相比于request来说,更贴切人工使用浏览器访问网站的模式,可以绕开复杂的js分析,直接获取数据,所以强烈推荐大家学习蚂蚁老师的selenium爬虫课程!
下面正式开始介绍本次的实战步骤
一:通过selenium爬虫获取数据
本次获取的数据是广州的2019-2021年各月的历史数据
http://www.tianqihoubao.com/lishi/guangzhou/month/202010.html
例如这个url,里面就有广州2020年10月的天气数据
本次的爬虫用到了selenium库,运行前需要安装selenium的库以及用于驱动浏览器的应用程序
我的驱动程序在C:/WebDriver/bin/msedgedriver.exe这个位置。
from selenium.webdriver import Edge
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
import time
driver = Edge(executable_path="C:/WebDriver/bin/msedgedriver.exe")
driver.get("https://tianqi.2345.com/wea_history/59287.htm")
# 网页每次加载1个月份的数据,36次循环,就是爬取19-21三年的数据
for i in range(36):
# 确保网页加载完成
WebDriverWait(driver, 10).until(lambda d: "广州历史天气" in d.title)
content = driver.find_element(By.XPATH, '//*[@id="weather-history"]/table/tbody').text
with open(f"guangzhou/{i}.csv", "w", encoding='utf-8') as fin:
fin.write(content)
# 休眠确保数据加载完成
time.sleep(1)
driver.find_element(By.XPATH, '//*[@id="js_prevMonth"]').click()
time.sleep(1)
二:通过pandas进行数据清洗
import pandas as pd
import numpy as np
# 读取刚才爬取保存在csv文件里的数据,然后加载到pandas的dataframe的结构里
df_list = []
for i in range(36):
data = pd.read_csv(f"guangzhou/{i}.csv", sep=' ')
df_list.append(data)
df_all = pd.concat(df_list)
查看一下拼接后的数据是什么样子的
df_all
日期 | 最高温 | 最低温 | 天气 | 风力风向 | 空气质量指数 | ||
---|---|---|---|---|---|---|---|
2021-12-01 | 周三 | 20° | 7° | 多云~晴 | 北风3级 | 46 | 优 |
2021-12-02 | 周四 | 21° | 7° | 多云~晴 | 北风3级 | 47 | 优 |
2021-12-03 | 周五 | 22° | 7° | 多云~晴 | 东北风3级 | 48 | 优 |
2021-12-04 | 周六 | 22° | 7° | 多云~晴 | 东北风2级 | 45 | 优 |
2021-12-05 | 周日 | 22° | 8° | 多云~晴 | 东北风2级 | 52 | 良 |
... | ... | ... | ... | ... | ... | ... | ... |
2019-01-27 | 周日 | 23° | 11° | 晴 | 东北风2级 | 81 | 良 |
2019-01-28 | 周一 | 23° | 11° | 多云~晴 | 东南风2级 | 88 | 良 |
2019-01-29 | 周二 | 24° | 13° | 阴 | 东南风1级 | 82 | 良 |
2019-01-30 | 周三 | 25° | 15° | 多云~阴 | 东南风2级 | 55 | 良 |
2019-01-31 | 周四 | 24° | 12° | 多云~阴 | 东北风2级 | 46 | 优 |
1083 rows × 6 columns
发现列名都错位了
我们先重置一下索引,然后再对列名进行修正
df_all = df_all.reset_index()
df_all
level_0 | level_1 | 日期 | 最高温 | 最低温 | 天气 | 风力风向 | 空气质量指数 | |
---|---|---|---|---|---|---|---|---|
0 | 2021-12-01 | 周三 | 20° | 7° | 多云~晴 | 北风3级 | 46 | 优 |
1 | 2021-12-02 | 周四 | 21° | 7° | 多云~晴 | 北风3级 | 47 | 优 |
2 | 2021-12-03 | 周五 | 22° | 7° | 多云~晴 | 东北风3级 | 48 | 优 |
3 | 2021-12-04 | 周六 | 22° | 7° | 多云~晴 | 东北风2级 | 45 | 优 |
4 | 2021-12-05 | 周日 | 22° | 8° | 多云~晴 | 东北风2级 | 52 | 良 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
1078 | 2019-01-27 | 周日 | 23° | 11° | 晴 | 东北风2级 | 81 | 良 |
1079 | 2019-01-28 | 周一 | 23° | 11° | 多云~晴 | 东南风2级 | 88 | 良 |
1080 | 2019-01-29 | 周二 | 24° | 13° | 阴 | 东南风1级 | 82 | 良 |
1081 | 2019-01-30 | 周三 | 25° | 15° | 多云~阴 | 东南风2级 | 55 | 良 |
1082 | 2019-01-31 | 周四 | 24° | 12° | 多云~阴 | 东北风2级 | 46 | 优 |
1083 rows × 8 columns
df_all.columns = ["日期","星期","最高气温","最低气温","天气","风力风向","空气质量指数","空气质量评级"]
df_all["日期"] = pd.to_datetime(df_all["日期"])df_all.set_index("日期", inplace=True)df_all
星期 | 最高气温 | 最低气温 | 天气 | 风力风向 | 空气质量指数 | 空气质量评级 | |
---|---|---|---|---|---|---|---|
日期 | |||||||
2021-12-01 | 周三 | 20° | 7° | 多云~晴 | 北风3级 | 46 | 优 |
2021-12-02 | 周四 | 21° | 7° | 多云~晴 | 北风3级 | 47 | 优 |
2021-12-03 | 周五 | 22° | 7° | 多云~晴 | 东北风3级 | 48 | 优 |
2021-12-04 | 周六 | 22° | 7° | 多云~晴 | 东北风2级 | 45 | 优 |
2021-12-05 | 周日 | 22° | 8° | 多云~晴 | 东北风2级 | 52 | 良 |
... | ... | ... | ... | ... | ... | ... | ... |
2019-01-27 | 周日 | 23° | 11° | 晴 | 东北风2级 | 81 | 良 |
2019-01-28 | 周一 | 23° | 11° | 多云~晴 | 东南风2级 | 88 | 良 |
2019-01-29 | 周二 | 24° | 13° | 阴 | 东南风1级 | 82 | 良 |
2019-01-30 | 周三 | 25° | 15° | 多云~阴 | 东南风2级 | 55 | 良 |
2019-01-31 | 周四 | 24° | 12° | 多云~阴 | 东北风2级 | 46 | 优 |
1083 rows × 7 columns
将气温列的数据转为数字
df_all["最高气温"] = df_all["最高气温"].str.replace("°", "")
df_all["最低气温"] = df_all["最低气温"].str.replace("°", "")
将风向和风力分离
首先对"风力风向"一列按"风"分割转换为列表,然后将得到的列表转置,最后复制给新增的"风向"、"风力"两列
temp = df_all["风力风向"].str.split("风").to_list()temp
[['北', '3级'],
['北', '3级'],
['东北', '3级'],
['东北', '2级'],
['东北', '2级'],
['东北', '3级'],
['东北', '2级'],
['东北', '2级'],
['东北', '2级'],
['东北', '2级'],
['东北', '1级'],
['北', '3级'],
['北', '3级'],
['东北', '2级'],
['东', '1级'],
['东北', '1级'],
['北', '4级'],
['东北', '3级'],
['东北', '2级'],
['东北', '2级'],
['东北', '2级'],
['东南', '1级'],
['东南', '2级'],
['东南', '2级'],
['东南', '2级'],
['北', '4级'],
['北', '3级'],
['北', '3级'],
['东北', '2级'],
...]
# 转置
temp = list(map(list, zip(*temp)))
df_all["风向"] = temp[0]
df_all["风力"] = temp[1]
# 这就是最终清洗好的数据
df_all
星期 | 最高气温 | 最低气温 | 天气 | 风力风向 | 空气质量指数 | 空气质量评级 | 风向 | 风力 | |
---|---|---|---|---|---|---|---|---|---|
日期 | |||||||||
2021-12-01 | 周三 | 20 | 7 | 多云~晴 | 北风3级 | 46 | 优 | 北 | 3级 |
2021-12-02 | 周四 | 21 | 7 | 多云~晴 | 北风3级 | 47 | 优 | 北 | 3级 |
2021-12-03 | 周五 | 22 | 7 | 多云~晴 | 东北风3级 | 48 | 优 | 东北 | 3级 |
2021-12-04 | 周六 | 22 | 7 | 多云~晴 | 东北风2级 | 45 | 优 | 东北 | 2级 |
2021-12-05 | 周日 | 22 | 8 | 多云~晴 | 东北风2级 | 52 | 良 | 东北 | 2级 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
2019-01-27 | 周日 | 23 | 11 | 晴 | 东北风2级 | 81 | 良 | 东北 | 2级 |
2019-01-28 | 周一 | 23 | 11 | 多云~晴 | 东南风2级 | 88 | 良 | 东南 | 2级 |
2019-01-29 | 周二 | 24 | 13 | 阴 | 东南风1级 | 82 | 良 | 东南 | 1级 |
2019-01-30 | 周三 | 25 | 15 | 多云~阴 | 东南风2级 | 55 | 良 | 东南 | 2级 |
2019-01-31 | 周四 | 24 | 12 | 多云~阴 | 东北风2级 | 46 | 优 | 东北 | 2级 |
1083 rows × 9 columns
三:利用pyechats对数据进行可视化并且分析
from pyecharts import options as opts
from pyecharts.charts import Pie
from pyecharts.charts import Line
1.绘制饼图查看天气类型对比
df_all_tianqi = df_all.groupby("天气").size().sort_values(ascending=False)
df_all_tianqi
天气
多云 216
阴~多云 146
晴 83
多云~晴 73
阴~雷阵雨 55
...
中到大雨~雷阵雨 1
大雨~多云 1
多云~阵雨 1
中雨~晴 1
雾~多云 1
Length: 63, dtype: int64
def create_pie(datas, title) -> Pie:
""" 创建饼图对象
文档地址:https://pyecharts.org/#/zh-cn/basic_charts?id=pie%ef%bc%9a%e9%a5%bc%e5%9b%be
@param datas: 数据,形式为[('晴', 115), ('多云', 78), ('晴~多云', 39)]
@param title: 图表的标题
"""
pie = Pie()
pie.add("", datas)
pie.set_global_opts(
title_opts=opts.TitleOpts(title=title),
legend_opts=opts.LegendOpts(pos_right="right")
)
pie.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}: {d}%"))
return pie
datas = list(zip(df_all_tianqi.index.to_list(), df_all_tianqi.to_list()))
datas
[('多云', 216),
('阴~多云', 146),
('晴', 83),
('多云~晴', 73),
('阴~雷阵雨', 55),
('雷阵雨', 47),
('中雨~雷阵雨', 37),
('小雨', 31),
('晴~多云', 30),
('阴', 29),
('阴~阵雨', 21),
('雷阵雨~多云', 20),
('多云~雷阵雨', 19),
('多云~小雨', 19),
('小雨~雷阵雨', 18),
('阴~小雨', 17),
('阴~中雨', 15),
('大雨~雷阵雨', 15),
('小雨~多云', 14),
('多云~阴', 14),
('阴~晴', 14),
('中雨', 14),
('小雨~中雨', 12),
('大雨~中雨', 11),
('阴~大雨', 9),
('雷阵雨~中雨', 8),
('小雨~阵雨', 7),
('大雨', 7),
('中雨~多云', 6),
('小雨~大雨', 6),
('小雨~晴', 5),
('中雨~大雨', 5),
('中雨~小雨', 4),
('中雨~暴雨', 4),
('多云~中雨', 4),
('暴雨~雷阵雨', 3),
('阵雨~小雨', 3),
('大雨~阵雨', 3),
('小雨~阴', 3),
('暴雨~中雨', 2),
('暴雨~大雨', 2),
('晴~小雨', 2),
('雷阵雨~小雨', 2),
('雷阵雨~大雨', 2),
('中雨~阵雨', 2),
('中雨~阴', 2),
('大雨~小雨', 2),
('雷阵雨~阴', 2),
('阴~暴雨', 2),
('大雨~阴', 2),
('阵雨~阴', 2),
('雷阵雨~中到大雨', 1),
('阵雨~雷阵雨', 1),
('中到大雨~中雨', 1),
('阵雨~中雨', 1),
('阵雨', 1),
('晴~雷阵雨', 1),
('晴~阴', 1),
('中到大雨~雷阵雨', 1),
('大雨~多云', 1),
('多云~阵雨', 1),
('中雨~晴', 1),
('雾~多云', 1)]
pie = create_pie(datas, "饼图-天气对比")
pie.render_notebook()
"2d6ef13045b646dc9a47240b506c0637" style="width:900px; height:500px;">
可以发现广州的天气以多云为主
2.绘制饼图查看风向数据比例对比
fengxiang = df_all.groupby("风向").size().sort_values(ascending=False)
datas = list(zip(fengxiang.index.to_list(), fengxiang.to_list()))
pie = create_pie(datas, "饼图-风向")
pie.render_notebook()
"8dd16bd33b9744568abe5e686b2c1579" style="width:900px; height:500px;">
可以发现广州的风向以东南、东北以及西南为主
3.绘制饼图查看空气质量对比
aqiInfo = df_all.groupby("空气质量评级").size().sort_values(ascending=False)
datas = list(zip(aqiInfo.index.to_list(), aqiInfo.to_list()))
pie = create_pie(datas, "饼图-空气质量")
pie.render_notebook()
"9ea8ccaf72a5484d8f14b10ecf5ab288" style="width:900px; height:500px;">
可以发现广州的空气质量还不错,优占了一大半。绝大部分都在良以上
最后,推荐蚂蚁老师的《零基础入门Python数据分析到办公自动化》课程:
评论