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是一个十分好用的语言,里面丰富的库可以实现你所能想到的几乎所有功能,大家可以好好学习和交流,让我们一起建立一个互帮互助的社区!我的分享就到这里,谢谢大家!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值