基于Python爬取天氣數據信息與可視化分析(文末完整源碼)
基于python的網絡爬蟲爬取天氣數據及可視化分析
可以看看演示視頻。
摘要
基于Python爬取天氣數據信息與可視化分析
本論文旨在利用Python編程語言實現天氣數據信息的爬取和可視化分析。天氣數據對于人們的生活和各個領域都有著重要的影響,因此準確獲取和有效分析天氣數據對于氣象預測、農業、旅游等方面至關重要。
在本文中,我們首先介紹了Python編程語言的基本原理和相關庫的使用。Python作為一種簡單易學且功能強大的編程語言,被廣泛應用于數據處理和分析領域。通過使用Python,我們可以方便地進行網頁爬取和數據處理。詳細介紹了如何使用Python編寫網絡爬蟲程序來獲取天氣數據。我們選擇了一些知名的氣象網站作為數據源,并通過分析網頁結構和標簽,準確提取所需的天氣信息。通過編寫自動化的爬蟲程序,可以快速獲取大量的天氣數據。
我們介紹了如何使用Python的數據處理和分析庫對獲取的天氣數據進行清理和整理。我們使用Pandas和NumPy等工具,去除重復數據、處理缺失值,并進行格式轉換,確保數據的準確性和一致性。
最后,我們展示了如何使用Python的可視化庫對清理后的天氣數據進行可視化分析。我們使用Matplotlib庫,繪制折線圖、散點圖等,展示不同時間段內的溫度變化、濕度分布等。通過這些可視化圖表,我們可以更直觀地觀察和分析天氣數據,揭示其潛在的趨勢和規律。
通過使用Python編程語言,我們可以快速獲取和分析大量的天氣數據,并通過可視化手段展示其特征和規律。這將有助于人們更好地理解和應用天氣數據,從而做出更準確的決策和規劃。
關鍵詞:天氣數據信息;處理數據信息;數據可視化分析;模型構建
第1章 引言
1.1 選題背景與意義
天氣數據是人們日常生活中非常重要的信息之一,對于氣象學、農業、城市規劃、交通運輸等領域都有著重要的影響。隨著科技的發展,越來越多的天氣數據可以通過互聯網獲取,而通過Python爬取天氣數據并進行可視化分析就成為了一個熱門的研究方向。
數據獲取與處理:通過Python爬取天氣數據,可以方便地獲取到各種天氣參數,如溫度、濕度、降水量等。這些數據對于研究天氣變化、分析氣候模式、進行氣象預測具有重要意義。
數據分析與模式識別:通過對爬取的天氣數據進行統計分析和模式識別,可以揭示天氣現象的規律性和周期性。這有助于理解天氣變化的趨勢和模式,為氣象預測和應對天氣變化提供參考。
可視化分析:通過將天氣數據進行可視化分析,可以更直觀地展示天氣變化的趨勢和模式。這有助于決策者更好地理解和利用天氣信息,例如用于城市規劃、交通運輸等方面的決策制定。
因此,基于Python爬取天氣數據并進行可視化分析作為本文選題具有重要的背景和意義,對于提高天氣數據的利用價值以及相關領域的研究和應用都具有積極的推動作用。
1.3 本文的研究內容與主要工作
本文涵蓋了氣象數據的獲取、處理與分析,以及基于歷史天氣數據進行的氣候變化研究、預測模型建立等方面。在數據獲取方面,使用各種方法從氣象局、科研機構或第三方數據提供商獲取歷史天氣數據。同時,也有研究對獲取的數據進行清洗、整合和格式化處理,確保數據的可靠性和完整性。同時使用Python編程語言中的數據分析庫(如pandas、numpy)和可視化庫(如matplotlib)來進行歷史天氣數據的分析和可視化。這些工具可以幫助更好地理解數據中的規律和趨勢,并生成直觀的可視化圖表。并且可以利用歷史天氣數據來研究氣候變化趨勢,包括全球范圍的氣候變化、特定地區的氣候特征變化等。通過分析歷史天氣數據,可以發現氣候變化的規律,并探討其對生態環境、農業生產等方面的影響。除了純粹的數據分析和可視化,還有建立氣象數據的預測模型,以實現對未來天氣情況的預測。這些模型通常基于歷史氣象數據和機器學習算法,能夠為氣象預報提供更準確的參考。
1.4 本文的論文結構與章節安排
本文共分為5章,章節內容安排如下:
- 第1章:引言
- 第2章:歷史天氣網站數據的獲取
- 第3章:數據可視化分析與處理
- 第4章:模型預測
- 第5章:總結與展望
第2章 歷史天氣網站數據的獲取
2.1 天氣網站數據來源
數據來源:查看天氣網網址:http://www.tianqi.com.cn。訪問廣東省東莞市的天氣網址:https://lishi.tianqi.com/dongguan/index.html,利用Python的爬蟲技術從網站上爬取東莞市2018-2023年天氣數據信息。
2.2 利用Python進行數據爬取與數據處理
首先查看中國天氣網的網址:https://lishi.tianqi.com/dongguan/index.html。訪問廣東省東莞市的天氣信息,我們主要訪問的是2023年中國天氣網的天氣數據,對東莞2023年1-11月份數據進行爬取。采用requests.get方法,請求網頁,運行后顯示成功訪問,則得到的是網頁的所有字符串文本。這就是請求過程。
采用xpath庫對獲取的字符串進行數據提取:首先對網頁進行檢查,找到需要獲取數據的標簽(截圖舉例說明)采用lxml解析HTML、XPath提取數據,通過循環調用getWeather函數,找到需要獲取數據的標簽,提取標簽的數據值,保存到對應列表并進行切片處理。
2.3 數據存儲與數據標準化處理
數據存儲:將爬取的數據存儲在CSV文件中,對數據進行了結構化處理,每個樣本包含日期、最高氣溫、最低氣溫、天氣狀況、風向、風速6個特征數據。
數據標準化處理:對讀取存儲的CSV數據文件對數據進行格式化、清洗,去掉無效行等將數據轉換為字典的格式,即每個字典代表一天的數據,字典的鍵和爬蟲部分一致,但是值都轉換為合適的類型,例如日期轉換為datetime對象,溫度轉換為浮點數等,方便后續處理數據分析與可視化。
第3章 數據可視化分析與處理
3.1 利用matplotlib庫繪制圖像
折線圖:采用matplotlib中plt.plot()方法分別制作出每月的溫度變化曲線圖,并用plt.plot()方法點出最高溫和最低溫,并分別畫出最高溫度線、最低溫度線。
散點圖:使用plt.scatter()方法將日期和時間為橫坐標、溫度為縱坐標,每天氣溫情況在圖中繪制出來,展示相關數據。
餅狀圖:使用plt.pie()方法對每月天氣狀況進行了餅狀圖繪制,并且根據5個等級的不同。相應餅柱狀圖的顏色各異,更直觀的顯示天氣狀況。
熱力圖:使用plt.imshow()方法將日期和時間為橫坐標、溫度范圍為縱坐標,整合最高溫度和最低溫度數據。
3D立體圖:使用ax.plot_trisurf和ax.grid方法繪制月最高溫和最低溫3D曲面圖。
(說明,這里本來要做抓取12個月 每個月份生成一張對應的可視化圖,再將這些可視化圖合作一個GIF動態圖,達到類似輪播圖的效果。直到我剛好看見一個動態圖,有了新的想法。。。)
3.2 生成靜態詞云與動態詞語圖
使用wordcloud庫,創建WordCloud對象,設置參數生成詞云圖,使用一個熱門表情包作為遮罩圖片,使詞云圖更具特色,增強觀感,吸引注意力,添加趣味性。并將詞云圖保存到指定的路徑。
最后,我們需要制作詞云動圖,包括:
- 分解GIF幀:用opencv讀取熱門表情包的GIF圖片,保存每一幀為圖片,作為遮罩圖片的序列。
- 生成詞云:對每張遮罩圖片調用詞云生成函數, 生成對應的詞云圖片,作為詞云圖片的序列。
- 拼接GIF:用imageio庫將詞云圖片的序列順序拼接成GIF圖片,并保存到指定的路徑。
第4章 模型預測
4.1 構建和訓練模型的設計
構建模型:使用sklearn庫構建一個線性回歸模型,設置參數。
- 訓練模型:將訓練集的X和Y傳入,訓練模型,得到模型的參數。
- 預測模型:使用predict()方法,將測試集的X傳入,得到預測Y,與測試集的真實Y進行比較,評估模型的性能。
4.2 繪制散點圖一元回歸線圖
- 繪制散點圖:使用matplotlib庫繪制散點圖,展示東莞市每一天的日期和平均溫度的關系,用不同的顏色區分訓練集和測試集。
- 繪制回歸線:使用matplotlib庫繪制回歸線,展示模型的分析結果,用不同的顏色區分訓練集和測試集。
- 設置圖表:設置合適的標題、圖例、坐標軸標簽等,使圖表清晰易懂。并將圖表保存到指定的路徑。
第5章 總結與展望
5.1 工作總結
在文中,我們旨在利用爬取的歷史天氣數據進行可視化分析。首先,我們選擇了一個可靠的數據源,并使用Python編程語言和BeautifulSoup庫實現了數據的爬取。接著,我們對原始數據進行了清洗和處理,包括缺失值的處理和數據格式轉換。然后,我們采用了Matplotlib可視化工具,設計了多種圖表類型,如折線圖、柱狀圖和熱力圖,以展示歷史天氣數據的趨勢和變化。通過分析結果,我們發現了不同時間段內溫度、天氣狀況等指標的變化情況,并與歷史數據進行了比較。總的來說,本次研究通過爬取歷史天氣數據并進行可視化分析,為相關領域的研究提供了有益的參考和啟示。
一些參考鏈接
[1]python Matplotlib庫:根據excel生成各種柱狀圖:https://mp.weixin.qq.com/s/lhOB8XO2zhjLRQZVqQe9sg
[2]踏入數據可視化的世界:Matplotlib庫的完整學習指南:https://mp.weixin.qq.com/s/uUWQti7lXuS2CE7SU2FnjQ
[3]使用Python可視化CSV文件數據:https://mp.weixin.qq.com/s/iKxP-8FIdGyi8F6kRCCouA
[4]Python數據可視化-詞云:https://mp.weixin.qq.com/s/kz9zBYwN3HDm9vESJ5VqgQ
[5]Python 實現圖片轉字符畫,靜態圖、GIF 都能轉:https://mp.weixin.qq.com/s/bzgpstD5_u6z75FvXYhVQg
[6]【python】4行代碼實現將多張圖片合成gif動圖(imageio):https://mp.weixin.qq.com/s/LIlX8eu6MOhwa32ZS19kIQ
[7] Python基礎教程:強大的Pandas數據分析庫: http://www.poycode.cn/coding/python/python-basic-tutorial-18/
[8]Python基礎教程:sklearn機器學習入門:https://mp.weixin.qq.com/s/8PoPxaR2R25krNt7H44zZA
[9]學習 Scikit-learn,從這 5 個步驟開始:https://mp.weixin.qq.com/s/QTacqEFJcdUoQsrwe3jjUw
[10] sklearn: https://scikit-learn.org/stable/index.html
**
說明:這只是一個學了十一二周python的課程大作業,
并不是真的畢業論文,只是學校要求按照畢業論文的格式寫。
完整代碼如下
各部分懶得封裝了,使用jupyter依次運行即可。
加了一些注釋,方便閱讀。
**
import requests
from lxml import etree
import csv
import numpy as np
from collections import defaultdict
from datetime import datetime
import matplotlib.pyplot as plt
from matplotlib import font_manager
from matplotlib import rcParams
from mpl_toolkits.mplot3d import Axes3D 用于創建3D圖形
import imageio.v2 as imageio
from IPython.display import Image, display
from wordcloud import WordCloud
from PIL import Image
# 設置字體為支持減號的字體,例如"SimHei"
rcParams['font.sans-serif'] = ['SimHei']
font = font_manager.FontProperties(fname="C:/Windows/Fonts/simsun.ttc", size=14) # 請將路徑替換為你的字體文件路徑
plt.rcParams['axes.unicode_minus'] = False # 解決保存圖像時負號'-'顯示為方塊的問題def getWeather(url):# 請求頭信息:瀏覽器版本型號,接收數據的編碼格式headers = {# 必填,不填拿不到數據# 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'}# 請求 接收到了響應數據resp = requests.get(url, headers=headers) # 使用lxml解析HTML tree = lxml.html.fromstring(resp.text) resp_list = tree.xpath("//ul[@class='thrui']/li") # for循環迭代遍歷 day_weather_info = []for li in resp_list: dates = li.xpath('.//div[@class="th200"]/text()') # 提取日期 max_temperatures = li.xpath('.//div[@class="th140"]/text()') # 提取最高氣溫 min_temperatures = li.xpath('.//div[@class="th140"][2]/text()') # 提取最低氣溫 weather_conditions = li.xpath('.//div[@class="th140"][3]/text()') # 提取天氣情況 wind_directions = li.xpath('.//div[@class="th140"][4]/text()')[0].split(' ')[0] # 提取風向 wind_speeds = li.xpath('.//div[@class="th140"][4]/text()')[0].split(' ')[1] # 提取風速 # 將提取的信息存儲到day_weather_info列表中 day_weather_info.append({ "日期": dates[0], "最高氣溫": max_temperatures[0], "最低氣溫": min_temperatures[0], "天氣情況": weather_conditions[0], "風向": wind_directions, "風速": wind_speeds })return day_weather_infoweathers = [getWeather(f'https://lishi.tianqi.com/dongguan/2023{str(month).zfill(2)}.html') for month in range(1, 13)]
print(weathers)# 數據寫入(一次性寫入)
with open("test01_weather.csv", "w",newline='') as csvfile:writer = csv.writer(csvfile)# 先寫入列名:columns_name 日期 最高氣溫 最低氣溫 天氣writer.writerow(["日期", "最高氣溫", "最低氣溫", '天氣',"風向","風速"])# 一次寫入多行用writerows(寫入的數據類型是列表,一個列表對應一行)writer.writerows([list(day_weather_dict.values()) for month_weather in weathers for day_weather_dict in month_weather])
print("寫入成功!")# 讀取數據
with open("weather.csv", "r", newline='') as csvfile:
# with open("weather_test.csv", "r", newline='') as csvfile:reader = csv.reader(csvfile)# 跳過列名# next(reader)# 逐行讀取數據read = []# for row in reader:# if row: # 檢查行是否為空# read.append(row)read = [row for row in reader # 檢查行是否為空if any(cell.strip() for cell in row)]
print("讀取成功!")
print(read)# 數據標準化處理
original_data = read# 初始化一個空列表來存儲處理后的數據
formatted_data = []# 遍歷原始數據
for item in original_data[1:]: # 從第二行開始,因為第一行是表頭formatted_item = {'日期時間': item[0],'最高溫度': item[1],'最低溫度': item[2],'天氣狀況': item[3]}formatted_data.append(formatted_item)
# 打印處理后的數據
print(formatted_data[0])def show(date_time,high_temp,low_temp,weather):# 繪制折線圖plt.plot(date_time, high_temp, label='最高溫度')plt.plot(date_time, low_temp, label='最低溫度')plt.xlabel('日期時間')plt.ylabel('溫度')plt.title(str(month)+'月最高溫度和最低溫度折線圖')plt.legend()plt.savefig('./show/plot_'+str(month)+'.jpg') # 將圖片保存plt.show()# print('plot_'+str(month)+'.jpg保存成功!')# 使用scatter()函數繪制散點圖plt.scatter(date_time, high_temp, label='最高溫度')plt.scatter(date_time, low_temp, label='最低溫度')# 添加顏色條cbar = plt.colorbar()cbar.set_label('Color Intensity')# 設置標題和標簽plt.title(str(month)+'月最高溫度和最低溫度散點圖')# 設置x軸和y軸的標簽plt.xlabel('日期時間')plt.ylabel('溫度')# 添加圖例plt.legend()plt.savefig('./show/scatter_'+str(month)+'.jpg') # 將圖片保存# 顯示圖形plt.show()# print('scatter_'+str(month)+'.jpg保存成功!')# 繪制餅狀圖# 提取數據weather = [item['天氣狀況'] for item in monthly_data[month]]# 計算每個天氣狀況的數量weather_counts = {weather_type: weather.count(weather_type) for weather_type in set(weather)}plt.pie(weather_counts.values(), labels=weather_counts.keys(), autopct='%1.1f%%')plt.title(str(month)+'月天氣狀況分布餅狀圖')plt.savefig('./show/pie_'+str(month)+'.jpg') # 將圖片保存plt.show()# print('pie_'+str(month)+'.jpg保存成功!')# 繪制熱力圖# 整合最高溫度和最低溫度數據temp_range = np.array([high - low for high, low in zip(high_temp, low_temp)])# 創建一個新的圖形plt.figure()plt.imshow(temp_range.reshape(-1, 1), cmap='hot', aspect='auto')# 設置x軸和y軸的標簽plt.xlabel('日期時間')plt.ylabel('溫度范圍')# 添加顏色條plt.colorbar(label='溫度差')# 添加標題plt.title(str(month)+'月最高溫度和最低溫度熱力圖')plt.savefig('./show/hot_'+str(month)+'.jpg') # 將圖片保存# 顯示圖形plt.show()# print('hot_'+str(month)+'.jpg保存成功!')#3D曲面圖# 創建一個新的圖形fig = plt.figure(figsize=(8,5),dpi=100)ax = fig.add_subplot(111, projection='3d')# 提取數據X = [item['日期時間'][-2:] for item in monthly_data[month]]Y = [int(item['最高溫度']) for item in monthly_data[month]]Z = [int(item['最低溫度']) for item in monthly_data[month]]# 繪制帶有網格線的曲面圖ax.plot_trisurf(X, Y, Z, cmap='viridis', edgecolor='none')ax.grid(True)plt.title(str(month)+'月最高溫度和最低溫度3D曲面圖')# 設置x軸和y軸的標簽ax.set_xlabel('日期時間')ax.set_ylabel('最高溫度')ax.set_zlabel('最低溫度')plt.savefig('./show/3D_'+str(month)+'.jpg') # 將圖片保存# 顯示圖形plt.show()# print('3D_'+str(month)+'.jpg保存成功!')# 初始化 monthly_data 字典
monthly_data = defaultdict(list)
# 遍歷 formatted_data,將日期時間字符串轉換為月份并添加到 monthly_data 字典中
for item in formatted_data:month = datetime.strptime(item['日期時間'], '%Y-%m-%d').monthif 1 <= month <= 12:monthly_data[month].append(item)# 提取數據
for month in range(1, 12):date_time = [item['日期時間'][-2:] for item in monthly_data[month]]high_temp = [int(item['最高溫度']) for item in monthly_data[month]]low_temp = [int(item['最低溫度']) for item in monthly_data[month]]weather = [item['天氣狀況'] for item in monthly_data[month]]# 調用 show() 函數繪制折線圖、散點圖、餅狀圖和熱力圖、3D曲面圖show(date_time, high_temp, low_temp, weather)import numpy as np
from PIL import Image
from wordcloud import WordCloud
import matplotlib.pyplot as plt
# 制作靜態詞云圖方法
def generate_wordcloud(image_path, font_path, weather_data, save_path=None):# 讀取字圖片文件,生成輪廓mask_array = np.array(Image.open(image_path))# 從formatted_data變量中提取天氣狀況數據,將其轉換為字符串weather = weather_dataweather_str = ''.join(weather)# 生成詞云圖,并顯示出來wordcloud = WordCloud(background_color='white', font_path=font_path, mask=mask_array,max_words=len(weather_str)).generate(weather_str)plt.imshow(wordcloud, interpolation='bilinear')plt.axis('off')# 如果提供了保存路徑,則保存詞云圖if save_path:plt.savefig(save_path)print("詞云圖已保存至"+save_path)# else:# plt.show()# 示例用法
# 生成靜態詞云圖
image_path = "./sucai/basketball.jpg"
font_path = 'simhei.ttf'weather_data = [item['天氣狀況'] for item in formatted_data]*2# 調用函數時提供保存路徑,將保存詞云圖為指定路徑的文件
save_path = "./sucai/basketball2.jpg"
generate_wordcloud(image_path, font_path, weather_data, save_path)
display(Image.open(image_path).resize((100, 100)))# 把GIF逐幀分解保存
import cv2
def process_gif_to_jpg(gif_path, output_folder):# 讀取GIF圖像gif = cv2.VideoCapture(gif_path)# 檢查是否成功打開GIF文件if not gif.isOpened():print("無法打開GIF文件")return# 獲取GIF的幀數frame_count = int(gif.get(cv2.CAP_PROP_FRAME_COUNT))# 遍歷每一幀for i in range(frame_count):# 讀取當前幀ret, frame = gif.read()# 檢查是否成功讀取幀if not ret:print("無法讀取幀")break# 構建輸出文件名output_file = f"{output_folder}/frame_{i}.jpg"print(output_file)# 保存當前幀為jpg圖cv2.imwrite(output_file, frame)# 釋放GIF資源gif.release()# 使用示例
gif_path = r'./sucai/basketball.gif'
output_folder = r'./sucai/tmp'
process_gif_to_jpg(gif_path, output_folder)# 生成動態詞云圖
import imageio
from IPython.display import Image, display
from imageio import imread, mimsavedef create_gif(image_files, output_file, fps=10): images = [] for image_file in image_files: images.append(imread(image_file)) mimsave(output_file, images, fps=fps) display(Image(filename=output_file))# 使用函數的方式創建GIF
images_path = ['./sucai/tmp2/jitu_{}.jpg'.format(i) for i in range(160)]
output_path='./sucai/dance.gif'
create_gif(images_path, output_path)# 打開文件,準備獲取入近6年天氣數據
with open("6years_weather.csv", "w", newline='') as csvfile:writer = csv.writer(csvfile)# 先寫入列名:columns_name 日期 最高氣溫 最低氣溫 天氣writer.writerow(["日期", "最高氣溫", "最低氣溫", '天氣'])# for循環生成for year in range(2018, 2024):yearly_weather = [] # 創建一個新的列表來存儲每年的天氣數據for month in range(1, 13):# 獲取某一月的天氣信息# 三元表達式weather_time = str(year) + ('0' + str(month) if month < 10 else str(month))print(weather_time)url = f'https://lishi.tianqi.com/dongguan/{weather_time}.html'# 爬蟲獲取這個月的天氣信息weather = getWeather(url)# 將這個月的天氣數據添加到年度天氣數據列表中yearly_weather.extend([list(day_weather_dict.values()) for day_weather_dict in weather])# 一次寫入一年的天氣數據writer.writerows(yearly_weather)print(str(year)+"年數據存入完成。")# 清空年度天氣數據列表,以便于存儲下一年的數據yearly_weather.clear()print("6年數據寫入成功!")# 讀取數據
with open("6years_weather.csv", "r", newline='') as csvfile:reader = csv.reader(csvfile)read = [row for row in reader # 檢查行是否為空if any(cell.strip() for cell in row)]
print("6年數據讀取成功!")
print(read)import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn import metrics
import matplotlib.pyplot as plt# 嵌套列表
data = read
# 轉換為DataFrame
df = pd.DataFrame(data[1:], columns=data[0])# 劃分數據集
X = df[['最高氣溫']].astype(float) # 特征變量
y = df['最低氣溫'].astype(float) # 目標變量
# 劃分訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.5, random_state=0) # 訓練模型
model = LinearRegression() # 創建線性回歸模型
model.fit(X_train, y_train) # 使用訓練集訓練模型# 預測
y_pred = model.predict(X_test) # 使用模型對測試集進行預測# 繪制散點圖和回歸線
plt.scatter(X_test, y_test, color='blue')
plt.plot(X_test, y_pred, color='red')
plt.title('最高氣溫與最低氣溫的線性回歸模型')
plt.xlabel('最高氣溫')
plt.ylabel('最低氣溫')
plt.show()