用python自动生成日历


Posted in Python onApril 24, 2021

效果

用python自动生成日历

在Excel日历模板的基础上,生成带有农历日期、节假日、休班等信息的日历,解决DIY日历最大的技术难题。

图中日期,第一行为公历,第二行为节假日,第三行为农历,第四行是其他特别的日子,比如生日、纪念日等。

特点

  • 使用门槛低

Python + Excel,会运行Python脚本,会使用Excel即可上手。

  • 步骤简单

只需要修改Excel的年份(在一月份表头修改),运行一次脚本

  • 可扩展

可制作任意年份的日历(修改年份即可)

  • 可定制

可以添加其他特殊日期

使用手册

第一步,修改日历年份及样式

打开calendar.xlsx文件,在一月份表头,”输入年份“位置,修改样式

第二步,添加自定义日期

calendar.xlsx文件的生日栏,添加需要标注的日期,并保存

第三部,运行脚本

主要代码

BdDataFetcher.py

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import datetime
import logging
import time

import requests
import re
import json

class BdDataFetcher(object):
    def __init__(self):
        self.url = 'https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php'
        self.request_session = requests.session()
        self.request_session.headers = {
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36",
            "Accept": "application/json, text/plain, */*",
            "Accept-Encoding": "gzip, deflate",
            "Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8",
            "Connection": "keep-alive"
        }

    def request(self, year_month):
        payload = {
            'query': year_month,
            'resource_id': 39043,
            't': int(round(time.time() * 1000)),
            'ie': 'utf8',
            'oe': 'utf8',
            'cb': 'op_aladdin_callback',
            'format': 'json',
            'tn': 'wisetpl',
            'cb': 'jQuery110206747607329442493_1606743811595',
            '_': 1606743811613
        }
        resp = self.request_session.get(url=self.url, params=payload)
        logging.debug('data fetcher resp = {}'.format(resp.text))
        bracket_pattern = re.compile(r'[(](.*?)[)]', re.S)
        valid_data = re.findall(bracket_pattern, resp.text)
        json_data = json.loads(valid_data[0])
        almanac = json_data['data'][0]['almanac']
        result = {}
        for day in almanac:
            key = '{}-{}-{}'.format(day['year'], day['month'],day['day'])
            result[key] = day
        return result
if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG,
                        format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S')
    BdDataFetcher().request('2021年1月')

ExcelDateFiller.py

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import logging
import os
import sys
from copy import copy

import openpyxl
import pandas as pandas
import xlrd
import xlutils
import yaml
from pandas._libs.tslibs.timestamps import Timestamp

from BdDataFetcher import BdDataFetcher


class Config(object):
    def __init__(self, config_path):
        try:
            with open(config_path, "r", encoding="utf-8") as yaml_file:
                data = yaml.load(yaml_file)
                self.excel_path = data['excel_path']
                self.sheet_special = data['sheet_special']
                self.skip_row = data['date_skip_row']
                self.skip_col = data['date_skip_col']
                self.max_length = data['max_length']
                self.holiday_color = data['holiday_color']
                self.workday_color = data['workday_color']
                logging.basicConfig(level=logging.DEBUG,
                            format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                            datefmt='%a, %d %b %Y %H:%M:%S')

        except Exception as e:
            logging.error(repr(e))
            sys.exit()

class SpecialDay(object):
    def __init__(self):
        self.is_lunar = False
        self.desc = ''

class ExcelDateFiller(object):
    def __init__(self):
        self.data_fetcher = BdDataFetcher()
        self.target = os.path.splitext(config.excel_path)[0] + '_out' + os.path.splitext(config.excel_path)[-1]
        # try:
        #     shutil.copy(config.excel_path, self.target)
        # except IOError as e:
        #     print("Unable to copy file. %s" % e)
        # except:
        #     print("Unexpected error:", sys.exc_info())
        # self.target_workbook = openpyxl.load_workbook(self.target, data_only=True)

    def fill_date_with_openpyxl(self):
        for sheet in self.target_workbook.worksheets:
            for column_index in range(1, sheet.max_column):
                for row_index in range(1, sheet.max_row):
                    data = sheet.cell(column=column_index, row=row_index)
                    print(data.value)

    def read_with_xlrd(self):
        workbook = xlrd.open_workbook(self.target)
        for sheet in workbook.sheets():
            for column_index in range(0, sheet.ncols):
                for row_index in range(0, sheet.nrows):
                    data = sheet.cell(rowx=row_index, colx=column_index)
                    logging.debug('ctype = {}, value = {}, xf_index = {}'.format(data.ctype, data.value, data.xf_index))

    def write_with_openpyxl(self):
        target_workbook = openpyxl.load_workbook(self.target)
        sheet = target_workbook.get_sheet_by_name('sheet_name')
        sheet.cell(0, 0).value = 'value'
        target_workbook.save()

    def write_with_xlwt(self):
        workbook = xlrd.open_workbook(self.target)
        workbook = xlutils.copy(workbook)
        sheet = workbook.get_sheet(0)
        sheet.write(0, 0, 'value')
        workbook.save()

    def load_special_sheet(self):
        data = {}
        special_sheet = pandas.read_excel(config.excel_path, sheet_name=config.sheet_special, header=0)
        for row_index in range(special_sheet.shape[0]):
            key = special_sheet.iloc[row_index, 0]
            struct_time = pandas.to_datetime(key.timestamp(), unit='s').timetuple()
            key = '{}-{}'.format(struct_time.tm_mon, struct_time.tm_mday)
            value = SpecialDay()
            value.desc = special_sheet.iloc[row_index, 1]
            value.is_lunar = special_sheet.iloc[row_index, 2] == '是'
            data[key] = value
        return data


    def fill_date(self):
        pandas_workbook = pandas.read_excel(config.excel_path, sheet_name=None, skiprows= config.skip_row, keep_default_na=False)
        out_workbook = openpyxl.load_workbook(config.excel_path)

        special_day = self.load_special_sheet()

        day_data = {}
        for sheet_name in pandas_workbook.keys():
            if not sheet_name.endswith('月'):
                continue
            sheet = pandas_workbook.get(sheet_name)
            out_sheet = out_workbook.get_sheet_by_name(sheet_name)

            nrows = sheet.shape[0]
            ncols = sheet.shape[1]
            for row_index in range(nrows):
                for col_index in range(ncols):
                    data = sheet.iloc[row_index, col_index]
                    logging.debug('origin row = {}, col = {}, data = {}'.format(row_index, col_index, data))
                    if type(data) == Timestamp:
                        struct_time = pandas.to_datetime(data.timestamp(), unit='s').timetuple()
                        date = '{}-{}-{}'.format(struct_time.tm_year, struct_time.tm_mon, struct_time.tm_mday)
                        if not day_data.__contains__(date):
                            request_data = self.data_fetcher.request(year_month='{}年{}月'.format(struct_time.tm_year, struct_time.tm_mon))
                            day_data.update(request_data)

                        temp_row = row_index + 2 + config.skip_row
                        temp_col = col_index + 1
                         # weekend color
                        if day_data[date]['cnDay'] == '六' or day_data[date]['cnDay'] == '日':
                            holiday_font = copy(out_sheet.cell(temp_row, temp_col).font)
                            holiday_font.color = config.holiday_color
                            out_sheet.cell(temp_row, temp_col).font = holiday_font
                        # holiday color
                        if day_data[date].__contains__('status'):
                            if day_data[date]['status'] == '1': # 休假
                                holiday_font = copy(out_sheet.cell(temp_row, temp_col).font)
                                holiday_font.color = config.holiday_color
                                out_sheet.cell(temp_row, temp_col).font = holiday_font
                            if day_data[date]['status'] == '2': #班
                                workday_font = copy(out_sheet.cell(temp_row, temp_col).font)
                                workday_font.color = config.workday_color
                                out_sheet.cell(temp_row, temp_col).font = workday_font
                        lunar_date = day_data[date]['lDate']
                        if lunar_date == '初一':
                            lunar_date = '{}月'.format(day_data[date]['lMonth'])
                        # logging.debug('date = {}, value = {}'.format(str(date), lunar_date))
                        temp_content = ''
                        if day_data[date].__contains__('value'):
                            temp_content += day_data[date]['value']
                            if len(temp_content) > config.max_length:
                                temp_content = temp_content[:config.max_length]
                        temp_content += '\n'
                        temp_content += lunar_date
                        # spacial day
                        month_day = day_data[date]['month'] + '-' + day_data[date]['day']
                        if special_day.__contains__(month_day):
                            temp_special_day = special_day.get(month_day)
                            if not temp_special_day.is_lunar:
                                temp_content += '\n'
                                temp_content += temp_special_day.desc

                        lunar_month_day = day_data[date]['lunarMonth'] + '-' + day_data[date]['lunarDate']
                        if special_day.__contains__(lunar_month_day):
                            temp_special_day = special_day.get(lunar_month_day)
                            if temp_special_day.is_lunar:
                                temp_content += '\n'
                                temp_content += temp_special_day.desc

                        temp_row = row_index + 3 + config.skip_row
                        temp_col = col_index + 1
                        out_sheet.cell(temp_row, temp_col).value = temp_content


        out_workbook.save(filename=self.target)
        out_workbook.close()

if __name__ == '__main__':
    config = Config(config_path='config.yaml')
    date_filler = ExcelDateFiller()
    date_filler.fill_date()

完整项目地址

https://github.com/yongjiliu/diycalendar

calendar_out.xlsx为处理好的日历

以上就是用python自动生成日历的详细内容,更多关于python 生成日历的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python模拟鼠标拖动操作的方法
Mar 11 Python
Python实现KNN邻近算法
Jan 28 Python
遗传算法python版
Mar 19 Python
详解python读取image
Apr 03 Python
pytz格式化北京时间多出6分钟问题的解决方法
Jun 21 Python
详解centos7+django+python3+mysql+阿里云部署项目全流程
Nov 15 Python
python简单的三元一次方程求解实例
Apr 02 Python
如何更换python默认编辑器的背景色
Aug 10 Python
python爬虫多次请求超时的几种重试方法(6种)
Dec 01 Python
Pytorch之扩充tensor的操作
Mar 04 Python
python之django路由和视图案例教程
Jul 26 Python
Python数据结构之队列详解
Mar 21 Python
解决Django transaction进行事务管理踩过的坑
Apr 24 #Python
pdf论文中python画的图Type 3 fonts字体不兼容的解决方案
Apr 24 #Python
Python使用UDP实现720p视频传输的操作
python通配符之glob模块的使用详解
Apr 24 #Python
Django debug为True时,css加载失败的解决方案
Apr 24 #Python
python 模块重载的五种方法
Apr 24 #Python
写一个Python脚本自动爬取Bilibili小视频
You might like
IP138 IP地址查询小偷实现代码
2010/02/15 PHP
php图片处理:加水印、缩略图的实现(自定义函数:watermark、thumbnail)
2010/12/02 PHP
php设计模式 Strategy(策略模式)
2011/06/26 PHP
Linux下编译redis和phpredis的方法
2016/04/07 PHP
php简单压缩css样式示例
2016/09/22 PHP
firefox下对ajax的onreadystatechange的支持情况分析
2009/12/14 Javascript
js获取时间并实现字符串和时间戳之间的转换
2015/01/05 Javascript
jQuery中nextAll()方法用法实例
2015/01/07 Javascript
JavaScript实现的SHA-1加密算法完整实例
2016/02/02 Javascript
利用BootStrap的Carousel.js实现轮播图动画效果
2016/12/21 Javascript
jQuery EasyUi 验证功能实例解析
2017/01/06 Javascript
js实现3D图片环展示效果
2017/03/09 Javascript
vue双向绑定简要分析
2017/03/23 Javascript
JS Testing Properties 判断属性是否在对象里的方法
2017/10/01 Javascript
vue 引入公共css文件的简单方法(推荐)
2018/01/20 Javascript
JavaScript实现浅拷贝与深拷贝的方法分析
2018/07/05 Javascript
JavaScript实现缓动动画
2020/11/25 Javascript
微信小程序轮播图swiper代码详解
2020/12/01 Javascript
[00:36]DOTA2上海特级锦标赛 Alliance战队宣传片
2016/03/04 DOTA
python paramiko实现ssh远程访问的方法
2013/12/03 Python
python使用新浪微博api上传图片到微博示例
2014/01/10 Python
python列表去重的二种方法
2014/02/14 Python
windows下python模拟鼠标点击和键盘输示例
2014/02/28 Python
mysql 之通过配置文件链接数据库
2017/08/12 Python
nginx+uwsgi+django环境搭建的方法步骤
2019/11/25 Python
Python抓新型冠状病毒肺炎疫情数据并绘制全国疫情分布的代码实例
2020/02/05 Python
浅谈在django中使用filter()(即对QuerySet操作)时踩的坑
2020/03/31 Python
说一下Linux下有关用户和组管理的命令
2016/01/04 面试题
我们在web应用开发过程中经常遇到输出某种编码的字符,如iso8859-1等,如何输出一个某种编码的字符串?
2014/03/30 面试题
法务专员岗位职责
2014/01/02 职场文书
幼儿园新学期寄语
2014/01/18 职场文书
承诺书怎么写
2014/03/26 职场文书
股份合作协议书范本
2014/04/14 职场文书
经济管理专业求职信
2014/06/09 职场文书
宿舍标语大全
2014/06/19 职场文书
机关单位保密工作责任书
2015/05/11 职场文书