Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

提供一个折中方案,使用网络api获取日历,适用各种语言的低并发场景 #116

Open
mouday opened this issue Apr 3, 2024 · 1 comment

Comments

@mouday
Copy link

mouday commented Apr 3, 2024

原文地址:https://blog.csdn.net/mouday/article/details/137352491

@TOC

现有方案:chinesecalendar

使用chinesecalendar库可以实现:判断一天是不是法定节假日/法定工作日(查看节假日安排)

安装

pip install chinesecalendar

使用示例

import datetime

# 判断 2018年4月30号 是不是节假日
from chinese_calendar import is_holiday, is_workday

april_last = datetime.date(2018, 4, 30)
assert is_workday(april_last) is False

缺点:

  • 1、更新不及时,或需要手动更新才能判断,由于次年的节假日安排,取决于国务院发布的日程。 所以本项目一般会在国务院更新以后,发布新的版本。 按照以往的经验,一般是每年的 11月 前后发布新版本。
  • 2、支持的版本有点高,Python :: 3.8起步,不支持低版本

基于网络的方案

可以使用现有的维护的比较好的网站数据,比如:https://wannianrili.bmcx.com/,通过网页请求解析获取日历数据,这样就能获取到实时的数据,缺点也很明显,需要网络请求,如果考虑性能的场景下,可能不适用。

依赖两个第三方库:

pip install requests parsel

代码文件,可以放到项目的utils工具包内

# -*- coding: utf-8 -*-
"""
@File    : calendar_util.py
@Date    : 2024-04-03
"""
import json
import re

import requests
from parsel import Selector


def get_calendar(year_and_month):
    """
    数据来源:https://wannianrili.bmcx.com/

    @return:

    {
      "2024-04-01": {
        "class_name": "",
        "comment": "愚人节"
        }
    }
    """

    # https://wannianrili.bmcx.com/ajax/?q=2024-04&v=22121303
    url = 'https://wannianrili.bmcx.com/ajax/'

    params = {
        'q': year_and_month,
        'v': '22121303'
    }

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:64.0) Gecko/20100101 Firefox/64.0"
    }

    res = requests.get(url, params=params, headers=headers)
    
    sel = Selector(text=res.text)
    rows = sel.css('.wnrl_riqi')

    data = {}
    for row in rows:
        class_name = row.css('a::attr(class)').extract_first('').strip()
        day = row.css('a::attr(onclick)').extract_first('').strip()
        comment = row.css('.wnrl_td_bzl::text').extract_first('').strip()

        ret = re.search('\d{4}-\d{2}-\d{2}', day)
        day = ret.group(0)

        data[day] = {
            'class_name': class_name,
            'comment': comment
        }

    return data


def get_day_item(day):
    """

    @param day:
    @return:
    {
        "class_name": "",
        "comment": "愚人节"
    }
    """
    # 2024-05-04 => 2024-05
    calendar = get_calendar('-'.join(day.split('-')[:2]))
    # print(json.dumps(calendar, indent=2, ensure_ascii=False))
    return calendar.get(day)


def is_workday(day):
    # 工作日
    workday_class_list = ['', 'wnrl_riqi_ban']

    day_item = get_day_item(day)

    if day_item:
        if day_item.get('class_name') in workday_class_list:
            return True
        else:
            return False


def is_holiday(day):
    # 节假日
    holiday_class_list = ['wnrl_riqi_xiu', 'wnrl_riqi_mo']
    day_item = get_day_item(day)

    if day_item:
        if day_item.get('class_name') in holiday_class_list:
            return True
        else:
            return False


if __name__ == '__main__':
    print(is_holiday('2024-05-04')) # True
@mouday
Copy link
Author

mouday commented Apr 3, 2024

我把上面的代码,简单的封装了一个库,分享给大家

安装

pip install china-calendar

使用示例:

import china_calendar

# 清明节
assert china_calendar.is_holiday('2024-04-04') == True

assert china_calendar.is_workday('2024-04-04') == False

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant