您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“Python怎么實(shí)現(xiàn)爬取天氣數(shù)據(jù)并可視化分析”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Python怎么實(shí)現(xiàn)爬取天氣數(shù)據(jù)并可視化分析”吧!
總體來(lái)說(shuō),我們需要先對(duì)中國(guó)天氣網(wǎng)中的天氣數(shù)據(jù)進(jìn)行爬取,保存為csv文件,并將這些數(shù)據(jù)進(jìn)行可視化分析展示。
拆解需求,大致可以整理出我們需要分為以下幾步完成:
1.通過(guò)爬蟲(chóng)獲取中國(guó)天氣網(wǎng)7.20-7.21的降雨數(shù)據(jù),包括城市,風(fēng)力方向,風(fēng)級(jí),降水量,相對(duì)濕度,空氣質(zhì)量。
2.對(duì)獲取的天氣數(shù)據(jù)進(jìn)行預(yù)處理,分析河南的風(fēng)力等級(jí)和風(fēng)向,繪制風(fēng)向風(fēng)級(jí)雷達(dá)圖。
3.根據(jù)獲取的溫度和濕度繪制溫濕度相關(guān)性分析圖,進(jìn)行溫度、濕度對(duì)比分析。
4.根據(jù)獲取的各城市的降雨量,可視化近24小時(shí)的每小時(shí)時(shí)段降水情況。
5.繪制各城市24小時(shí)的累計(jì)降雨量。
首先我們需要獲取各個(gè)城市的降雨數(shù)據(jù),通過(guò)對(duì)中國(guó)天氣網(wǎng)網(wǎng)址分析發(fā)現(xiàn),城市的天氣網(wǎng)址為:http://www.weather.com.cn/weather/101180101.shtml。
根據(jù)對(duì)數(shù)據(jù)分析,返回的json格式數(shù)據(jù),不難發(fā)現(xiàn):
101180101就是代表城市編號(hào)- 7天的天氣預(yù)報(bào)數(shù)據(jù)信息在div標(biāo)簽中并且id=“7d”- 日期、天氣、溫度、風(fēng)級(jí)等信息都在ul和li標(biāo)簽 網(wǎng)頁(yè)結(jié)構(gòu)我們上面已經(jīng)分析好了,那么我們就可以來(lái)動(dòng)手爬取所需要的數(shù)據(jù)了。獲取到所有的數(shù)據(jù)資源之后,可以把這些數(shù)據(jù)保存下來(lái)。
請(qǐng)求網(wǎng)站
天氣網(wǎng)的網(wǎng)址:http://www.weather.com.cn/weather/101180101.shtml。如果想爬取不同的地區(qū)只需修改最后的101180101地區(qū)編號(hào),前面的weather代表是7天的網(wǎng)頁(yè)。
def getHTMLtext(url): """請(qǐng)求獲得網(wǎng)頁(yè)內(nèi)容""" 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" "
處理數(shù)據(jù)
采用BeautifulSoup庫(kù)對(duì)剛剛獲取的字符串進(jìn)行數(shù)據(jù)提取。獲取我們需要的風(fēng)力方向,風(fēng)級(jí),降水量,相對(duì)濕度,空氣質(zhì)量等。
def get_content(html,cityname): """處理得到有用信息保存數(shù)據(jù)文件""" final = [] # 初始化一個(gè)列表保存數(shù)據(jù) bs = BeautifulSoup(html, "html.parser") # 創(chuàng)建BeautifulSoup對(duì)象 body = bs.body data = body.find('div', {<!-- -->'id': '7d'}) # 找到div標(biāo)簽且id = 7d # 下面爬取當(dāng)天的數(shù)據(jù) data2 = body.find_all('div',{<!-- -->'class':'left-div'}) text = data2[2].find('script').string text = text[text.index('=')+1 :-2] # 移除改var data=將其變?yōu)閖son數(shù)據(jù) jd = json.loads(text) dayone = jd['od']['od2'] # 找到當(dāng)天的數(shù)據(jù) final_day = [] # 存放當(dāng)天的數(shù)據(jù) count = 0 for i in dayone: temp = [] if count <=23: temp.append(i['od21']) # 添加時(shí)間 temp.append(cityname+'市') # 添加城市 temp.append(i['od22']) # 添加當(dāng)前時(shí)刻溫度 temp.append(i['od24']) # 添加當(dāng)前時(shí)刻風(fēng)力方向 temp.append(i['od25']) # 添加當(dāng)前時(shí)刻風(fēng)級(jí) temp.append(i['od26']) # 添加當(dāng)前時(shí)刻降水量 temp.append(i['od27']) # 添加當(dāng)前時(shí)刻相對(duì)濕度 temp.append(i['od28']) # 添加當(dāng)前時(shí)刻控制質(zhì)量 # print(temp) final_day.append(temp) data_all.append(temp) count = count +1 # 下面爬取24h的數(shù)據(jù) ul = data.find('ul') # 找到所有的ul標(biāo)簽 li = ul.find_all('li') # 找到左右的li標(biāo)簽 i = 0 # 控制爬取的天數(shù) for day in li: # 遍歷找到的每一個(gè)li if i < 7 and i > 0: temp = [] # 臨時(shí)存放每天的數(shù)據(jù) date = day.find('h2').string # 得到日期 date = date[0:date.index('日')] # 取出日期號(hào) temp.append(date) inf = day.find_all('p') # 找出li下面的p標(biāo)簽,提取第一個(gè)p標(biāo)簽的值,即天氣 temp.append(inf[0].string) tem_low = inf[1].find('i').string # 找到最低氣溫 if inf[1].find('span') is None: # 天氣預(yù)報(bào)可能沒(méi)有最高氣溫 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') # 找到風(fēng)向 for j in wind: temp.append(j['title']) wind_scale = inf[2].find('i').string # 找到風(fēng)級(jí) index1 = wind_scale.index('級(jí)') temp.append(int(wind_scale[index1-1:index1])) final.append(temp) i = i + 1 return final_day,final
城市的天氣數(shù)據(jù)拿到了,同理我們可以根據(jù)不同的地區(qū)編號(hào)獲取河南省各個(gè)地級(jí)市的天氣數(shù)據(jù)。
Citycode = {<!-- --> "鄭州": "101180101", "新鄉(xiāng)": "101180301", "許昌": "101180401", "平頂山": "101180501", "信陽(yáng)": "101180601", "南陽(yáng)": "101180701", "開(kāi)封": "101180801", "洛陽(yáng)": "101180901", "商丘": "101181001", "焦作": "101181101", "鶴壁": "101181201", "濮陽(yáng)": "101181301", "周口": "101181401", "漯河": "101181501", "駐馬店": "101181601", "三門(mén)峽": "101181701", "濟(jì)源": "101181801", "安陽(yáng)": "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天氣中國(guó)天氣網(wǎng) html1 = getHTMLtext(url1) data1, data1_7 = get_content(html1,cityname) # 獲得1-7天和當(dāng)天的數(shù)據(jù)
存儲(chǔ)數(shù)據(jù)
def write_to_csv(file_name, data, day=14): """保存為csv文件""" with open(file_name, 'a', errors='ignore', newline='') as f: if day == 14: header = ['日期','城市','天氣','最低氣溫','最高氣溫','風(fēng)向1','風(fēng)向2','風(fēng)級(jí)'] else: header = ['小時(shí)','城市','溫度','風(fēng)力方向','風(fēng)級(jí)','降水量','相對(duì)濕度','空氣質(zhì)量'] f_csv = csv.writer(f) f_csv.writerow(header) f_csv.writerows(data) write_to_csv('河南天氣.csv',data_all,1)
這樣我們就可以把全省的各個(gè)地級(jí)市天氣數(shù)據(jù)保存下來(lái)了。
統(tǒng)計(jì)全省的風(fēng)力和風(fēng)向,因?yàn)轱L(fēng)力風(fēng)向使用極坐標(biāo)的方式展現(xiàn)比較清晰,所以我們采用極坐標(biāo)的方式展現(xiàn)一天的風(fēng)力風(fēng)向圖,將圓分為8份,每一份代表一個(gè)風(fēng)向,半徑代表平均風(fēng)力,并且隨著風(fēng)級(jí)增高,藍(lán)色加深。
def wind_radar(data): """風(fēng)向雷達(dá)圖""" wind = list(data['風(fēng)力方向']) wind_speed = list(data['風(fēng)級(jí)']) for i in range(0,24): if wind[i] == "北風(fēng)": wind[i] = 90 elif wind[i] == "南風(fēng)": wind[i] = 270 elif wind[i] == "西風(fēng)": wind[i] = 180 elif wind[i] == "東風(fēng)": wind[i] = 360 elif wind[i] == "東北風(fēng)": wind[i] = 45 elif wind[i] == "西北風(fēng)": wind[i] = 135 elif wind[i] == "西南風(fēng)": wind[i] = 225 elif wind[i] == "東南風(fēng)": wind[i] = 315 degs = np.arange(45,361,45) temp = [] for deg in degs: speed = [] # 獲取 wind_deg 在指定范圍的風(fēng)速平均值數(shù)據(jù) 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) # 數(shù)據(jù)極徑 radii = np.array(temp) # 繪制極區(qū)圖坐標(biāo)系 plt.axes(polar=True) # 定義每個(gè)扇區(qū)的RGB值(R,G,B),x越大,對(duì)應(yīng)的顏色越接近藍(lán)色 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('河南風(fēng)級(jí)圖--Dragon少年',x=0.2,fontsize=16) plt.show()
結(jié)果如下:
觀察可以發(fā)現(xiàn),當(dāng)天的東北風(fēng)最多,平均風(fēng)級(jí)達(dá)到了1.75級(jí)。
我們可以分析溫度和濕度之間是否存在關(guān)系,為了更加清楚直觀地驗(yàn)證,可以使用離散點(diǎn)plt.scatter()方法將溫度為橫坐標(biāo)、濕度為縱坐標(biāo),每個(gè)時(shí)刻的點(diǎn)在圖中點(diǎn)出來(lái),并且計(jì)算相關(guān)系數(shù)。
def calc_corr(a, b): """計(jì)算相關(guān)系數(shù)""" 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): """溫濕度相關(guān)性分析""" tem = data['溫度'] hum = data['相對(duì)濕度'] plt.scatter(tem,hum,color='blue') plt.title("溫濕度相關(guān)性分析圖--Dragon少年") plt.xlabel("溫度/℃") plt.ylabel("相對(duì)濕度/%") # plt.text(20,40,"相關(guān)系數(shù)為:"+str(calc_corr(tem,hum)),fontdict={'size':'10','color':'red'}) plt.show() print("相關(guān)系數(shù)為:"+str(calc_corr(tem,hum)))
結(jié)果如下:
觀察可以發(fā)現(xiàn),一天的溫度和濕度具有強(qiáng)烈的相關(guān)性,呈負(fù)相關(guān)。當(dāng)溫度較低時(shí),空氣中水分含量較多,濕度自然較高,而溫度高時(shí)空氣中可容納的水汽增大,相對(duì)濕度隨之降低,但其實(shí)空氣中的水汽往往是增加的。
from pyecharts import options as opts from pyecharts.charts import Map,Timeline #定義一個(gè)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)#設(shè)置播放速度、是否循環(huán)播放等參數(shù) for h in time_line_final: x =data[data["小時(shí)"]==h]['城市'].values.tolist() #選取指定城市 y=data[data["小時(shí)"]==h]['降水量'].values.tolist() #選取時(shí)間的降水量 map_shape = ( Map() .add("{}h時(shí)降水量(mm)".format(h),[list(z) for z in zip(x, y)],"河南") #打包輸入地區(qū)及對(duì)應(yīng)降水量數(shù)據(jù) .set_series_opts(label_opts=opts.LabelOpts("")) #配置系列參數(shù),為顯示地區(qū)數(shù)據(jù) .set_global_opts( title_opts=opts.TitleOpts(title="河南省降雨分布--Dragon少年"), #全局參數(shù)中設(shè)置標(biāo)題 visualmap_opts=opts.VisualMapOpts(max_=300, #設(shè)置映射配置項(xiàng)的最大值 is_piecewise=True, #設(shè)置是否為分段顯示 pos_top = "60%", #映射配置項(xiàng)距圖片上部的距離 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)) #將不同日期的數(shù)據(jù)加入到timeline中 return tl timeline_map(data).render("rainfall.html")
from pyecharts import options as opts from pyecharts.charts import Map,Timeline #定義一個(gè)timeline和map的組合圖 time_line_final = list(data1['小時(shí)'].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)#設(shè)置播放速度、是否循環(huán)播放等參數(shù) for h in time_line_final: x =data1[data1["小時(shí)"]==h]['城市'].values.tolist() #選取指定城市 y=data1[data1["小時(shí)"]==h]['降水量'].values.tolist() #選取時(shí)間的降水量 map_shape1 = ( Map() .add("{}h時(shí)累計(jì)降水量(mm)".format(h),[list(z) for z in zip(x, y)],"河南") #打包輸入地區(qū)及對(duì)應(yīng)降水量數(shù)據(jù) .set_series_opts(label_opts=opts.LabelOpts("")) #配置系列參數(shù),為顯示地區(qū)數(shù)據(jù) .set_global_opts( title_opts=opts.TitleOpts(title="河南省累計(jì)降雨分布--Dragon少年"), #全局參數(shù)中設(shè)置標(biāo)題 visualmap_opts=opts.VisualMapOpts(max_=300, #設(shè)置映射配置項(xiàng)的最大值 is_piecewise=True, #設(shè)置是否為分段顯示 pos_top = "60%", #映射配置項(xiàng)距圖片上部的距離 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)) #將不同日期的數(shù)據(jù)加入到timeline中 return tl timeline_map(data1).render("rainfalltoall_1.html")
到此,相信大家對(duì)“Python怎么實(shí)現(xiàn)爬取天氣數(shù)據(jù)并可視化分析”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。