前言
今天我們分享一個小案例,獲取天氣資料,進行可視化分析,帶你直觀了解天氣情況!
一、核心功能設計
總體來說,我們需要先對中國天氣網中的天氣資料進行爬取,保存為csv檔案,并將這些資料進行可視化分析展示,
拆解需求,大致可以整理出我們需要分為以下幾步完成:
- 通過爬蟲獲取中國天氣網7.20-7.21的降雨資料,包括城市,風力方向,風級,降水量,相對濕度,空氣質量,
- 對獲取的天氣資料進行預處理,分析河南的風力等級和風向,繪制風向風級雷達圖,
- 根據獲取的溫度和濕度繪制溫濕度相關性分析圖,進行溫度、濕度對比分析,
- 根據獲取的各城市的降雨量,可視化近24小時的每小時時段降水情況,
- 繪制各城市24小時的累計降雨量,
二、實作步驟
1. 爬取資料
首先我們需要獲取各個城市的降雨資料,通過對中國天氣網網址分析發現,城市的天氣網址為:http://www.weather.com.cn/weather/101180101.shtml,

根據對資料分析,回傳的json格式資料,不難發現:
- 101180101就是代表城市編號
- 7天的天氣預報資料資訊在div標簽中并且id=“7d”
- 日期、天氣、溫度、風級等資訊都在ul和li標簽
網頁結構我們上面已經分析好了,那么我們就可以來動手爬取所需要的資料了,獲取到所有的資料資源之后,可以把這些資料保存下來,
請求網站:
天氣網的網址:http://www.weather.com.cn/weather/101180101.shtml,如果想爬取不同的地區只需修改最后的101180101地區編號,前面的weather代表是7天的網頁,
def getHTMLtext(url):
"""請求獲得網頁內容"""
try:
r = requests.get(url, timeout = 30)
r.raise_for_status()
r.encoding = r.apparent_encoding
print("Success")
return r.text
except:
print("Fail")
return" "

處理資料:
采用BeautifulSoup庫對剛付訓取的字串進行資料提取,獲取我們需要的風力方向,風級,降水量,相對濕度,空氣質量等,
def get_content(html,cityname):
"""處理得到有用資訊保存資料檔案"""
final = [] # 初始化一個串列保存資料
bs = BeautifulSoup(html, "html.parser") # 創建BeautifulSoup物件
body = bs.body
data = body.find('div', {'id': '7d'}) # 找到div標簽且id = 7d
# 下面爬取當天的資料
data2 = body.find_all('div',{'class':'left-div'})
text = data2[2].find('script').string
text = text[text.index('=')+1 :-2] # 移除改var data=將其變為json資料
jd = json.loads(text)
dayone = jd['od']['od2'] # 找到當天的資料
final_day = [] # 存放當天的資料
count = 0
for i in dayone:
temp = []
if count <=23:
temp.append(i['od21']) # 添加時間
temp.append(cityname+'市') # 添加城市
temp.append(i['od22']) # 添加當前時刻溫度
temp.append(i['od24']) # 添加當前時刻風力方向
temp.append(i['od25']) # 添加當前時刻風級
temp.append(i['od26']) # 添加當前時刻降水量
temp.append(i['od27']) # 添加當前時刻相對濕度
temp.append(i['od28']) # 添加當前時刻控制質量
# print(temp)
final_day.append(temp)
data_all.append(temp)
count = count +1
# 下面爬取24h的資料
ul = data.find('ul') # 找到所有的ul標簽
li = ul.find_all('li') # 找到左右的li標簽
i = 0 # 控制爬取的天數
for day in li: # 遍歷找到的每一個li
if i < 7 and i > 0:
temp = [] # 臨時存放每天的資料
date = day.find('h1').string # 得到日期
date = date[0:date.index('日')] # 取出日期號
temp.append(date)
inf = day.find_all('p') # 找出li下面的p標簽,提取第一個p標簽的值,即天氣
temp.append(inf[0].string)
tem_low = inf[1].find('i').string # 找到最低氣溫
if inf[1].find('span') is None: # 天氣預報可能沒有最高氣溫
tem_high = None
else:
tem_high = inf[1].find('span').string # 找到最高氣溫
temp.append(tem_low[:-1])
if tem_high[-1] == '℃':
temp.append(tem_high[:-1])
else:
temp.append(tem_high)
wind = inf[2].find_all('span') # 找到風向
for j in wind:
temp.append(j['title'])
wind_scale = inf[2].find('i').string # 找到風級
index1 = wind_scale.index('級')
temp.append(int(wind_scale[index1-1:index1]))
final.append(temp)
i = i + 1
return final_day,final
城市的天氣資料拿到了,同理我們可以根據不同的地區編號獲取河南省各個地級市的天氣資料,
Citycode = { "鄭州": "101180101",
"新鄉": "101180301",
"許昌": "101180401",
"平頂山": "101180501",
"信陽": "101180601",
"南陽": "101180701",
"開封": "101180801",
"洛陽": "101180901",
"商丘": "101181001",
"焦作": "101181101",
"鶴壁": "101181201",
"濮陽": "101181301",
"周口": "101181401",
"漯河": "101181501",
"駐馬店": "101181601",
"三門峽": "101181701",
"濟源": "101181801",
"安陽": "101180201"}
citycode_lists = list(Citycode.items())
for city_code in citycode_lists:
city_code = list(city_code)
print(city_code)
citycode = city_code[1]
cityname = city_code[0]
url1 = 'http://www.weather.com.cn/weather/'+citycode+ '.shtml' # 24h天氣中國天氣網
html1 = getHTMLtext(url1)
data1, data1_7 = get_content(html1,cityname) # 獲得1-7天和當天的資料
存盤資料:
def write_to_csv(file_name, data, day=14):
"""保存為csv檔案"""
with open(file_name, 'a', errors='ignore', newline='') as f:
if day == 14:
header = ['日期','城市','天氣','最低氣溫','最高氣溫','風向1','風向2','風級']
else:
header = ['小時','城市','溫度','風力方向','風級','降水量','相對濕度','空氣質量']
f_csv = csv.writer(f)
f_csv.writerow(header)
f_csv.writerows(data)
write_to_csv('河南天氣.csv',data_all,1)
這樣我們就可以把全省的各個地級市天氣資料保存下來了,

2. 風向風級雷達圖
統計全省的風力和風向,因為風力風向使用極坐標的方式展現比較清晰,所以我們采用極坐標的方式展現一天的風力風向圖,將圓分為8份,每一份代表一個風向,半徑代表平均風力,并且隨著風級增高,藍色加深,
def wind_radar(data):
"""風向雷達圖"""
wind = list(data['風力方向'])
wind_speed = list(data['風級'])
for i in range(0,24):
if wind[i] == "北風":
wind[i] = 90
elif wind[i] == "南風":
wind[i] = 270
elif wind[i] == "西風":
wind[i] = 180
elif wind[i] == "東風":
wind[i] = 360
elif wind[i] == "東北風":
wind[i] = 45
elif wind[i] == "西北風":
wind[i] = 135
elif wind[i] == "西南風":
wind[i] = 225
elif wind[i] == "東南風":
wind[i] = 315
degs = np.arange(45,361,45)
temp = []
for deg in degs:
speed = []
# 獲取 wind_deg 在指定范圍的風速平均值資料
for i in range(0,24):
if wind[i] == deg:
speed.append(wind_speed[i])
if len(speed) == 0:
temp.append(0)
else:
temp.append(sum(speed)/len(speed))
print(temp)
N = 8
theta = np.arange(0.+np.pi/8,2*np.pi+np.pi/8,2*np.pi/8)
# 資料極徑
radii = np.array(temp)
# 繪制極區圖坐標系
plt.axes(polar=True)
# 定義每個扇區的RGB值(R,G,B),x越大,對應的顏色越接近藍色
colors = [(1-x/max(temp), 1-x/max(temp),0.6) for x in radii]
plt.bar(theta,radii,width=(2*np.pi/N),bottom=0.0,color=colors)
plt.title('河南風級圖--Dragon少年',x=0.2,fontsize=16)
plt.show()
結果如下:

觀察可以發現,當天的東北風最多,平均風級達到了1.75級,
3. 溫濕度相關性分析
我們可以分析溫度和濕度之間是否存在關系,為了更加清楚直觀地驗證,可以使用離散點plt.scatter()方法將溫度為橫坐標、濕度為縱坐標,每個時刻的點在圖中點出來,并且計算相關系數,
def calc_corr(a, b):
"""計算相關系數"""
a_avg = sum(a)/len(a)
b_avg = sum(b)/len(b)
cov_ab = sum([(x - a_avg)*(y - b_avg) for x,y in zip(a, b)])
sq = math.sqrt(sum([(x - a_avg)**2 for x in a])*sum([(x - b_avg)**2 for x in b]))
corr_factor = cov_ab/sq
return corr_factor
def corr_tem_hum(data):
"""溫濕度相關性分析"""
tem = data['溫度']
hum = data['相對濕度']
plt.scatter(tem,hum,color='blue')
plt.title("溫濕度相關性分析圖--Dragon少年")
plt.xlabel("溫度/℃")
plt.ylabel("相對濕度/%")
# plt.text(20,40,"相關系數為:"+str(calc_corr(tem,hum)),fontdict={'size':'10','color':'red'})
plt.show()
print("相關系數為:"+str(calc_corr(tem,hum)))
結果如下:

觀察可以發現,一天的溫度和濕度具有強烈的相關性,呈負相關,當溫度較低時,空氣中水分含量較多,濕度自然較高,而溫度較高時,水分蒸發,空氣就比較干燥,濕度較低,
4. 24小時內每小時時段降水
from pyecharts import options as opts
from pyecharts.charts import Map,Timeline
#定義一個timeline和map的組合圖
def timeline_map(data):
tl = Timeline().add_schema(play_interval =300,height=40,is_rewind_play=False,orient = "horizontal",is_loop_play = True,is_auto_play=False)#設定播放速度、是否回圈播放等引數
for h in time_line_final:
x =data[data["小時"]==h]['城市'].values.tolist() #選取指定城市
y=data[data["小時"]==h]['降水量'].values.tolist() #選取時間的降水量
map_shape = (
Map()
.add("{}h時降水量(mm)".format(h),[list(z) for z in zip(x, y)],"河南") #打包輸入地區及對應降水量資料
.set_series_opts(label_opts=opts.LabelOpts("{b}")) #配置系列引數,{b}為顯示地區資料
.set_global_opts(
title_opts=opts.TitleOpts(title="河南省降雨分布--Dragon少年"), #全域引數中設定標題
visualmap_opts=opts.VisualMapOpts(max_=300, #設定映射配置項的最大值
is_piecewise=True, #設定是否為分段顯示
pos_top = "60%", #映射配置項距圖片上部的距離
pieces=[
{"min": 101, "label": '>100ml', "color": "#FF0000"}, # 分段指定顏色及名稱
{"min": 11, "max": 50, "label": '11-50ml', "color": "#FF3333"},
{"min": 6, "max": 10, "label": '6-10ml', "color": "#FF9999"},
{"min": 0.1, "max": 5, "label": '0.1-5ml', "color": "#FFCCCC"}])
))
tl.add(map_shape, "{}h".format(h)) #將不同日期的資料加入到timeline中
return tl
timeline_map(data).render("rainfall.html")
效果如下:

觀察可以發現,7.20當天大部分地區均有雨,7月20日17時-18時一小時的降水量達到了201.9mm,
4. 24小時累計降雨量
from pyecharts import options as opts
from pyecharts.charts import Map,Timeline
#定義一個timeline和map的組合圖
time_line_final = list(data1['小時'].iloc[0:24])
def timeline_map(data1):
tl = Timeline().add_schema(play_interval =200,height=40,is_rewind_play=False,orient = "horizontal",is_loop_play = True,is_auto_play=True)#設定播放速度、是否回圈播放等引數
for h in time_line_final:
x =data1[data1["小時"]==h]['城市'].values.tolist() #選取指定城市
y=data1[data1["小時"]==h]['降水量'].values.tolist() #選取時間的降水量
map_shape1 = (
Map()
.add("{}h時累計降水量(mm)".format(h),[list(z) for z in zip(x, y)],"河南") #打包輸入地區及對應降水量資料
.set_series_opts(label_opts=opts.LabelOpts("{b}")) #配置系列引數,{b}為顯示地區資料
.set_global_opts(
title_opts=opts.TitleOpts(title="河南省累計降雨分布--Dragon少年"), #全域引數中設定標題
visualmap_opts=opts.VisualMapOpts(max_=300, #設定映射配置項的最大值
is_piecewise=True, #設定是否為分段顯示
pos_top = "60%", #映射配置項距圖片上部的距離
pieces=[
{"min": 251, "label": '特大暴雨', "color": "#800000"}, # 分段指定顏色及名稱
{"min": 101, "max": 250, "label": '暴雨', "color": "#FF4500"},
{"min": 51, "max": 100, "label": '暴雨', "color": "#FF7F50"},
{"min": 25, "max": 50, "label": '大雨', "color": "#FFFF00"},
{"min": 10, "max": 25, "label": '中雨', "color": "#1E90FF"},
{"min": 0.1, "max": 9.9, "label": '小雨', "color": "#87CEFA"}])
))
tl.add(map_shape1, "{}h".format(h)) #將不同日期的資料加入到timeline中
return tl
timeline_map(data1).render("rainfalltoall_1.html")
效果如下:

至此,天氣資料分析可視化就完成啦~
今天我們就到這里,明天繼續努力!

若本篇內容對您有所幫助,請三連點贊,關注,收藏支持下,
創作不易,白嫖不好,各位的支持和認可,就是我創作的最大動力,我們下篇文章見!
Dragon少年 | 文
如果本篇博客有任何錯誤,請批評指教,不勝感激 !
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/291050.html
標籤:python
上一篇:?「和平精英」被python爬蟲了?看看你最適合什么配件!?
下一篇:Python知識點(史上最全)
