溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python怎么實(shí)現(xiàn)爬取天氣數(shù)據(jù)并可視化分析

發(fā)布時(shí)間:2022-02-22 15:14:26 來(lái)源:億速云 閱讀:190 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(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ù)并可視化分析”吧!

核心功能設(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ì)降雨量。

實(shí)現(xiàn)步驟

爬取數(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。

Python怎么實(shí)現(xiàn)爬取天氣數(shù)據(jù)并可視化分析

根據(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" "

Python怎么實(shí)現(xiàn)爬取天氣數(shù)據(jù)并可視化分析

處理數(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 &lt;=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 &lt; 7 and i &gt; 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)了。

Python怎么實(shí)現(xiàn)爬取天氣數(shù)據(jù)并可視化分析

風(fēng)向風(fēng)級(jí)雷達(dá)圖

統(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é)果如下:

Python怎么實(shí)現(xiàn)爬取天氣數(shù)據(jù)并可視化分析

觀察可以發(fā)現(xiàn),當(dāng)天的東北風(fēng)最多,平均風(fēng)級(jí)達(dá)到了1.75級(jí)。

溫濕度相關(guān)性分析

我們可以分析溫度和濕度之間是否存在關(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é)果如下:

Python怎么實(shí)現(xiàn)爬取天氣數(shù)據(jù)并可視化分析

觀察可以發(fā)現(xiàn),一天的溫度和濕度具有強(qiáng)烈的相關(guān)性,呈負(fù)相關(guān)。當(dāng)溫度較低時(shí),空氣中水分含量較多,濕度自然較高,而溫度高時(shí)空氣中可容納的水汽增大,相對(duì)濕度隨之降低,但其實(shí)空氣中的水汽往往是增加的。

24小時(shí)內(nèi)每小時(shí)時(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")

24小時(shí)累計(jì)降雨量

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í)!

向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI