标签归档:Python工具

Python 计算多少天前后、距离X日多久的日期

接下来,我就教大家怎么用十行代码计算我们剩余的假期天数!我们的代码用到了一个概念叫时间戳:

时间戳就是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数

因此,2019年8月1日的时间戳,就是从1970年01月01日08时00分00秒到2019年8月1日00时00分的秒数,我们可以先用工具计算一下这个秒数:

今天我们就基于时间戳,计算一下我们剩余的假期天数吧!

# 文件名:count_days.py
import time
import datetime

def get_between_days(start_date, end_date):
    # 获得两个日期之间的天数
    start_sec = time.mktime(time.strptime(start_date,'%Y-%m-%d'))
    end_sec = time.mktime(time.strptime(end_date,'%Y-%m-%d'))
    work_days = int((end_sec - start_sec)/(24*60*60))
    work_hours = int((end_sec - start_sec)/(60*60))
    work_minutes = int((end_sec - start_sec)/(60))
    return work_days, work_hours, work_minutes
# 获得当天时间 yyyy-mm-dd
start_date = time.strftime('%Y-%m-%d',time.localtime(time.time()))
end_date = '2019-09-01'
print (get_between_days(start_date, end_date))

首先,我们需要把类似2019-09-01这样的yyyy-mm-dd格式的时间转化为时间戳,这样做就可以了:

time.mktime(time.strptime(start_date,'%Y-%m-%d'))

strptime是将yyyy-mm-dd这样的字符串转化为time类型的变量,然后time.mktime()函数可以将time类型的变量转化为时间戳。

将两个日期的时间戳相减,就能得到这两个时间之间的秒数,然后将其除以24小时*60分钟*60秒就能得到这两个时间间隔的天数

work_days = int((end_sec - start_sec)/(24*60*60))

除以60分钟*60秒就能得到这两个时间间隔的小时数

work_hours = int((end_sec - start_sec)/(60*60))

除以60秒就能得到这两个时间间隔的分钟数

work_minutes = int((end_sec - start_sec)/(60))

让我们尝试一下,进入cmd(windows)/Terminal(macOS),cd到当前文件夹下,运行命令:

python count_days.py

运行结果

可以看到,从2019年8月12日到2019年9月1日,还剩余20天,正好和我们数手指头算出来的时间是一样的呢

但是!!天呐,我们的大家的暑假只剩下20天,换算成小时,就是480个小时!!作业做了吗?

你可以将start_date修改成你想要的任意时间进行计算哦,并不一定是今天。只要格式符合yyyy-mm-dd即可。

怎么样,方便吧?嘻嘻,接下来还有更方便的玩法,我们可以计算任意天的x天、y小时、t分钟、z秒后的时间:

# 文件名:count_days.py
import time
import datetime
def time_controller(d=0, hour=0, minute=0, second=0, arg=1, day=datetime.datetime.now()):
    # 获得某天的x天、y小时、t分钟、z秒后的日期, day为空默认为当前时间开始
    # 所有参数默认都为0,只需要调你需要的时间即可
    # arg = 1: 获得hour小时,minute分钟,second秒后的具体时间
    # arg = -1: 获得hour小时,minute分钟,second秒前的具体时间
    now = datetime.datetime.now()
    if type(day) == str:
        now = datetime.datetime.strptime(day, '%Y-%m-%d %H:%M:%S')
    if arg == 1:
        value = now + datetime.timedelta(days=d, hours=hour, minutes=minute, seconds=second)
    elif arg == -1:
        value = now - datetime.timedelta(days=d, hours=hour, minutes=minute, seconds=second)
    return value
print(time_controller(d=10, hour=20, minute=10, second=0, arg=-1, day='2019-08-01 10:00:00'))
print(time_controller(d=10, hour=20, minute=10, second=0, arg=-1))

代码里,argv=-1表示取day参数之前的时间,也就是2019-08-01 10:00:00之前10天、20小时、10分钟的时间。同样地,进入cmd(windows)/Terminal(macOS),cd到当前文件夹下,运行命令:

python count_days.py

运行结果

得到2019-08-01 10:00:00的10天、20小时、10分钟之前的时间为 2019-07-21 13:50:00. 如果day参数为空,默认为当前时间开始,那么这个结果则是:2019-08-01 23:35:23.

由于datetime是精确到毫秒的,所以后面有小数点,大家可以自行去掉

今天小技巧不仅简单,而且在实际生活中也非常方便实用。用上面的方法可做未来的计划安排,考试倒计时准备,也可以算算离上次某个时间点(节假日)过去了多久,我们一起认识了多长时间,在一起了多少天,想想就激动呢!

当然还有更多有趣的用法待大家去挖掘哦

我们的文章到此结束啦!如果你喜欢我们的文章,持续关注Python实用宝典哦!请记住我们的官方网站:https://pythondict.com 公众号:python实用宝典

Excel+Python=精美壁纸日历 任意DIY

广东的太阳还是那么大,隔着玻璃都能感受到热浪。

明明前不久才立夏(明明已经过去三个月!!)

时间跑,日程赶。

昨日又迎来了立秋,正在放暑假的童靴是不是有点忘记时间了呢~

什么?真的忘记了?没关系,今日小编为大家带来一款由Excel简易DIY的小日历

给自己10分钟(滑稽),python回你一个智慧与美貌并存的备忘小神器 相信它会给你带来不少方便(滑稽)

一、环境说明

开始之前,当然要跟小伙伴们交代一下运行环境咯

我们使用的python版本为 Python3.6,需要使用到的包为 openpyxlcalendar,后者是python自带的,而前者则需要小伙伴们打开Cmd/Terminal,运行以下指令安装,如果你还没有安装python,请看这篇文章

pip install openpyxl

安装完成后我们就可以正式开始啦!

二、代码说明

我们会给大家先讲解一些细节的东西,等大家都理解明白了原理,最后会献上完整的源代码~

1. 首先,绘制一份日历,我们得先知道每个月份有多少天,每天都是星期几,我们使用calendar包获得这些信息:
calendar.monthcalendar(2019, i)

通过这个函数,我们能得到 2019年i月的日历,它类似一个j*k的矩阵,因此我们可以这样遍历得到每一个日期:

    for j in range(len(calendar.monthcalendar(2019, i))):
        for k in range(len(calendar.monthcalendar(2019, i)[j])):
            value = calendar.monthcalendar(2019, i)[j][k]
2. 其次,我们怎么样绘制得到日历呢?

openpyxl包给予了我们答案,最方便的做法是我们先将日历绘制到Excel中,然后再从Excel中提取图片出来。openpyxl怎么用?给大家一个设置单元格字体的例子:

sheet.cell(row=j + 4 + count, column=k + 2).font = Font(u'微软雅黑', color=text_color , size=14)

sheet是对应的表格,row和column就是某个单元格的位置,然后对font属性进行设置,调用Font类并设置参数,如果大家不知道Font类有什么参数,可以参考openpyxl官方文档:https://openpyxl.readthedocs.io/en/stable/,你可以看到里面大部分单元格的属性都是这样设置的,非常简单。

3. 我们的作品是每个月份都有一个图在旁边做装饰,其添加方法如下:
imgs = ['12/1.jpg','12/2.jpg','12/3.jpg','12/4.jpg','12/5.jpg','12/6.jpg','12/7.jpg','12/8.jpg','12/9.jpg','12/10.jpg','12/11.jpg','12/12.jpg']

img = Image(imgs[i-1])        
sheet.add_image(img, 'J2')

imgs是每个图的相对路径,如12/1.jpg 是名字为12的文件夹下的1.jpg. 图像路径要导入到openpyxl的Image对象中: img=Image(’12/1.jpg’),然后将该变量放置到某个单元格上:sheet.add_image(img, ‘J2).

这样看你可能会有点糊涂, i-1是哪里来的?sheet是哪里来的?没关系,其实是因为讲解的时候只能给大家献上部分代码,看完下面的完整代码你们就懂啦:

from openpyxl.styles import Alignment, PatternFill, Font, Border, Side
from openpyxl.utils import get_column_letter
from openpyxl.drawing.image import Image
import openpyxl
import calendar

def set_information(date, text):
    t = {}
    t['month'] = date.split('-')[1]
    t['day'] = date.split('-')[2]
    t['text'] = text
    flex_text.append(t)

def set_month_value(i, sheet, border_color, text_color, color_one, color_two):
    # i: 月份
    # sheet: 该月份的excel
    # border_color: 边框颜色
    count = 0
    # render_color 用来设定单元格背景色,交替进行
    render_color_1 = 1
    render_color_2 = 0

    for j in range(len(calendar.monthcalendar(2019, i))):
        for k in range(len(calendar.monthcalendar(2019, i)[j])):
            value = calendar.monthcalendar(2019, i)[j][k]
            # 将0值变为空值
            bd = Border(right=Side(color=border_color, style='thick'),
                        top=Side(color=border_color, style='thick'),
                        left=Side(color=border_color, style='thick'))
            right_bd = Border(right=Side(color=border_color, style='thick'),
                              left=Side(color=border_color, style='thick'),
                              bottom=Side(color=border_color, style='thick'))
            
            if value == 0:
                value = ''
                sheet.cell(row=j + 4 + count, column=k + 2).value = value
                sheet.cell(row=j + 4 + count, column=k + 2).border = bd
                sheet.cell(row=j + 5 + count, column=k + 2).border = right_bd
            else:
                sheet.cell(row=j + 4 + count, column=k + 2).value = value
                sheet.cell(row=j + 4 + count, column=k + 2).border = bd
                sheet.cell(row=j + 4 + count, column=k + 2).font = Font(u'微软雅黑', color=text_color , size=14)
                sheet.cell(row=j + 5 + count, column=k + 2).border = right_bd
                # 单元格文字设置,右对齐,垂直居中

            if render_color_1 > render_color_2:
                sheet.cell(row=j + 4 + count, column=k + 2).fill = PatternFill("solid", fgColor=color_one)
                sheet.cell(row=j + 5 + count, column=k + 2).fill = PatternFill("solid", fgColor=color_one)
                render_color_2 += 1
            else:
                sheet.cell(row=j + 4 + count, column=k + 2).fill = PatternFill("solid", fgColor=color_two)
                sheet.cell(row=j + 5 + count, column=k + 2).fill = PatternFill("solid", fgColor=color_two)
                render_color_1 += 1

            # 提取当天所有事件
            text = ''
            for t in flex_text:
                if int(t['day']) == value and int(t['month']) == i:
                    print(t)
                    text = text + t['text']+'\n'

            # 设置事件信息
            if text != '':
                sheet.cell(row=j + 5 + count, column=k + 2).value = text
                sheet.cell(row=j + 5 + count, column=k + 2).font = Font(u'宋体',color=text_color, size=13)
                align = Alignment(horizontal='right', vertical='center', wrapText=True)
                # wrapText 设置单元格可包含多行字符
                sheet.cell(row=j + 5 + count, column=k + 2).alignment = align
        count += 1

def set_week_line(sheet, border_color, workday_color, otherday_color, text_color):
    # 设置星期栏
    align = Alignment(horizontal='center', vertical='center')
    days = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
    bd_day = Border(right=Side(color=border_color, style='thick'), 
                      top=Side(color=border_color, style='thick'),
                      left=Side(color=border_color, style='thick'))
    num = 0
    # 单元格填充色属性设置
    for day in range(2, 9):
        sheet.cell(row=3, column=day).value = days[num]
        sheet.cell(row=3, column=day).alignment = align
        sheet.cell(row=3, column=day).border = bd_day
        sheet.cell(row=3, column=day).font = Font(u'微软雅黑', color=text_color, bold=True , size=12)
        # 设置列宽12
        c_char = get_column_letter(day)
        sheet.column_dimensions[get_column_letter(day)].width = 12
        # 行高27
        sheet.row_dimensions[day].height = 27
        num += 1
        if day == 2 or day == 8:
            for r in range(3, 14):
                sheet.cell(row=r, column=day).fill = PatternFill("solid", fgColor=otherday_color)
        else:
            sheet.cell(row=3, column=day).fill = PatternFill("solid", fgColor=workday_color)

def set_month_year(i, sheet, year_color, month_color):
    # 添加年份及月份
    sheet.cell(row=2, column=8).value = '2019'
    sheet.cell(row=2, column=8).font = Font(u'微软雅黑', size=30, color=year_color)
    sheet.cell(row=2, column=2).value = str(i) + '月'
    sheet.cell(row=2, column=2).font = Font(u'微软雅黑', size=25, color=month_color)
    sheet.row_dimensions[2].height = 35

def get_month_xlsx(wb, imgs, flex_text):
    for i in range(1, 13):
        sheet = wb.create_sheet(index=0, title=str(i) + '月')
        # 添加工作表

        text_color = '000000'
        # 日历文字颜色
        text_color_week = '000000'
        # 星期栏文字颜色
        BorderCorlor = 'B7E0E8'
        # 边框颜色
        backgroundColor = 'FFFFFF'
        # 背景颜色
        workday_color = 'CBEEEE'
        # 工作日背景颜色
        otherday_color = '7FD4D2'
        # 其他日背景颜色
        year_color = '000000'
        # 年份颜色
        month_color = '000000'
        # 月份颜色
        s_color = 'CBEEEE'
        # 单数颜色
        d_color = 'A5E1E0'
        # 双数颜色
        
        # 单元格的背景色
        for k1 in range(1, 15):
            for k2 in range(1, 16):
                sheet.cell(row=k1, column=k2).fill = PatternFill("solid", fgColor=backgroundColor)

        set_month_value(i, sheet, BorderCorlor, text_color, s_color, d_color)
        # 设定月份的值,参数:月份, 表, 边框颜色

        set_week_line(sheet, BorderCorlor, workday_color, otherday_color, text_color_week)
        # 设定星期栏

        set_month_year(i, sheet, year_color, month_color)
        # 设定年份和月份的格式

        # 设置日历主体行高
        for row in range(3, 19):
            if row % 2 == 0 or row == 3:
                sheet.row_dimensions[row].height = 28
            else:
                sheet.row_dimensions[row].height = 56

        # 合并单元格
        sheet.merge_cells('I1:P14')

        # 添加图片
        img = Image(imgs[i-1])
        sheet.add_image(img, 'J2')

        # 添加二维码
        img = Image('2.png')
        sheet.add_image(img, 'O2')

calendar.setfirstweekday(firstweekday=6)
wb = openpyxl.Workbook()
flex_text = []

imgs = ['12/1.jpg','12/2.jpg','12/3.jpg','12/4.jpg','12/5.jpg','12/6.jpg','12/7.jpg','12/8.jpg','12/9.jpg','12/10.jpg','12/11.jpg','12/12.jpg']
# 每个月的图片

set_information('2019-12-1', '考试')
set_information('2019-12-1', '约会')
# 需要添加的信息

get_month_xlsx(wb, imgs, flex_text)
# 得到文档

wb.save('my_calendary.xlsx')
# 保存文档
4. 我们还有一个神秘功能

差点忘了告诉大家了,我们的日历能支持备注哦,在调用get_month_xlsx得到文档前,通过set_information()放入你某一天想做的事情即可。如:

set_information('2019-12-5', '面试')

三、运行代码

终于到了激动人心的运行代码部分了,运行这份代码,你只需要把你想要的图片变量名改一下即可,即imgs. 然后在本地cmd/terminal运行:

python 这份代码的文件名(滑稽.py

会自动生成一个Excel表格叫my_calendary.xlsx. 怎样从里面把日历提取成图片呢?很简单,复制拉取你想要的部分,粘贴到聊天窗口就能变成一个图片!这里给大家献上源代码里的12张图,希望大家喜欢!

下载地址:https://pythondict-1252734158.file.myqcloud.com/home/www/pythondict/wp-content/uploads/2019/08/2019080909262065.zip


根据大家的喜好,大家可以自己设置背景色、边框色、交替色和图片,还有把这个讨厌的好看的二维码去掉。如果有阅读完注释还是不懂的地方,欢迎在下方留言区讨论,我们会抽空回答的~


Python实用宝典 (pythondict.com)

不只是一个宝典

欢迎关注公众号:Python实用宝典

python 树莓派语音控制普通台灯教程

阅读这篇文章前,这两篇文章可能对你会有所帮助:

利用智能音箱语音控制电脑开关机 (必读,否则你可能不知道我在说什么)

语音控制 – 改造普通风扇 (选读)

先看看效果:

完成这项有趣的实验,你所需要的材料有:

1.电烙铁

2.一个8050三极管

3.一个继电器

4.一个路由器

5.一个树莓派

6.一个智能音箱 (我使用的是亚马逊 Echo Dot2)

7.一个普通台灯

我使用的是最基本的开关台灯,所以它只有一个开关按钮,也只有一个功能,那就是开关台灯(废话),现在我们需要让它能够被语音控制。由于我们可以让智能音箱树莓派通信,所以只需要让台灯连接树莓派就能达成我们的目的,因此我们需要有一个能和这个台灯并联,并且能够接线出来让树莓派控制的器件。那就是继电器。

PS:为什么不能让树莓派像控制风扇一样,直接控制台灯呢?

因为台灯接的是220V电压,树莓派最大电压只有5V,树莓派是较小电流,较小电流要控制大电流则必须用继电器。

加上继电器后,其电路图就如同下面所示。

我们使用的继电器是这个小东西:

但由于我的台灯里的空间不够大(如下图所示,我还打了个孔,方便接出线),我只好拆出这个继电器的核心,当然如果你的台灯够大,就不需要考虑这一点了。

接下来讲一下继电器的使用(原理可见上方动图),其实是很简单的,把点灯开关的两条线接到COM端(共接点)和NO端(常开端),此外DC+, DC-分别连树莓派的5V电源和接地即可。然后从树莓派任意GPIO引脚中引线接继电器的控制端,这个控制端能控制NO端的开闭,当输入1的时候就是闭合,电路连通,灯亮。

不过需要注意的是,树莓派的GPIO口是3.3V的,你需要把它转化成5V才能进行控制,怎么转化呢?那就要使用上我们上一节 语音控制 – 改造普通风扇 讲的三极管了。

接完后如下图所示

这样,硬件方面的工作我们就做完了,接下来是软件方面的工作。

其实也就是让智能音箱识别到一个控制开关的命令,跟 利用智能音箱语音控制电脑开关机 中提到的一样。让树莓派使用fauxmo,模拟成许多智能设备,模拟的配置如下:

"MyLight": {
    "path": "/home/pi/Documents/fauxmo/src/fauxmo/plugins/MyLight.py",
    "DEVICES": [
        {
        "name": "Light",
        "port": 49919,
        "on_cmd": "python2 /home/pi/Documents/Automatic/GPIO13.py on",
        "off_cmd": "python /home/pi/Documents/Automatic/GPIO13.py off",
        "state_cmd": ""
        }
    ]
}

这样,智能音箱就会把这个设备的名字识别为 Light. 因此,当你说

” turn on the light “,

它就会执行on_cmd命令,(在这个例子中,我们的path指向的文件MyLight.py即只是启动一个cmd命令而已)即执行 python GPIO13.py on . 相应地,”turn off the light”则执行off_cmd命令。

GPIO13.py 内只是控制树莓派的开关而已,如下所示,它接收两个参数,on或off. 当参数是on的时候,向树莓派的GPIO33口输出高电平,灯亮。Off的时候则输出低电平,灯灭。

# -*- coding: utf-8 -*-

import RPi.GPIO as GPIO
import time
import sys

# BOARD编号方式,基于插座引脚编号
GPIO.setmode(GPIO.BOARD)

# 输出模式
GPIO.setup(33, GPIO.OUT)

def turnOn():
    GPIO.output(33, GPIO.HIGH)

def turnOff():
    GPIO.output(33, GPIO.LOW)

if sys.argv[1] == 'on':
    turnOn()

elif sys.argv[1] == 'off':
    turnOff()

重启fauxmo,让智能音箱重新搜索,就能找到这个Light的设备,然后说一句 “turn on the light”,就能享受这份折腾的成就感了。

最近我还发现,Amazon Alexa 的手机软件,还支持外网控制这些室内设备,如图。

因此,现在每当我要回到宿舍的时候,在宿舍楼下时,我都会先点击Fan,让它帮我开个风扇,然后根据我是要玩游戏还是要干活,再点击PC或Laptop. 如果是晚上,我还可以点击Light打开点灯。这就是新时代的生活,你得Catch Up。

无论是多么普通的设备,你都可以用一个树莓派把它变得智能。

我们的文章到此就结束啦,如果你希望我们今天的Python 教程,请持续关注我们,如果对你有帮助,麻烦在下面点一个赞/在看哦有任何问题都可以在下方留言区留言,我们都会耐心解答的!


​Python实用宝典 (pythondict.com)
不只是一个宝典
欢迎关注公众号:Python实用宝典

使用python识别图片每一个像素的RGB颜色

休息了一个月,从今天开始继续更新文章!希望大家喜欢。最近在研究怎么破解验证码,其中就要利用到Python识别像素颜色的技术。你也可以用PS慢慢地进行取样记录,但那样效率非常低下,而且麻烦。识别验证码需要我们高效地提取出像素,并将其转换成黑白二色,这样才好进行矢量对比。

工具

pillow

如果你有PyCharm的话,可以在Preferences内的Project Interpreter中安装pillow.

若你没有PyCharm.请上网查阅安装流程,非常简单。

几个要用到的比较重要的函数(你可以先跳过,遇到不认识的函数再回来查看):

建议直接阅读PIL的英文文档:http://effbot.org/imagingbook/image.htm

image.new(mode,size,color)

使用给定的变量mode和size生成新的图像。mode是图片模式,如”RGB”、”P”。Size是给定的宽/高二元组,这是按照像素数来计算的。对于单通道图像,变量color只给定一个值;对于多通道图像,变量color给定一个元组(每个通道对应一个值)。

im.convert(mode)

将你打开的图片转化为某种格式。

im.getpixel(xy)

返回给定位置的像素。

im.putpixel(xy,color)

修改给定位置的像素。

im.size()

返回两个元素,宽和高。im.size ⇒ (width, height)

若是变量名.size[0]则便是是宽,size[1]则表示是高。

使用的图片:

from PIL import Image

im = Image.open("1.jpg")

for y in range(im.size[1]):
    for x in range(im.size[0]):
        pix = im.getpixel((x,y))
        print(pix)

运行结果很长,我们截取一部分:

不得不说Python实在很强大。不过这样看实在很麻烦,因为像素这么多,我们不可能手动地去分析数据。

如果我们要算出RGB各个位低于100的数量,我们可以这样做:

from PIL import Image
 im = Image.open("1.jpg")
 count = 0
 for y in range(im.size[1]):
     for x in range(im.size[0]):
         pix = im.getpixel((x,y))
         if(pix[0] < 100 and pix[1] < 100 and pix[2] < 100):
             count = count + 1
 print(count)

结果是265743.我们甚至可以把它们转换成别的颜色。

最好是不在原图上操作,我们new一个一样大小的图片即可。

im2 = Image.new(“RGB”,im.size,255)

意思是新建一个跟它一样大的RGB图片,背景颜色为红色。

我们把刚刚各个位低于100的像素转化为白色。

from PIL import Image
im = Image.open("1.jpg")
im2 = Image.new("RGB",im.size,255)
count = 0
for y in range(im.size[1]):
    for x in range(im.size[0]):
        pix = im.getpixel((x,y))
        if(pix[0] < 100 and pix[1] < 100 and pix[2] < 100):
            im2.putpixel((x,y),(255,255,255))
im2.show()

结果:

如果我们对原图进行修改颜色:

嘛,还是可以接受的。

源代码已经上传到公众号的github项目。以后公众号的源代码及图片都能在这里找到:https://github.com/Ckend/GongZhongHao

欢迎关注微信公众号:Python实用宝典https://pythondict.com