基於Python實現Windows下壁紙切換功能

在過去一年多的時間裡,我嘗試改變博客的寫作風格,努力讓自己不再寫教程類文章,即使在這個過程中,不斷地面臨著寫作內容枯竭的痛苦。因為我漸漸地意識到,告訴別人如何去做一件事情,始終停留在"術"的層面,而比這個更為重要的是,告訴別人為什麼要這樣做,這樣就可以過渡到"道"的層面。古人云:形而上者謂之道,形而下者謂之器。我們常常希望通過量變來產生質變,可是如果在這個過程中不能及時反思和總結,我們認為的努力或許僅僅是重複的勞作而已。如你所見,在這篇文章里,我們將通過Python和Windows註冊表實現壁紙切換功能,主要涉及到的Python中的requests、pyinstaller這兩個模塊的使用,希望大家喜歡。

故事緣由

人們常常相信事出有因,可這世界上有些事情,哪裡會有什麼原因啊,比如喜歡與不喜歡。做這樣一個小功能的初衷,起源於我對桌面壁紙的挑剔。作為一個不完全的強迫症患者,我需要花費大量時間去挑選一張壁紙,絲毫不亞於在網上挑選一件喜歡的商品。我注意到知乎上有這樣的話題:有哪些無版權圖片網站值得推薦?,因此對於桌面壁紙的篩選,我漸漸地開始擺脫對搜索引擎的依賴,我個人比較喜歡Pexels和Unsplash這兩個網站,所以我想到了從這兩個網站抓取圖片來設置Windows壁紙的方案。市面上類似的商業軟體有百度壁紙、搜狗壁紙等,可這些軟體都不純粹,或多或少地摻雜了額外功能,個中緣由想來大家都是知道的。聯想到微信最新版本的更新,"發現"頁面支持所有項目的隱藏,甚至是盟友京東的電商入口和騰訊最賺錢的遊戲入口,這讓我開始正視騰訊這家公司,我收回曾經因為抄襲對騰訊產生的不滿,騰訊是一家值得尊重的互聯網公司。做一個純粹的應用程序,這就是我的初心。

設計實現

好了,現在我們考慮如何來實現這個功能,我們的思路是從Unsplash這個網站抓取圖片,並將其存儲在指定路徑,然後通過Windows API完成壁紙的設置。Python腳本會通過pyinstaller模塊打包成可執行文件,我們通過修改註冊表的方式,在右鍵菜單內加入切換壁紙的選項,這樣我們可以直接通過右鍵菜單實現壁紙切換功能。在編寫腳本的時候,起初想到的是抓包這樣的常規思路,因為請求過程相對複雜而失敗,後來意外地發現官方提供了API介面。事實上Pexels和Unsplash都提供了API介面,通過調用這些API介面,我們的探索進行得非常順利,下面是具體腳本實現:

# Query ImagessearchURL = https://unsplash.com/napi/search?client_id=%s&query=%s&page=1client_id = fa60305aa82e74134cabc7093ef54c8e2c370c47e73152f72371c828daedfcd7categories = [nature,flowers,wallpaper,landscape,sky]searchURL = searchURL % (client_id,random.choice(categories))response = requests.get(searchURL)print(u正在從Unsplash上搜索圖片...)# Parse Imagesdata = json.loads(response.text)results = data[photos][results]print(u已為您檢索到圖片共%s張 % str(len(results)))results = list(filter(lambda x:float(x[width])/x[height] >=1.33,results))result = random.choice(results)resultId = str(result[id])resultURL = result[urls][regular]# Download Imagesprint(u正在為您下載圖片:%s... % resultId)basePath = sys.path[0]if(os.path.isfile(basePath)): basePath = os.path.dirname(basePath)baseFolder = basePath + \Download\if(not path.exists(baseFolder)): os.makedirs(baseFolder)jpgFile = baseFolder + resultId + .jpgbmpFile = baseFolder + resultId + .bmpresponse = requests.get(resultURL)with open(jpgFile,wb) as file: file.write(response.content)img = Image.open(jpgFile)img.save(bmpFile,BMP)os.remove(jpgFile)

這部分代碼非常簡單,需要關注的地方有:第一,這個API對應的密鑰是公共的,即所有人都可以使用,這裡隨機從指定的分類中去搜索圖片。第二,這裡使用filter()函數過濾出寬高比超過1.33的圖片,即解析度為1366 * 768的圖片。這裡需要注意的是,在Python3.X下filter需要轉化為list,否則會引發一個異常。第三,下載的圖片默認為JPEG格式,而Windows下設置壁紙使用的是點陣圖格式,即BMP格式,所以在這裡我們使用PIL模塊來完成格式轉換。這裡需要注意的是,PIL模塊目前不支持Python3.X以後的版本,我們這裡使用的是Pillow模塊,該模塊可以通過pip直接完成安裝。

現在,我們將壁紙下載到本地以後,就可以著手設置壁紙相關的工作。這些工作主要藉助為win32api和win32gui這兩個內置模塊,我們一起來看具體代碼:

print(u正在設置圖片:%s為桌面壁紙... % resultId)key = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER, "Control Panel\Desktop",0,win32con.KEY_SET_VALUE)win32api.RegSetValueEx(key, "WallpaperStyle", 0, win32con.REG_SZ, "2") #2拉伸適應桌面,0桌面居中win32api.RegSetValueEx(key, "TileWallpaper", 0, win32con.REG_SZ, "0")win32gui.SystemParametersInfo(win32con.SPI_SETDESKWALLPAPER, bmpFile, 1+2)print(u成功應用圖片:%s為桌面壁紙 % resultId)

這部分內容非常簡單,基本沒有複雜的東西在裡面。接下來我們需要通過pyinstaller模塊將腳本打包成可執行文件,實際上這個步驟完全可以省略,因為現在我們通過命令行就可以實現壁紙切換,為什麼要做這樣額外的工作呢?考慮到Windows下GUI更為便捷一點,所以我們打包成可執行文件,主要是為了給右鍵菜單添加功能,我們最終點擊想要實現的功能是,點擊右鍵菜單就可以完成壁紙的切換。首先通過pip安裝pyinstaller模塊,在終端下執行命令:

python -m pip install pyinstaller

安裝完成後按照官方文檔即可在./dist/目錄中找到生成的可執行文件,如果打包出錯可以修改Python根目錄下的./Scripts/pyinstaller-script.py文件,修改第一行Python.exe的路徑,刪除兩端的引號即可,如下圖所示。關於pyinstaller模塊打包時的詳細參數設定,請自行查閱官方文檔。

現在,在生成可執行文件以後,我們打開註冊表,定位到以下節點:

計算機HKEYCLASSESROOTDirectoryBackgroundshell,然後創建一級子節點WallPaper,其默認值填寫"更換壁紙",接下來創建二級子節點command,注意這個名稱不能修改,其默認值填寫可執行文件路徑,本例中為:E:SoftwareWallPapermain.exe,如下圖所示:

好了,現在我們可以看看在右鍵菜單中增加"更換壁紙"選項以後的效果:

文本小結

本文使用Python實現了Windows下切換壁紙的功能,通過requests模塊從網路上抓取圖片,通過PIL模塊實現JPEG格式到BMP格式的轉換,通過win32api和win32gui模塊實現壁紙設置,並通過修改註冊表的方式,將這一功能整合到系統菜單中,可以非常便捷地更換桌面壁紙。作為一個設計上的擴展,我們需要考慮更多的問題,比如當網路斷開的時候如何避免異常,如何接入更多的在線圖庫API,如何支持可配置的圖片分類信息以及如何將修改註冊表的過程自動化等等,這些問題博主會利用空閑時間去解決,今天這篇文章就是這樣啦,本文源代碼可以通過這裡獲取,謝謝大家!


版權信息:

《基於Python實現Windows下壁紙切換功能》由Payne首發于飛鴻踏雪的部落格,轉載請註明作者及出處,謝謝。

推薦閱讀:

那麼,Python做爬蟲究竟比其他語言好在哪裡呢?
如何用爬蟲下載中國土地市場網的土地成交數據?
【翻譯搬運】SciPy-Python科學演算法庫
第十三章 Python: xml轉json
流暢的Python --- 導言

TAG:Python | 脚本 | 工具 |