欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

技术图文:如何爬取一个地区的气象数据(上)?

程序员文章站 2022-05-09 14:07:19
...

背景

架空线路主要指架空明线,架设在地面之上,是用绝缘子将输电导线固定在直立于地面的杆塔上以传输电能的输电线路。架设及维修比较方便,成本较低,但容易受到气象和环境(如大风、雷击、污秽、冰雪等)的影响而引起故障。

在对架空线路故障进行研究的时候,我们需要从网上爬取其所在位置的气象数据。

在爬取气象数据之前需要对爬取数据的网站进行分析,以邯郸地区为例:

技术图文:如何爬取一个地区的气象数据(上)?

2019年10月份天气数据的URL:

http://lishi.tianqi.com/handan/201910.html

2019年09月份天气数据的URL:

http://lishi.tianqi.com/handan/201909.html

以此类推,该网站可以获取邯郸地区2011年到2019年的全部数据,只要发现请求url地址的规律就可以自动化的下载这些数据了。本篇图文作为爬取数据的引导,先来介绍构造一个区间段日期的方法。


技术分析

1. datetime 模块简介

datetime是Python处理日期和时间的模块,该模块包含一个datetime类用来处理程序中遇到的日期和时间,还包含一个timedelta类,通过该类可以对datetime对象进行加减运算。

str转换为datetime

  • datetime.strptime(date_string, format)

Return a datetime corresponding to date_string, parsed according to format.

from datetime import datetime

cday = datetime.strptime('2019-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
print(cday)

# 2019-06-01 18:19:59

字符串'%Y-%m-%d %H:%M:%S'规定了日期和时间部分的格式。

%Y:四个数字表示的年份 2019

%y:两个数字表示的年份 19

%m:返回月份 范围[0,12]

%d:返回的是当前时间是当前月的第几天

%H:以24小时制表示当前小时

%I:以12小时制表示当前小时

%M:返回分钟数 范围 [0,59]

%S:返回秒数 范围 [0,61]

datetime转换为str

  • time.strftime(format)

Return a string representing the time, controlled by an explicit format string.

from datetime import datetime
now = datetime.now()
sday = now.strftime('%Y-%m-%d %H:%M:%S')
print(sday)

# 2019-12-15 17:04:04

datetime加减

对日期和时间进行加减实际上就是把datetime往后或往前计算,得到新的datetime。加减可以直接用+-运算符,不过需要导入timedelta这个类:

from datetime import datetime, timedelta

now = datetime.now()
print(now)
print(now + timedelta(hours=10))
print(now - timedelta(days=1))
print(now + timedelta(days=2, hours=12))

# 2019-12-15 17:26:51.035849
# 2019-12-16 03:26:51.035849
# 2019-12-14 17:26:51.035849
# 2019-12-18 05:26:51.035849

可见,使用timedelta可以很容易地算出前几天和后几天的时刻。

2. calendar模块简介

  • calendar.monthrange(year,month)

返回两个整数。第一个是该月的星期几的日期码,第二个是该月的日期码。日从0(星期一)到6(星期日);月从1到12。

  • calendar.weekday(year,month,day)

返回给定日期的日期码。0(星期一)到6(星期日)。月份为 1(一月) 到 12(12月)。

print(calendar.weekday(year=2019, month=12, day=1))
# 6
print(calendar.monthrange(year=2019, month=12))
# (6, 31)

代码实现(Python)

1. 引入的模块

from datetime import datetime, timedelta
import calendar

2. 获取所有天,返回一个列表。

def getBetweenDay(begin_date, end_date):
    date_list = []
    begin_date = datetime.strptime(begin_date, "%Y%m%d")
    end_date = datetime.strptime(end_date, "%Y%m%d")
    while begin_date <= end_date:
        date_str = begin_date.strftime("%Y%m%d")
        date_list.append(date_str)
        begin_date += timedelta(days=1)
    return date_list

例子

date = getBetweenDay('20110201', '20110301')
print(date)

# ['20110201', '20110202', '20110203', '20110204', '20110205', '20110206', '20110207', '20110208', '20110209', '20110210', '20110211', '20110212', '20110213', '20110214', '20110215', '20110216', '20110217', '20110218', '20110219', '20110220', '20110221', '20110222', '20110223', '20110224', '20110225', '20110226', '20110227', '20110228', '20110301']

3. 获取所有月,返回一个列表。

def add_months(dt, months):
    # 返回dt隔months个月后的日期,months相当于步长
    month = dt.month - 1 + months
    year = dt.year + month // 12
    month = month % 12 + 1
    day = min(dt.day, calendar.monthrange(year, month)[1])
    return dt.replace(year=year, month=month, day=day)


def getBetweenMonth(begin_date, end_date):
    date_list = []
    begin_date = datetime.strptime(begin_date, "%Y%m%d")
    end_date = datetime.strptime(end_date, "%Y%m%d")
    while begin_date <= end_date:
        date_str = begin_date.strftime("%Y%m")
        date_list.append(date_str)
        begin_date = add_months(begin_date, 1)
    return date_list

例子

month = getBetweenMonth('20111201', '20130201')
print(month)

# ['201112', '201201', '201202', '201203', '201204', '201205', '201206', '201207', '201208', '201209', '201210', '201211', '201212', '201301', '201302']

4. 获取所有季度,返回一个字典。

def getBetweenQuarter(begin_date, end_date):
    # 加上每季度的起始日期、结束日期
    quarter_list = {}
    month_list = getBetweenMonth(begin_date, end_date)
    for value in month_list:
        year = value[:4]
        month = value[4:]
        if month in ['01', '02', '03']:
            quarter_list[year + "Q1"] = ['%s0101' % year, '%s0331' % year]
        elif month in ['04', '05', '06']:
            quarter_list[year + "Q2"] = ['%s0401' % year, '%s0630' % year]
        elif month in ['07', '08', '09']:
            quarter_list[year + "Q3"] = ['%s0731' % year, '%s0930' % year]
        elif month in ['10', '11', '12']:
            quarter_list[year + "Q4"] = ['%s1001' % year, '%s1231' % year]
    return quarter_list

例子

quarter = getBetweenQuarter('20111201', '20130201')
print(quarter)

# {'2012Q1': ['20120101', '20120331'], '2012Q3': ['20120731', '20120930'], '2012Q4': ['20121001', '20121231'], '2012Q2': ['20120401', '20120630'], '2011Q4': ['20111001', '20111231'], '2013Q1': ['20130101', '20130331']}

代码实现(C#)

1. 获取所有天,返回一个列表。

static List<string> GetBetweenDay(DateTime begin, DateTime end)
{
    List<string> result = new List<string>();
    while (begin <= end)
    {
        string year = begin.Year.ToString();
        string month = begin.Month.ToString().PadLeft(2, '0');
        string day = begin.Day.ToString().PadLeft(2, '0');
        result.Add(string.Concat(year,month,day));
        begin = begin.AddDays(1);
    }
    return result;
}

2. 获取所有月,返回一个列表。

static List<string> GetBetweenMonth(DateTime begin, DateTime end)
{
    List<string> result = new List<string>();
    begin = new DateTime(begin.Year, begin.Month, 1);
    while (begin <= end)
    {
        string year = begin.Year.ToString();
        string month = begin.Month.ToString().PadLeft(2, '0');
        result.Add(string.Concat(year, month));
        begin = begin.AddMonths(1);
    }
    return result;
}

3. 获取所有季度,返回一个字典。

static Dictionary<string, string> getBetweenQuarter(DateTime begin, DateTime end)
{
    Dictionary<string, string> result = new Dictionary<string, string>();
    List<string> lst = GetBetweenMonth(begin, end);
    foreach (string str in lst)
    {
        string year = str.Substring(0, 4);
        string month = str.Substring(4, 2);
        switch (month)
        {
            case "01":
            case "02":
            case "03":
                if (result.Keys.Contains(year + "Q1") == false)
                {
                    result.Add(year + "Q1", year + "0101," + year + "0331");
                }
                break;
            case "04":
            case "05":
            case "06":
                if (result.Keys.Contains(year + "Q2") == false)
                {
                    result.Add(year + "Q2", year + "0401," + year + "0630");
                }
                break;
            case "07":
            case "08":
            case "09":
                if (result.Keys.Contains(year + "Q3") == false)
                {
                    result.Add(year + "Q3", year + "0701," + year + "1031");
                }
                break;
            case "10":
            case "11":
            case "12":
                if (result.Keys.Contains(year + "Q4") == false)
                {
                    result.Add(year + "Q4", year + "1101," + year + "1231");
                }
                break;
        }
    }
    return result;
}

总结

本篇图文介绍了如何利用 Python 和 C# 语言来构建一个区间段日期的方法,为后面爬取气象数据做准备。大家如果感兴趣可以试验一下啊。今天就这样吧!See You!


参考文献

  • https://blog.csdn.net/joson1234567890/article/details/80946974
  • https://www.liaoxuefeng.com/wiki/1016959663602400/1017648783851616
  • http://www.imooc.com/wiki/detail/id/1911

往期活动

LSGO软件技术团队会定期开展提升编程技能的刻意练习活动,希望大家能够参与进来一起刻意练习,一起学习进步!