Python實現(xiàn)爬取天氣數(shù)據(jù)并可視化分析
今天我們分享一個小案例,獲取天氣數(shù)據(jù),進行可視化分析,帶你直觀了解天氣情況!
核心功能設計
總體來說,我們需要先對中國天氣網(wǎng)中的天氣數(shù)據(jù)進行爬取,保存為csv文件,并將這些數(shù)據(jù)進行可視化分析展示。
拆解需求,大致可以整理出我們需要分為以下幾步完成:
1.通過爬蟲獲取中國天氣網(wǎng)7.20-7.21的降雨數(shù)據(jù),包括城市,風力方向,風級,降水量,相對濕度,空氣質(zhì)量。
2.對獲取的天氣數(shù)據(jù)進行預處理,分析河南的風力等級和風向,繪制風向風級雷達圖。
3.根據(jù)獲取的溫度和濕度繪制溫濕度相關(guān)性分析圖,進行溫度、濕度對比分析。
4.根據(jù)獲取的各城市的降雨量,可視化近24小時的每小時時段降水情況。
5.繪制各城市24小時的累計降雨量。
實現(xiàn)步驟
爬取數(shù)據(jù)
首先我們需要獲取各個城市的降雨數(shù)據(jù),通過對中國天氣網(wǎng)網(wǎng)址分析發(fā)現(xiàn),城市的天氣網(wǎng)址為:http://www.weather.com.cn/weather/101180101.shtml。
根據(jù)對數(shù)據(jù)分析,返回的json格式數(shù)據(jù),不難發(fā)現(xiàn):
101180101就是代表城市編號- 7天的天氣預報數(shù)據(jù)信息在div標簽中并且id=“7d”- 日期、天氣、溫度、風級等信息都在ul和li標簽 網(wǎng)頁結(jié)構(gòu)我們上面已經(jīng)分析好了,那么我們就可以來動手爬取所需要的數(shù)據(jù)了。獲取到所有的數(shù)據(jù)資源之后,可以把這些數(shù)據(jù)保存下來。
請求網(wǎng)站
天氣網(wǎng)的網(wǎng)址:http://www.weather.com.cn/weather/101180101.shtml。如果想爬取不同的地區(qū)只需修改最后的101180101地區(qū)編號,前面的weather代表是7天的網(wǎng)頁。
def?getHTMLtext(url): ?"""請求獲得網(wǎng)頁內(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庫對剛剛獲取的字符串進行數(shù)據(jù)提取。獲取我們需要的風力方向,風級,降水量,相對濕度,空氣質(zhì)量等。
def?get_content(html,cityname): ?"""處理得到有用信息保存數(shù)據(jù)文件""" ?final?=?[]??????????#?初始化一個列表保存數(shù)據(jù) ?bs?=?BeautifulSoup(html,?"html.parser")??#?創(chuàng)建BeautifulSoup對象 ?body?=?bs.body ?data?=?body.find('div',?{<!--?-->'id':?'7d'})????#?找到div標簽且id?=?7d ?#?下面爬取當天的數(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']?????#?找到當天的數(shù)據(jù) ?final_day?=?[]???????????#?存放當天的數(shù)據(jù) ?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'])?????#?添加當前時刻控制質(zhì)量 #????print(temp) ???final_day.append(temp) ???data_all.append(temp) ??count?=?count?+1 ?#?下面爬取24h的數(shù)據(jù) ?ul?=?data.find('ul')?????????????????????#?找到所有的ul標簽 ?li?=?ul.find_all('li')???????????????????#?找到左右的li標簽 ?i?=?0????????????????????????????????????#?控制爬取的天數(shù) ?for?day?in?li:??????????????????????????#?遍歷找到的每一個li ?????if?i?<?7?and?i?>?0: ?????????temp?=?[]????????????????????????#?臨時存放每天的數(shù)據(jù) ?????????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
城市的天氣數(shù)據(jù)拿到了,同理我們可以根據(jù)不同的地區(qū)編號獲取河南省各個地級市的天氣數(shù)據(jù)。
Citycode?=?{<!--?-->?"鄭州":?"101180101", ?????????????"新鄉(xiāng)":?"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天氣中國天氣網(wǎng) ?html1?=?getHTMLtext(url1) ?data1,?data1_7?=?get_content(html1,cityname)??#?獲得1-7天和當天的數(shù)據(jù)
存儲數(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?=?['日期','城市','天氣','最低氣溫','最高氣溫','風向1','風向2','風級'] ??else: ???header?=?['小時','城市','溫度','風力方向','風級','降水量','相對濕度','空氣質(zhì)量'] ??f_csv?=?csv.writer(f) ??f_csv.writerow(header) ??f_csv.writerows(data) write_to_csv('河南天氣.csv',data_all,1)
這樣我們就可以把全省的各個地級市天氣數(shù)據(jù)保存下來了。
風向風級雷達圖
統(tǒng)計全省的風力和風向,因為風力風向使用極坐標的方式展現(xiàn)比較清晰,所以我們采用極坐標的方式展現(xiàn)一天的風力風向圖,將圓分為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?在指定范圍的風速平均值數(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ū)圖坐標系 ?plt.axes(polar=True) ?#?定義每個扇區(qū)的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()
結(jié)果如下:
觀察可以發(fā)現(xiàn),當天的東北風最多,平均風級達到了1.75級。
溫濕度相關(guān)性分析
我們可以分析溫度和濕度之間是否存在關(guān)系,為了更加清楚直觀地驗證,可以使用離散點plt.scatter()方法將溫度為橫坐標、濕度為縱坐標,每個時刻的點在圖中點出來,并且計算相關(guān)系數(shù)。
def?calc_corr(a,?b): ?"""計算相關(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['相對濕度'] ?plt.scatter(tem,hum,color='blue') ?plt.title("溫濕度相關(guān)性分析圖--Dragon少年") ?plt.xlabel("溫度/℃") ?plt.ylabel("相對濕度/%") ?# 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),一天的溫度和濕度具有強烈的相關(guān)性,呈負相關(guān)。當溫度較低時,空氣中水分含量較多,濕度自然較高,而溫度高時空氣中可容納的水汽增大,相對濕度隨之降低,但其實空氣中的水汽往往是增加的。
24小時內(nèi)每小時時段降水
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)#設置播放速度、是否循環(huán)播放等參數(shù) 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)],"河南") #打包輸入地區(qū)及對應降水量數(shù)據(jù) .set_series_opts(label_opts=opts.LabelOpts("")) #配置系列參數(shù),為顯示地區(qū)數(shù)據(jù) .set_global_opts( title_opts=opts.TitleOpts(title="河南省降雨分布--Dragon少年"), #全局參數(shù)中設置標題 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)) #將不同日期的數(shù)據(jù)加入到timeline中 return tl timeline_map(data).render("rainfall.html")
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)#設置播放速度、是否循環(huán)播放等參數(shù) 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)],"河南") #打包輸入地區(qū)及對應降水量數(shù)據(jù) .set_series_opts(label_opts=opts.LabelOpts("")) #配置系列參數(shù),為顯示地區(qū)數(shù)據(jù) .set_global_opts( title_opts=opts.TitleOpts(title="河南省累計降雨分布--Dragon少年"), #全局參數(shù)中設置標題 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)) #將不同日期的數(shù)據(jù)加入到timeline中 return tl timeline_map(data1).render("rainfalltoall_1.html")
至此,天氣數(shù)據(jù)分析可視化就完成啦
以上就是Python實現(xiàn)爬取天氣數(shù)據(jù)并可視化分析的詳細內(nèi)容,更多關(guān)于Python爬取天氣數(shù)據(jù)的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python+selenium select下拉選擇框定位處理方法
今天小編就為大家分享一篇python+selenium select下拉選擇框定位處理方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08使用PowerShell實現(xiàn)批量修改或替換文件名
這篇文章主要為大家介紹了基于PowerShell語言,對文件夾中全部文件的名稱加以批量替換、修改的方法,文中的示例代碼講解詳細,感興趣的可以了解一下2023-04-04python通過cookie模擬已登錄狀態(tài)的初步研究
對于那些需要在登錄環(huán)境下進行的爬蟲操作,模擬登陸或偽裝已登錄狀態(tài)是一個剛性需求。這篇文章主要介紹了python通過cookie模擬已登錄狀態(tài)的相關(guān)資料,需要的朋友可以參考下2016-11-11Python實現(xiàn)的基數(shù)排序算法原理與用法實例分析
這篇文章主要介紹了Python實現(xiàn)的基數(shù)排序算法,簡單說明了基數(shù)排序的原理并結(jié)合實例形式分析了Python實現(xiàn)與使用基數(shù)排序的具體操作技巧,需要的朋友可以參考下2017-11-11