【python爬蟲(chóng)+數(shù)分+可視化】基于廣州近年天氣數(shù)據(jù)
今天給大家?guī)?lái)的是python數(shù)據(jù)分析的全流程實(shí)戰(zhàn)
首先通過(guò)爬蟲(chóng)技術(shù)獲取數(shù)據(jù),然后通過(guò)pandas清洗和分析數(shù)據(jù),最后通過(guò)pyecharts進(jìn)行數(shù)據(jù)的可視化。這次的爬蟲(chóng)采用的是螞蟻老師課程介紹的selenium相關(guān)技術(shù),它的操作相比于request來(lái)說(shuō),更貼切人工使用瀏覽器訪問(wèn)網(wǎng)站的模式,可以繞開(kāi)復(fù)雜的js分析,直接獲取數(shù)據(jù),所以強(qiáng)烈推薦大家學(xué)習(xí)螞蟻老師的selenium爬蟲(chóng)課程!
下面正式開(kāi)始介紹本次的實(shí)戰(zhàn)步驟
一:通過(guò)selenium爬蟲(chóng)獲取數(shù)據(jù)
本次獲取的數(shù)據(jù)是廣州的2019-2021年各月的歷史數(shù)據(jù)
http://www.tianqihoubao.com/lishi/guangzhou/month/202010.html
例如這個(gè)url,里面就有廣州2020年10月的天氣數(shù)據(jù)
本次的爬蟲(chóng)用到了selenium庫(kù),運(yùn)行前需要安裝selenium的庫(kù)以及用于驅(qū)動(dòng)瀏覽器的應(yīng)用程序
我的驅(qū)動(dòng)程序在C:/WebDriver/bin/msedgedriver.exe這個(gè)位置。
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")
#?網(wǎng)頁(yè)每次加載1個(gè)月份的數(shù)據(jù),36次循環(huán),就是爬取19-21三年的數(shù)據(jù)
for?i?in?range(36):
????#?確保網(wǎng)頁(yè)加載完成
????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)
????#?休眠確保數(shù)據(jù)加載完成
????time.sleep(1)
????driver.find_element(By.XPATH,?'//*[@id="js_prevMonth"]').click()
????time.sleep(1)
二:通過(guò)pandas進(jìn)行數(shù)據(jù)清洗
import?pandas?as?pd
import?numpy?as?np
#?讀取剛才爬取保存在csv文件里的數(shù)據(jù),然后加載到pandas的dataframe的結(jié)構(gòu)里
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)
查看一下拼接后的數(shù)據(jù)是什么樣子的
df_all
| 日期 | 最高溫 | 最低溫 | 天氣 | 風(fēng)力風(fēng)向 | 空氣質(zhì)量指數(shù) | ||
|---|---|---|---|---|---|---|---|
| 2021-12-01 | 周三 | 20° | 7° | 多云~晴 | 北風(fēng)3級(jí) | 46 | 優(yōu) |
| 2021-12-02 | 周四 | 21° | 7° | 多云~晴 | 北風(fēng)3級(jí) | 47 | 優(yōu) |
| 2021-12-03 | 周五 | 22° | 7° | 多云~晴 | 東北風(fēng)3級(jí) | 48 | 優(yōu) |
| 2021-12-04 | 周六 | 22° | 7° | 多云~晴 | 東北風(fēng)2級(jí) | 45 | 優(yōu) |
| 2021-12-05 | 周日 | 22° | 8° | 多云~晴 | 東北風(fēng)2級(jí) | 52 | 良 |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 2019-01-27 | 周日 | 23° | 11° | 晴 | 東北風(fēng)2級(jí) | 81 | 良 |
| 2019-01-28 | 周一 | 23° | 11° | 多云~晴 | 東南風(fēng)2級(jí) | 88 | 良 |
| 2019-01-29 | 周二 | 24° | 13° | 陰 | 東南風(fēng)1級(jí) | 82 | 良 |
| 2019-01-30 | 周三 | 25° | 15° | 多云~陰 | 東南風(fēng)2級(jí) | 55 | 良 |
| 2019-01-31 | 周四 | 24° | 12° | 多云~陰 | 東北風(fēng)2級(jí) | 46 | 優(yōu) |
1083 rows × 6 columns
發(fā)現(xiàn)列名都錯(cuò)位了
我們先重置一下索引,然后再對(duì)列名進(jìn)行修正
df_all?=?df_all.reset_index()
df_all
| level_0 | level_1 | 日期 | 最高溫 | 最低溫 | 天氣 | 風(fēng)力風(fēng)向 | 空氣質(zhì)量指數(shù) | |
|---|---|---|---|---|---|---|---|---|
| 0 | 2021-12-01 | 周三 | 20° | 7° | 多云~晴 | 北風(fēng)3級(jí) | 46 | 優(yōu) |
| 1 | 2021-12-02 | 周四 | 21° | 7° | 多云~晴 | 北風(fēng)3級(jí) | 47 | 優(yōu) |
| 2 | 2021-12-03 | 周五 | 22° | 7° | 多云~晴 | 東北風(fēng)3級(jí) | 48 | 優(yōu) |
| 3 | 2021-12-04 | 周六 | 22° | 7° | 多云~晴 | 東北風(fēng)2級(jí) | 45 | 優(yōu) |
| 4 | 2021-12-05 | 周日 | 22° | 8° | 多云~晴 | 東北風(fēng)2級(jí) | 52 | 良 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 1078 | 2019-01-27 | 周日 | 23° | 11° | 晴 | 東北風(fēng)2級(jí) | 81 | 良 |
| 1079 | 2019-01-28 | 周一 | 23° | 11° | 多云~晴 | 東南風(fēng)2級(jí) | 88 | 良 |
| 1080 | 2019-01-29 | 周二 | 24° | 13° | 陰 | 東南風(fēng)1級(jí) | 82 | 良 |
| 1081 | 2019-01-30 | 周三 | 25° | 15° | 多云~陰 | 東南風(fēng)2級(jí) | 55 | 良 |
| 1082 | 2019-01-31 | 周四 | 24° | 12° | 多云~陰 | 東北風(fēng)2級(jí) | 46 | 優(yōu) |
1083 rows × 8 columns
df_all.columns?=?["日期","星期","最高氣溫","最低氣溫","天氣","風(fēng)力風(fēng)向","空氣質(zhì)量指數(shù)","空氣質(zhì)量評(píng)級(jí)"]
df_all["日期"]?=?pd.to_datetime(df_all["日期"])df_all.set_index("日期",?inplace=True)df_all
| 星期 | 最高氣溫 | 最低氣溫 | 天氣 | 風(fēng)力風(fēng)向 | 空氣質(zhì)量指數(shù) | 空氣質(zhì)量評(píng)級(jí) | |
|---|---|---|---|---|---|---|---|
| 日期 | |||||||
| 2021-12-01 | 周三 | 20° | 7° | 多云~晴 | 北風(fēng)3級(jí) | 46 | 優(yōu) |
| 2021-12-02 | 周四 | 21° | 7° | 多云~晴 | 北風(fēng)3級(jí) | 47 | 優(yōu) |
| 2021-12-03 | 周五 | 22° | 7° | 多云~晴 | 東北風(fēng)3級(jí) | 48 | 優(yōu) |
| 2021-12-04 | 周六 | 22° | 7° | 多云~晴 | 東北風(fēng)2級(jí) | 45 | 優(yōu) |
| 2021-12-05 | 周日 | 22° | 8° | 多云~晴 | 東北風(fēng)2級(jí) | 52 | 良 |
| ... | ... | ... | ... | ... | ... | ... | ... |
| 2019-01-27 | 周日 | 23° | 11° | 晴 | 東北風(fēng)2級(jí) | 81 | 良 |
| 2019-01-28 | 周一 | 23° | 11° | 多云~晴 | 東南風(fēng)2級(jí) | 88 | 良 |
| 2019-01-29 | 周二 | 24° | 13° | 陰 | 東南風(fēng)1級(jí) | 82 | 良 |
| 2019-01-30 | 周三 | 25° | 15° | 多云~陰 | 東南風(fēng)2級(jí) | 55 | 良 |
| 2019-01-31 | 周四 | 24° | 12° | 多云~陰 | 東北風(fēng)2級(jí) | 46 | 優(yōu) |
1083 rows × 7 columns
將氣溫列的數(shù)據(jù)轉(zhuǎn)為數(shù)字
df_all["最高氣溫"]?=?df_all["最高氣溫"].str.replace("°",?"")
df_all["最低氣溫"]?=?df_all["最低氣溫"].str.replace("°",?"")
將風(fēng)向和風(fēng)力分離
首先對(duì)"風(fēng)力風(fēng)向"一列按"風(fēng)"分割轉(zhuǎn)換為列表,然后將得到的列表轉(zhuǎn)置,最后復(fù)制給新增的"風(fēng)向"、"風(fēng)力"兩列
temp?=?df_all["風(fēng)力風(fēng)向"].str.split("風(fēng)").to_list()temp
[['北',?'3級(jí)'],
?['北',?'3級(jí)'],
?['東北',?'3級(jí)'],
?['東北',?'2級(jí)'],
?['東北',?'2級(jí)'],
?['東北',?'3級(jí)'],
?['東北',?'2級(jí)'],
?['東北',?'2級(jí)'],
?['東北',?'2級(jí)'],
?['東北',?'2級(jí)'],
?['東北',?'1級(jí)'],
?['北',?'3級(jí)'],
?['北',?'3級(jí)'],
?['東北',?'2級(jí)'],
?['東',?'1級(jí)'],
?['東北',?'1級(jí)'],
?['北',?'4級(jí)'],
?['東北',?'3級(jí)'],
?['東北',?'2級(jí)'],
?['東北',?'2級(jí)'],
?['東北',?'2級(jí)'],
?['東南',?'1級(jí)'],
?['東南',?'2級(jí)'],
?['東南',?'2級(jí)'],
?['東南',?'2級(jí)'],
?['北',?'4級(jí)'],
?['北',?'3級(jí)'],
?['北',?'3級(jí)'],
?['東北',?'2級(jí)'],
?...]
#?轉(zhuǎn)置
temp?=?list(map(list,?zip(*temp)))
df_all["風(fēng)向"]?=?temp[0]
df_all["風(fēng)力"]?=?temp[1]
#?這就是最終清洗好的數(shù)據(jù)
df_all
| 星期 | 最高氣溫 | 最低氣溫 | 天氣 | 風(fēng)力風(fēng)向 | 空氣質(zhì)量指數(shù) | 空氣質(zhì)量評(píng)級(jí) | 風(fēng)向 | 風(fēng)力 | |
|---|---|---|---|---|---|---|---|---|---|
| 日期 | |||||||||
| 2021-12-01 | 周三 | 20 | 7 | 多云~晴 | 北風(fēng)3級(jí) | 46 | 優(yōu) | 北 | 3級(jí) |
| 2021-12-02 | 周四 | 21 | 7 | 多云~晴 | 北風(fēng)3級(jí) | 47 | 優(yōu) | 北 | 3級(jí) |
| 2021-12-03 | 周五 | 22 | 7 | 多云~晴 | 東北風(fēng)3級(jí) | 48 | 優(yōu) | 東北 | 3級(jí) |
| 2021-12-04 | 周六 | 22 | 7 | 多云~晴 | 東北風(fēng)2級(jí) | 45 | 優(yōu) | 東北 | 2級(jí) |
| 2021-12-05 | 周日 | 22 | 8 | 多云~晴 | 東北風(fēng)2級(jí) | 52 | 良 | 東北 | 2級(jí) |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 2019-01-27 | 周日 | 23 | 11 | 晴 | 東北風(fēng)2級(jí) | 81 | 良 | 東北 | 2級(jí) |
| 2019-01-28 | 周一 | 23 | 11 | 多云~晴 | 東南風(fēng)2級(jí) | 88 | 良 | 東南 | 2級(jí) |
| 2019-01-29 | 周二 | 24 | 13 | 陰 | 東南風(fēng)1級(jí) | 82 | 良 | 東南 | 1級(jí) |
| 2019-01-30 | 周三 | 25 | 15 | 多云~陰 | 東南風(fēng)2級(jí) | 55 | 良 | 東南 | 2級(jí) |
| 2019-01-31 | 周四 | 24 | 12 | 多云~陰 | 東北風(fēng)2級(jí) | 46 | 優(yōu) | 東北 | 2級(jí) |
1083 rows × 9 columns
三:利用pyechats對(duì)數(shù)據(jù)進(jìn)行可視化并且分析
from?pyecharts?import?options?as?opts
from?pyecharts.charts?import?Pie
from?pyecharts.charts?import?Line
1.繪制餅圖查看天氣類(lèi)型對(duì)比
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:
????"""?創(chuàng)建餅圖對(duì)象
????文檔地址:https://pyecharts.org/#/zh-cn/basic_charts?id=pie%ef%bc%9a%e9%a5%bc%e5%9b%be
????@param?datas:?數(shù)據(jù),形式為[('晴',?115),?('多云',?78),?('晴~多云',?39)]
????@param?title:?圖表的標(biāo)題
????"""
????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=":?{c}:?go7utgvlrp%"))
????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,?"餅圖-天氣對(duì)比")
pie.render_notebook()
????"2d6ef13045b646dc9a47240b506c0637"?style="width:900px;?height:500px;">
可以發(fā)現(xiàn)廣州的天氣以多云為主
2.繪制餅圖查看風(fēng)向數(shù)據(jù)比例對(duì)比
fengxiang?=?df_all.groupby("風(fēng)向").size().sort_values(ascending=False)
datas?=?list(zip(fengxiang.index.to_list(),?fengxiang.to_list()))
pie?=?create_pie(datas,?"餅圖-風(fēng)向")
pie.render_notebook()
????"8dd16bd33b9744568abe5e686b2c1579"?style="width:900px;?height:500px;">
可以發(fā)現(xiàn)廣州的風(fēng)向以東南、東北以及西南為主
3.繪制餅圖查看空氣質(zhì)量對(duì)比
aqiInfo?=?df_all.groupby("空氣質(zhì)量評(píng)級(jí)").size().sort_values(ascending=False)
datas?=?list(zip(aqiInfo.index.to_list(),?aqiInfo.to_list()))
pie?=?create_pie(datas,?"餅圖-空氣質(zhì)量")
pie.render_notebook()
????"9ea8ccaf72a5484d8f14b10ecf5ab288"?style="width:900px;?height:500px;">
可以發(fā)現(xiàn)廣州的空氣質(zhì)量還不錯(cuò),優(yōu)占了一大半。絕大部分都在良以上
最后,推薦螞蟻老師的《零基礎(chǔ)入門(mén)Python數(shù)據(jù)分析到辦公自動(dòng)化》課程:
評(píng)論
圖片
表情
