社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

用Python采集历史天气数据

happy科研 • 3 年前 • 448 次点击  

大家好,我是才哥。

2021年11月6日晚,北京2021年的第一场冬雪降临,似乎比以往时候都要来的更早一些。

下雪了

今天,我们用Python采集北京历史天气数据,来看看今年的冬雪是不是真的来的更早一些呢!?

不过,在开始正文之前,咱们先赏一波雪景吧!!

下雪
故宫雪景图1
故宫雪景图2

好了,我们开始正文部分吧~~

目录:

  • 1. 近11年北京第1场冬雪时间

  • 2. 2021年北京天气数据全览

    • 2.1. 整体天气分布

    • 2.2. 不同月份天气分布

    • 2.3. 不同月份气温走势

    • 2.4. 全年气温变化动态图

  • 3. 数据采集

  • 4. 数据处理


1. 近11年北京第1场冬雪时间

其实,并不是每年的北京的冬天都有下雪,才哥女票就曾抱怨她在北京的两年就没见到过一场下雪!!比如,去年也就是2020年的冬季就没有下雪!

今年(2021年的冬雪是在11月6日),过去10年的第1场冬雪时间表如下:

过去10年的第1场冬雪时间表如下

我们可以看到,过去10年里有3个年头并没有冬雪 ,大部分年份的第1场冬雪都是在11下旬及之后才出现。相比之下,2015年和2012年的第1场冬雪来的时间相对更早一些(仅1日)是11月5日。不过吧,今年的这个雪属于大雪了,要比往年的都要大很多,更有下雪的味道!


2. 2021年北京天气数据全览

截止2021年10月31日共有304天,基于这304天的天气数据,我们可以看到:

2.1. 整体天气分布

合计有223天多云和晴天,占比超过73%;阴天和雾霾天有55天,占比约为18%;下雨天有24天,占比约为8%。

(绘图来自Excel的EasyShu插件)

注:在该网站历史数据中很多天空气质量差的算在了阴天里哈

2.2. 不同月份天气分布

(绘图参考《用python绘制北京近一年来空气质量热力图,看看北京的沙尘暴真的多吗?》)

下雨天主要集中在5-8月份、主要集中在2、3月份。

下雨天主要集中在5至8月份,主要集中在2、3月份。

热力图

2.3. 不同月份气温走势

(绘图来自Excel的EasyShu插件)

从每日最高气温来看,基本上6-8月属于高温月,很明显。

最高气温

从每日最低气温来看,7月的最低气温也属于全年度最高,而1月的最低气温可低到-20摄氏度,简直了。。

最低气温

2.4. 全年气温变化动态图


3. 数据采集

数据来源

历史天气网 https://lishi.tianqi.com/

网页简单解析如下

F12开发者模式

选定月份后,URL地址栏URL会变化,比如2021年10月在URL地址栏里是 https://lishi.tianqi.com/beijing/202110.html,在URL最后的202110就是变化的规律所在。

确定的URL规律后,我们再看看怎么解析出数据,我这里直接采用的是xpath方法哈,整体完整代码大家参考如下即可(修改地址即可,北京是beijing,其他城市的大家打开网页自己看即可,很简单)。

完整代码

import requests
from lxml import etree
import pandas as pd

def get_html(month):
    headers = {
        "Accept-Encoding""Gzip",  
        "User-Agent""Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36",
        }
    url = f'https://lishi.tianqi.com/beijing/{month}.html'
    
    r = requests.get(url, headers=headers)
    r_html = etree.HTML(r.text)
    
    return r_html

# 月份参数列表
month_list = pd.period_range('201101','202110',freq='M').strftime('%Y%m')
df = pd.DataFrame(columns=['日期''最高气温''最低气温''天气''风向'])
for i ,month in enumerate(month_list):
    r_html = get_html(month)
    # 找到存放历史天气数据的div节点
    div = r_html.xpath('.//div[@class="tian_three"]')[0]
    # 每个日期的历史天气数据的li节点组成的列表
    lis = div.xpath('.//li')
    for li in lis:
        item = {
            '日期':li.xpath('./div[@class="th200"]/text()')[0],
            '最高气温':li.xpath('./div[@class="th140"]/text()')[0],
            '最低气温':li.xpath('./div[@class="th140"]/text()')[1],
            '天气':li.xpath('./div[@class="th140"]/text()')[2],
            '风向':li.xpath('./div[@class="th140"]/text()')[3]
             }
        df = df.append(item, ignore_index=True)
    print(f'{i+1}/130月数据已采集')
df.to_excel(r'北京历史天气数据.xlsx',index=None)

最终,我们采集的数据结果预览如下:

结果预览


4. 数据处理

数据处理部分我们用到的也是pandas,以下将从处理思路和方法进行简单讲解,原始数据大家可以通过第三部分的数据采集爬虫代码运行获取或者后台回复 955北京历史天气文件夹中领取。

引入库并读取数据预览

import pandas as pd

df = pd.read_excel('北京历史天气数据.xlsx')
df.head()
前几条数据
# 后几条数据
df.tail()
后几条数据

通过观察采集下来的数据,我们可以发现日期字段中带有星期信息最高的最低气温中带有摄氏度符号天气中存在雨夹雪等字眼

为了进行数据的统计分析,我们需要对原始数据做简单的处理,操作如下:

分列日期与星期

df['日期'].str.split(' ',expand=True,n=1)

赋值

df[['日期','星期']] = df['日期'].str.split(' ',expand=True,n=1)

去掉气温的单位符号

df[['最高气温','最低气温']] = df[['最高气温','最低气温']].apply(lambda x: x.str.replace('℃',''))

新增字段标记是否有雪

df.loc[df['天气'].str.contains('雪'),'是否有雪']='是'
df.fillna('否',inplace=True)
# 预览
df.head()

再看数据info

df.info()

我们看这个数据info发现各字段基本都不是我们想要的类型,比如日期字段、最高最低气温期望是int类型等等。于是,我们需要进行相关数据类型转换啦。

数据类型转换

df['日期'] = pd.to_datetime(df['日期'])
df[['最高气温','最低气温']] = df[['最高气温','最低气温']].astype('int')

筛选出年月日信息

df['年份'] = df['日期'].dt.year
df['月份'] = df['日期'].dt.month
df['日'] = df['日期'].dt.day
# 预览
df.sample(5)
随机5条数据

寻找每年的第一场冬雪




    
snowData = df[df['是否有雪']=='是']
snowData[snowData['月份']>=9].groupby('年份').first().reset_index()

每年下雪天数

snowData.groupby('年份')['日期'].count().to_frame('下雪天数').reset_index()
年份下雪天数
201111
201213
201315
20146
201515
20166
20176
20182
20192
20206
20211



阅读更多


用Python读写Word文档入门

2021-11-05

007

2021-11-03

菜比肉贵?用Python采集蔬菜与肉类商品历史价格,带你了解了解~

2021-11-01

一道简单的电商数据分析笔试题:求组合商品的库存量

2021-10-27

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/122671
 
448 次点击