用python實(shí)現(xiàn)一個(gè)自動(dòng)保存復(fù)制圖片的功能
由于經(jīng)常寫作,需要為文章準(zhǔn)備一些配圖,通常這些配圖是從百度圖片搜索里準(zhǔn)備的。在準(zhǔn)備圖片時(shí),我遇到了兩個(gè)小麻煩:
有些圖片的格式是webp,需要在另存為時(shí)指定格式
有些圖片需要剪切,剪切后不能直接復(fù)制到桌面,我總是先復(fù)制到qq聊天窗口,然后另存為,步驟繁瑣
有沒有什么辦法能讓我輕松的獲得復(fù)制的圖片呢?經(jīng)過一番思索,我研究出一個(gè)方案:讓程序每隔一秒鐘監(jiān)聽一次剪貼板,如果剪貼板里是圖片,就保存到指定文件夾里,這樣,在復(fù)制圖片1秒鐘后程序就自動(dòng)的幫我把圖片保存下來(lái)。
說干就干。
1. 驗(yàn)證可行性
首先,我需要驗(yàn)證這個(gè)思路的可行性,經(jīng)過調(diào)研,得知PIL庫(kù)的ImageGrab模塊提供的grabclipboard函數(shù)可以獲得剪貼板里的內(nèi)容并且可以判斷是否為圖片,這就好辦了
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()
代碼準(zhǔn)備好以后,我在百度圖片里隨意復(fù)制了一張圖片,然后運(yùn)行程序,圖片果然被保存到了指定目錄里,哈哈,完全可行。
2. 設(shè)置文件名稱
我不能從剪貼板里獲得圖片的文件名,因此需要為它設(shè)置文件名稱,就用時(shí)間這種最簡(jiǎn)單的方式,2021-07-16-10-25-39,用時(shí)間命名在查找圖片時(shí)也提供了一定的檢索能力
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,不損失太多圖片質(zhì)量的情況下比png格式圖片要小很多。
3. 以天為單位存儲(chǔ)
圖片存儲(chǔ)的多了,自然會(huì)變得雜亂無(wú)章,盡管文件名稱可以排序但還是應(yīng)當(dāng)按天來(lái)存儲(chǔ),這樣便于查找
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. 清空剪貼板
程序最終要循環(huán)執(zhí)行,每隔一秒鐘去剪貼板里檢查一下是否有數(shù)據(jù),數(shù)據(jù)是否是圖片,在第一次保存圖片后,圖片仍然在剪貼板里,1秒鐘后再次執(zhí)行paste_pic時(shí)又會(huì)復(fù)制保存一次,這是萬(wàn)萬(wàn)不行的。
在圖片被保存后,直接清空剪貼板
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() # 關(guān)閉剪切板
5. 運(yùn)行起來(lái)
def main():
while True:
paste_pic()
time.sleep(1)
if __name__ == '__main__':
main()
每隔一秒鐘,運(yùn)行一次paste_pic函數(shù),實(shí)際測(cè)試,效果非常好,包括屏幕截取也能保存下來(lái),因?yàn)榻仄梁蟮膱D片也保存在剪貼板里。

6. 剪貼板保留圖片30秒
在前面的設(shè)計(jì)中,圖片被保存后清空剪貼板,想了想,這樣做有不妥之處。復(fù)制圖片并不都是為了保存成文件,有時(shí)僅僅是想粘貼在某處,比如發(fā)送給微信的朋友或者直接粘貼在有道云筆記里。針對(duì)這種情況,我修改了刪除策略,圖片在剪貼板里存儲(chǔ)超過39秒以后再執(zhí)行刪除
old_info = {
'size': 0,
'time': datetime.now()
}
def is_old_pic(im):
im_size = len(im.tobytes())
if old_info['size'] == im_size: # 是舊圖片,已經(jīng)保存過
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):
# 如果是舊圖片,存在時(shí)間超過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保存新圖片的保存時(shí)間,用于計(jì)算圖片被保存在剪貼板里的時(shí)間。
經(jīng)過改造后,圖片可以正常保存,但不會(huì)在保存后立即刪除,而是在剪貼板里保存30秒,這30秒的時(shí)間里,你可以將圖片粘貼到你想粘貼的位置上。
