Python爬取天气数据及可视化动态图
爬取天气数据
大家好,接下来这篇是对Python语言程序设计课程结课作业的分析,以便同学们对爬虫应用有个认知,方便完成自己课程的Python大作业。三个环节爬取数据,数据分析,可视化,因为天气是我们常常会关注的点,可能未来工程时间的安排,以及出行的安排,未来的旅游计划等等都和天气密不可分,如果能让天气数据以图像的方式呈现在眼前,将会有更直观的视觉冲击。
网址选取
这边选取的是中国天气网,杭州的天气数据。
链接1: http://www.weather.com.cn/weather/101210101.shtml
链接2:http://www.weather.com.cn/weather15d/101210101.shtml
url = 'http://www.weather.com.cn//weather//101210101.shtml'
url8_15 = 'http://www.weather.com.cn/weather15d/101210101.shtml'
因为中国天气网是一个非盈利性的网站,所以几乎没有反爬虫措施,很适合我们新手上手尝试。
右键页面点开检查,或者Ctrl + Shift + i快捷键打开检查页面,点开网络,其中一个1.shtml文件(也就是我们的网站)访问信息
设置请求头:
headers = {'Use-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0'}
创建request对象
引入一个request库,获取一个request对象
from urllib import request
# 获取一个request对象
req = request.Request(url,headers=headers)
response = request.urlopen(req)
req8_15 = request.Request(url8_15,headers=headers)
response8_15 = request.urlopen(req8_15)
异常处理,保存html文件
判断响应不是404(失败)就是200(成功),保存html文件,就可以分离处理,不用一直频繁访问网站,防止反爬虫措施响应。
import sys
# 判断响应结果
if response.getcode() == 200:
print("访问成功")
data = response.read()
# document.charset看网页的编码方式
data = str(data,encoding='UTF-8')
with open('data.html',mode='w',encoding='UTF-8') as f:
f.write(data)
else:
print("error")
sys.exit()
# 判断响应结果
if response8_15.getcode() == 200:
print("访问成功")
data = response8_15.read()
# document.charset看网页的编码方式
data = str(data, encoding='UTF-8')
with open('data8_15.html', mode='w', encoding='UTF-8') as f:
f.write(data)
else:
print("error")
sys.exit()
得到html文件
其中UTF-8的编码方式是可以通过网页的控制台进行查询的.
输入:document.charset
解析数据
解析数据一直是爬虫整个过程中相对比较复杂的一个过程,因为需要结合每个网站不同的特点进行特定的处理,才能过滤掉我们不需要的数据,使留下的数据能够方便的进行可视化过程。
这边我们使用的是BeautifulSoup库
from bs4 import BeautifulSoup
解析当天以及2-7天数据
通过分析网页中html代码可以得到当天数据信息在script中,以json数据形式保存
、
# 创建一个BeautifulSoup对象
bs = BeautifulSoup(html,'html.parser')
# 分析今天数据
data = bs.select(".left-div script")
text = data[3].string
# print(text)
text = text[text.index('=') + 1:-2] # 移除多余元素,保留字典
dic = eval(text)
lst = dic['od']['od2']
用json库解析也同理,这里我用的是eval特殊用法
之后进行数据分析
final_day = [] # 存放当天的数据
count = 0
for i in lst:
temp = []
if count <= 23:
temp.append(i['od21']) # 添加时间
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)
count = count + 1
同理找到2-7天的数据在ul class=“t clearfix” 之中
进行数据分析,本文统一用的都是select(CSS规则),find,find_all
# 分析后六天数据
day2_7 = bs.select(".clearfix li.sky")
# print(data2_7[1])
final = []
i = 0 # 控制爬取的天数
for day in day2_7: # 遍历找到的每一个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)
# 存最高气温最低气温
if inf[1].find('i') is None: # 天气预报可能没有最低气温
tem_low = None
temp.append(tem_low)
else:
tem_low = inf[1].find('i').string # 找到最低气温
temp.append(tem_low[:-1])
if inf[1].find('span') is None: # 天气预报可能没有最高气温
tem_high = None
temp.append(tem_high)
else:
tem_high = inf[1].find('span').string # 找到最高气温
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 += 1
解析8-15天数据
8-15天与上文同理,可以自行尝试
保存至Excel
保存Excel这边引入了一个Workbook库,可以直接对excel进行操作
from openpyxl import Workbook
# 创建工作簿Workbook对象
book = Workbook()
# 创建工作表sheet
sheet = book.create_sheet('weather1',0)
sheet2_15 = book.create_sheet('weather14',1)
# 向工作表中添加数据
sheet.append(['小时', '温度', '风力方向', '风级', '降水量', '相对湿度', '空气质量'])
sheet2_15.append(['日期', '天气', '最低气温', '最高气温', '风向1', '风向2', '风级'])
for i in data:
sheet.append(i)
for j in data2_15:
sheet2_15.append(j)
# 输出保存
book.save('weather.xlsx')
得到Excel表格
可视化处理
可视化处理是我们爬取数据,整理数据的目的所在,得到一个清晰而又全面的图形展示,这样能给我们直观的数据体验,并且能从图像中说明一些问题和道理。
引入几个库:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import wordcloud
from PIL import Image
import math
当天数据可视化
这里是对一天数据可视化,反映过去一天的温度,湿度,空气质量情况。
动态温度曲线
关键代码动态图:
plt.plot(xy[0:2], y[0:2], color='red', label='温度') # 画出温度曲线
plt.scatter(xy[0:2], y[0:2], color='red') # 点出每个时刻的温度点
plt.plot([0,2], [tem_ave, tem_ave], c='blue', linestyle='--', label='平均温度') # 画出平均温度虚线
for i in range(1,23):
plt.plot(xy[i:i+2], y[i:i+2], color='red') # 画出温度曲线
plt.scatter(xy[i:i+2], y[i:i+2], color='red') # 点出每个时刻的温度点
plt.plot([i,i+1], [tem_ave, tem_ave], c='blue', linestyle='--') # 画出平均温度虚线
plt.pause(0.1) # 延时0.1
plt.text(tem_max_hour, tem_max + 0.15, str(tem_max), ha='center', va='bottom', fontsize=10.5) # 标出最高温度
plt.text(tem_min_hour, tem_min + 0.15, str(tem_min), ha='center', va='bottom', fontsize=10.5) # 标出最低温度
# plt.xticks(x)
plt.legend()
plt.title('过去一天温度变化曲线图')
plt.xlabel('时间/h')
plt.ylabel('摄氏度/℃')
plt.show()
温度曲线
动态相对湿度曲线
关键代码同上理,就不过多阐述了,后续完整代码一并奉上。
相对湿度曲线
动态空气质量曲线
这边是用柱形图呈现,颜色越深代表污染越严重,等级按照空气质量国际等级来划分,可以反映这一天不同时间点杭州天气质量的情况,从而更好的安排出门时间。
# 颜色越深,污染越严重
for i in range(0, 24):
if y[i] <= 50:
plt.bar(xy[i], y[i], color='lightgreen', width=0.7) # 1等级
elif y[i] <= 100:
plt.bar(xy[i], y[i], color='wheat', width=0.7) # 2等级
elif y[i] <= 150:
plt.bar(xy[i], y[i], color='orange', width=0.7) # 3等级
elif y[i] <= 200:
plt.bar(xy[i], y[i], color='orangered', width=0.7) # 4等级
elif y[i] <= 300:
plt.bar(xy[i], y[i], color='darkviolet', width=0.7) # 5等级
elif y[i] > 300:
plt.bar(xy[i], y[i], color='maroon', width=0.7) # 6等级
plt.pause(0.1) # 延时0.1
plt.plot([0, 24], [air_ave, air_ave], c='black', linestyle='--') # 画出平均空气质量虚线
plt.text(air_max_hour + 0.15, air_max + 0.15, str(air_max), ha='center', va='bottom', fontsize=10.5) # 标出最高空气质量
plt.text(air_min_hour + 0.15, air_min + 0.15, str(air_min), ha='center', va='bottom', fontsize=10.5) # 标出最低空气质量
空气质量柱形图
未来十四天数据可视化
温度曲线绘制
代码逻辑很简单,画了最高和最低温度分布,并在温度上面标出数值,可以直观反应出温差以及最高温究竟多高,最低温究竟多低,以及未来14天温度走势。
x = range(1, 15)
plt.figure(1)
plt.plot(x, tem_high, color='red', label='高温') # 画出高温度曲线
plt.scatter(x, tem_high, color='red') # 点出每个时刻的温度点
plt.plot(x, tem_low, color='blue', label='低温') # 画出低温度曲线
plt.scatter(x, tem_low, color='blue') # 点出每个时刻的温度点
plt.plot([1, 15], [tem_high_ave, tem_high_ave], c='black', linestyle='--') # 画出平均温度虚线
plt.plot([1, 15], [tem_low_ave, tem_low_ave], c='black', linestyle='--') # 画出平均温度虚线
plt.legend()
# 作上标
for i,j,z in zip([i for i in range(1,15)],tem_low,tem_high):
plt.text(i, z + 0.30, str(z), ha='center', va='bottom', fontsize=10.5) # 标出最高温度
plt.text(i, j + 0.30, str(j), ha='center', va='bottom', fontsize=10.5) # 标出最低温度
天气饼图绘制
天气饼图可以反映未来这几天的天气分布情况,大部分是什么类型的天气,可以很直观的看出哪种天气出现的频率更高。
def weather_pie(data):
"""绘制天气饼图"""
weather = list(data['天气'])
dic_wea = {}
for i in range(0, 14):
if weather[i] in dic_wea.keys():
dic_wea[weather[i]] += 1
else:
dic_wea[weather[i]] = 1
print(dic_wea)
explode = [0.01] * len(dic_wea.keys())
color = ['silver', 'yellow', 'salmon', 'grey', 'lime', 'gold', 'red', 'green', 'pink']
plt.pie(dic_wea.values(), explode=explode, labels=dic_wea.keys(), autopct='%1.1f%%', colors=color)
plt.title('未来14天气候分布饼图')
plt.show()
天气词云图
词云图也是非常常见的一个数据可视化的手段,可以反应某种情况出现的频率之大,也可以根据自己心中喜欢的图形来做不同的形状,个性而美观。
def generate_wordcloud(data):
# 词云
path_img = "ab5.png"
background_image = np.array(Image.open(path_img))
# 生成
weather = list(data['天气'])
a = ['天气','云','词']
weather_data = ','.join(weather)
weather_data = weather_data.join(a)
wordcloud1 = wordcloud.WordCloud(font_path='C:\\Windows\\Fonts\\msyh.ttc', background_color="white",\
mask=background_image, max_words=20).generate(weather_data)
wordcloud1.to_file('weather.png')
plt.title("未来十四天天气词云图",fontsize = 14)
plt.imshow(wordcloud1, interpolation="bilinear")
plt.axis("off")
plt.show()
总结
这里希望大家能够自己理解其中的含义,如果要使用,我这也不多做阻碍,你们可以自行使用,但是精进自己的技术才是关键,不能过度依赖别人的代码,可以学习我的思路和使用技巧,然后加上你们自己的心意,融会贯通,Python是一个十分好用的语言,里面丰富的库可以实现你所能想到的几乎所有功能,大家可以好好学习和交流,让我们一起建立一个互帮互助的社区!我的分享就到这里,谢谢大家!