用python实现一个自动保存复制图片的功能

coolpython

共 3614字,需浏览 8分钟

 · 2021-07-20

由于经常写作,需要为文章准备一些配图,通常这些配图是从百度图片搜索里准备的。在准备图片时,我遇到了两个小麻烦:

  1. 有些图片的格式是webp,需要在另存为时指定格式

  2. 有些图片需要剪切,剪切后不能直接复制到桌面,我总是先复制到qq聊天窗口,然后另存为,步骤繁琐

有没有什么办法能让我轻松的获得复制的图片呢?经过一番思索,我研究出一个方案:让程序每隔一秒钟监听一次剪贴板,如果剪贴板里是图片,就保存到指定文件夹里,这样,在复制图片1秒钟后程序就自动的帮我把图片保存下来。

说干就干。

1. 验证可行性

首先,我需要验证这个思路的可行性,经过调研,得知PIL库的ImageGrab模块提供的grabclipboard函数可以获得剪贴板里的内容并且可以判断是否为图片,这就好办了

from PIL import Image, ImageGrab

def paste_pic():
im = ImageGrab.grabclipboard()
if isinstance(im, Image.Image):
im.save(r'C:\Users\zhangdongsheng\Desktop\图片\pic.png')


if __name__ == '__main__':
paste_pic()

代码准备好以后,我在百度图片里随意复制了一张图片,然后运行程序,图片果然被保存到了指定目录里,哈哈,完全可行。

2. 设置文件名称

我不能从剪贴板里获得图片的文件名,因此需要为它设置文件名称,就用时间这种最简单的方式,2021-07-16-10-25-39,用时间命名在查找图片时也提供了一定的检索能力

import os
from PIL import Image, ImageGrab
from datetime import datetime

def get_file_name():
return datetime.now().strftime("%Y-%m-%d-%H-%M-%S") + '.jpg'

def paste_pic():
im = ImageGrab.grabclipboard()
if isinstance(im, Image.Image):
filename = os.path.join(r'C:\Users\zhangdongsheng\Desktop\图片', get_file_name())
im.save(filename)

if __name__ == '__main__':
paste_pic()

顺便将图片的格式改为jpg,不损失太多图片质量的情况下比png格式图片要小很多。

3. 以天为单位存储

图片存储的多了,自然会变得杂乱无章,尽管文件名称可以排序但还是应当按天来存储,这样便于查找

import os, time
from PIL import Image, ImageGrab
from datetime import datetime

root_dir = r'C:\Users\zhangdongsheng\Desktop\图片'

def get_file_name():
return datetime.now().strftime("%Y-%m-%d-%H-%M-%S") + '.jpg'

def make_dir_by_day():
day_dir = datetime.now().strftime("%y-%m-%d")
day_dir = os.path.join(root_dir, day_dir)
if not os.path.exists(day_dir):
os.mkdir(day_dir)

return day_dir

def paste_pic():
im = ImageGrab.grabclipboard()
if isinstance(im, Image.Image):
day_dir = make_dir_by_day()
filename = os.path.join(day_dir, get_file_name())
im.save(filename)


if __name__ == '__main__':
paste_pic()

4. 清空剪贴板

程序最终要循环执行,每隔一秒钟去剪贴板里检查一下是否有数据,数据是否是图片,在第一次保存图片后,图片仍然在剪贴板里,1秒钟后再次执行paste_pic时又会复制保存一次,这是万万不行的。

在图片被保存后,直接清空剪贴板

def paste_pic():
im = ImageGrab.grabclipboard()
if isinstance(im, Image.Image):
day_dir = make_dir_by_day()
filename = os.path.join(day_dir, get_file_name())
im.save(filename)
clear_clipboard()

def clear_clipboard():
from ctypes import windll
if windll.user32.OpenClipboard(None): # 打开剪切板
windll.user32.EmptyClipboard() # 清空剪切板
windll.user32.CloseClipboard() # 关闭剪切板

5. 运行起来

def main():
while True:
paste_pic()
time.sleep(1)


if __name__ == '__main__':
main()

每隔一秒钟,运行一次paste_pic函数,实际测试,效果非常好,包括屏幕截取也能保存下来,因为截屏后的图片也保存在剪贴板里。 


6. 剪贴板保留图片30秒

在前面的设计中,图片被保存后清空剪贴板,想了想,这样做有不妥之处。复制图片并不都是为了保存成文件,有时仅仅是想粘贴在某处,比如发送给微信的朋友或者直接粘贴在有道云笔记里。针对这种情况,我修改了删除策略,图片在剪贴板里存储超过39秒以后再执行删除

old_info = {
'size': 0,
'time': datetime.now()
}


def is_old_pic(im):
im_size = len(im.tobytes())
if old_info['size'] == im_size: # 是旧图片,已经保存过
return True

# 新图片,记录新图片的信息
old_info['size'] = im_size
old_info['time'] = datetime.now()
return False


def paste_pic():
im = ImageGrab.grabclipboard()
if isinstance(im, Image.Image):
if is_old_pic(im):
# 如果是旧图片,存在时间超过30秒以后再清空
if (datetime.now() - old_info['time']).seconds > 30:
clear_clipboard()
else:
day_dir = make_dir_by_day()
filename = os.path.join(day_dir, get_file_name())
im.save(filename)

使用old_info字典记录图片的信息,size保存图片大小,用于比较剪贴板里的图片是否为旧图片,time保存新图片的保存时间,用于计算图片被保存在剪贴板里的时间。

经过改造后,图片可以正常保存,但不会在保存后立即删除,而是在剪贴板里保存30秒,这30秒的时间里,你可以将图片粘贴到你想粘贴的位置上。


浏览 33
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报