用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的Tornado框架实现一个一对一聊天的程序
Apr 25 Python
Python3.2模拟实现webqq登录
Feb 15 Python
Python使用poplib模块和smtplib模块收发电子邮件的教程
Jul 02 Python
linux环境下的python安装过程图解(含setuptools)
Nov 22 Python
Python实现从log日志中提取ip的方法【正则提取】
Mar 31 Python
对python .txt文件读取及数据处理方法总结
Apr 23 Python
mac下给python3安装requests库和scrapy库的实例
Jun 13 Python
python设置值及NaN值处理方法
Jul 03 Python
python pexpect ssh 远程登录服务器的方法
Feb 14 Python
浅谈Python爬虫基本套路
Mar 25 Python
Python xlrd模块导入过程及常用操作
Jun 10 Python
python如何控制进程或者线程的个数
Oct 16 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
用Zend Encode编写开发PHP程序
2010/02/21 PHP
PHP判断远程图片是否存在的几种方法
2014/05/04 PHP
php中的字符编码转换函数用法示例
2014/10/20 PHP
php实现mysql事务处理的方法
2014/12/25 PHP
linux中cd命令使用详解
2015/01/08 PHP
PHP两个n位的二进制整数相加问题的解决
2018/08/26 PHP
用dtree实现树形菜单 dtree使用说明
2011/10/17 Javascript
jquery下div 的resize事件示例代码
2014/03/09 Javascript
Angular发布1.5正式版,专注于向Angular 2的过渡
2016/02/18 Javascript
js html css实现复选框全选与反选
2016/10/09 Javascript
vue-router 中router-view不能渲染的解决方法
2017/05/23 Javascript
vue-cli初始化项目中使用less的方法
2018/08/09 Javascript
在antd4.0中Form使用initialValue操作
2020/11/02 Javascript
Django学习笔记之Class-Based-View
2017/02/15 Python
Python进阶-函数默认参数(详解)
2017/05/18 Python
Python设计模式之MVC模式简单示例
2018/01/10 Python
python+pillow绘制矩阵盖尔圆简单实例
2018/01/16 Python
django框架自定义用户表操作示例
2018/08/07 Python
python实现共轭梯度法
2019/07/03 Python
PyQt5使用QTimer实现电子时钟
2019/07/29 Python
python实现证件照换底功能
2019/08/20 Python
python使用pip安装模块出现ReadTimeoutError: HTTPSConnectionPool的解决方法
2019/10/04 Python
python读取Kafka实例
2019/12/23 Python
Python concurrent.futures模块使用实例
2019/12/24 Python
Django 项目布局方法(值得推荐)
2020/03/22 Python
python实现密度聚类(模板代码+sklearn代码)
2020/04/27 Python
python爬虫---requests库的用法详解
2020/09/28 Python
美国户外生活方式品牌:Eddie Bauer
2016/12/28 全球购物
全球知名的婚恋交友网站:Match.com
2017/01/05 全球购物
童装店创业计划书
2014/01/09 职场文书
党员干部廉洁承诺书
2014/05/28 职场文书
十佳好少年事迹材料
2014/08/21 职场文书
2014年销售员工作总结
2014/12/01 职场文书
个人事迹材料怎么写
2014/12/30 职场文书
红旗渠导游词
2015/02/09 职场文书
Python Matplotlib绘制动画的代码详解
2022/05/30 Python