由于经常写作,需要为文章准备一些配图,通常这些配图是从百度图片搜索里准备的。在准备图片时,我遇到了两个小麻烦:
有没有什么办法能让我轻松的获得复制的图片呢?经过一番思索,我研究出一个方案:
让程序每隔一秒钟监听一次剪贴板,如果剪贴板里是图片,就保存到指定文件夹里,这样,在复制图片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()
代码准备好以后,我在百度图片里随意复制了一张图片,然后运行程序,图片果然被保存到了指定目录里,哈哈,完全可行。
我不能从剪贴板里获得图片的文件名,因此需要为它设置文件名称,就用时间这种最简单的方式,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格式图片要小很多。
图片存储的多了,自然会变得杂乱无章,尽管文件名称可以排序但还是应当按天来存储,这样便于查找
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()
程序最终要循环执行,每隔一秒钟去剪贴板里检查一下是否有数据,数据是否是图片,在第一次保存图片后,图片仍然在剪贴板里,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() # 关闭剪切板
def main():
while True:
paste_pic()
time.sleep(1)
if __name__ == '__main__':
main()
每隔一秒钟,运行一次paste_pic函数,实际测试,效果非常好,包括屏幕截取也能保存下来,因为截屏后的图片也保存在剪贴板里。
在前面的设计中,图片被保存后清空剪贴板,想了想,这样做有不妥之处。复制图片并不都是为了保存成文件,有时仅仅是想粘贴在某处,比如发送给微信的朋友或者直接粘贴在有道云笔记里。针对这种情况,我修改了删除策略,图片在剪贴板里存储超过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秒的时间里,你可以将图片粘贴到你想粘贴的位置上。
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
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():
try:
im = ImageGrab.grabclipboard()
except:
print('打开剪贴板失败')
return
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)
def clear_clipboard():
from ctypes import windll
if windll.user32.OpenClipboard(None): # 打开剪切板
windll.user32.EmptyClipboard() # 清空剪切板
windll.user32.CloseClipboard() # 关闭剪切板
def main():
while True:
paste_pic()
time.sleep(1)
if __name__ == '__main__':
main()
QQ交流群: 211426309