小豬的Python學習之旅 —— 22.安靜!吵到我用TNT了
小豬的Python學習之旅 —— 22.安靜!吵到我用TNT了
標籤:Python
一句話概括本文:
靈感來自於5.15錘子鳥巢釋出會上老羅用閃念膠囊一鍵生成了32張PPT,
原理利用Python-pptx庫,通過編寫模板的方式自動生成批量PPT!
引言:
鏘鏘鏘,失蹤人口迴歸,距離上一篇文章已過去14天。不是我偷懶不更新,
主要是轉崗打雜了,很雜那種,每天要處理一堆和開發無關的瑣事,
真的是敲碼五分鐘,打雜兩小時…還是當個單純的開發仔好啊。
標題沒錯,是第22篇不是21,不用回去翻,沒看漏,第20篇寫的是爬取Gank.io
介面的所有資料到MySQL,第21篇已經定好利用Flask編寫一個API介面,
程式碼是實現了,部署還有些問題,所以還沒些,先佔個坑。
本節的話,是最近兩天在折騰的一個東西,因為組內正在整線上早教
相關的東西,老師呢,要做很多的課件,但是大部分的內容都是重複的,
可能就圖片會變下,流程可能會變一點,然後就找到我,讓我想想有沒有辦法
自動生成減少她們的工作量,對,她們想要的就是 自動生成PPT!
還記得5.15錘子鳥巢釋出會嗎?不記得?看到這個圖你應該想起什麼了~
老羅現場展示了次時代電腦:TNT工作站 ,這裡就不吐槽現場演示時的
各種小失誤和理解萬歲了。直播回顧的視訊可以到B站看:
釋出會直播我是有全程看完的,有個地方吸引了我的注意,在視訊裡69:08處,
老羅利用閃念膠囊直接就生成了32張PPT,給人一種錯覺:
臥槽,好屌,以後連PPT都不用自己做了!
其實不然,如果是細心的觀眾基本會發現一個規律,生成的PPT都是非常簡單
的PPT,一個黑色漸變的大背景,配幾行字,或者再配個圖片,PPT動畫也沒有。
來,來給你個這樣的PPT生成給我看:
這種批量生成簡單PPT的套路,我覺得思路無非這樣:
根據情形,定義幾套模板,然後約定一個規則,根據不同的內容呼叫
不同的模板,進行內容填充。
套路知道了,接下來就是看看Python有沒有支援庫了~
找到兩個pptx和win32com,本節只用前者,因為後者的文件是真的
看得人頭皮發麻,而且網上的例子非常少…
1.python-pptx庫
官方文件:http://python-pptx.readthedocs.io/en/latest/index.html
官方倉庫:https://github.com/scanny/python-pptx
安裝庫:pip install python-pptx
對了,因為win32com那個庫要呼叫微軟的PowerPoint,我把電腦重灌回
Win 10了,索性安裝了最新版的PyCharm,然後發現建立的工程和以前
建立的工程結構不一樣,多了個這樣的東西:
終端執行也變成了:(venv) F:\Python> 這樣,這個就是虛擬環境,
簡單點說就是對開發環境進行隔離,比如你這個專案基於Python 2.x,另一個專案
基於Python 3.x,或者說著兩個專案裡依賴的同一個模組用著不同的版本,通過
虛擬環境可以讓這兩個專案互不干擾,將所需的包安裝到獨立的環境中。
Python中常用的建立和管理虛擬環境的工具有:virtualenv和pyvenv,
Pycharm預設帶有virtualenv,新建的時候就可以看到,具體怎麼定製化,
自行百度吧~對了,下載模組都在Lib/site-packages
目錄下!
2.實現流程分析
首先的話,先想想有哪些模板,羅列下:
- 1.只有一張圖片
- 2.只有一條文字
- 3.一條文字和一張圖片
- 4.兩條文字
- 5.四條文字
然後佈局大概這樣咯:
接著定義一個規則,資料怎麼傳,這裡採用最簡單的套路,寫個txt檔案,
每行代表一個PPT,引數通過逗號間隔,於是完整的PPT對應這樣的txt檔案:
通過逗號分割引數,優先判斷是否有圖片,有的話走模板1,3,
其他再另外判斷。好的,思路有了,接下來開始一步步實現吧。
3.程式碼實現
PS:這裡不去介紹怎麼用,看不懂自己去翻文件,我也是自己摸索,
有我寫的示例參考,應該覺得很欣慰了。
1.定義一個釐米轉英寸的方法
以為PPT裡的位置和大小用到的單位都是釐米,需要轉換下
# 釐米轉英寸
def cm_to_in(cm):
return Inches(cm / 2.54)
2.編寫模板
先是模板1,傳入Presentation的物件,這個你可以理解成PPT物件,
呼叫該物件的.slides.add_slide()方法新增一張幻燈片,pptx庫為我們
提供了八個不一樣的模板,喜歡的可以自己一個個試,這裡我們直接用第七
張空白幻燈片,下標從0開始,所以是prs.slide_layouts[6]
,幻燈片
加了之後,呼叫Presentation的save(ppt檔名)函式開啟生成的PPT,
然後點選設定 -> 幻燈片大小 -> 直接選擇16:9或者設定幻燈片大小,比如我
的,這裡的寬度和高度就是我們幻燈片的大小了,後面填充滿屏的圖片就要
用到這個。
然後呼叫add_picture函式新增一個滿屏圖片:
slide.shapes.add_picture(ppt_bg_path, cm_to_in(0), cm_to_in(0), cm_to_in(25.4), cm_to_in(14.288))
然後模板1就寫完了,完成程式碼如下:
# 模板1:只有一張圖片
def model_1(prs, pic_path):
slide = prs.slides.add_slide(prs.slide_layouts[6])
slide.shapes.add_picture(pic_path, cm_to_in(0), cm_to_in(0), cm_to_in(25.4), cm_to_in(14.288))
# 呼叫:
presentation = Presentation(ppt_file_name)
model_1(presentation, laoluo_bg_path)
開啟生成的ppt:
喲,成功生成,接著到模板2:
填充滿屏圖片,然後新建一個文字框:
title_box = slide.shapes.add_textbox(cm_to_in(3.89), cm_to_in(5.35), cm_to_in(17.61), cm_to_in(3.59))
再接著新增一個文字域:
paragraph = title_box.text_frame.add_paragraph()
然後就可以對文字域裡進行文字相關的操作了:
paragraph.text = title # 設定文字
paragraph.vertical_anchor = MSO_VERTICAL_ANCHOR.MIDDLE # 設定垂直方向對齊方式
paragraph.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER # 設定水平方向對齊方式
paragraph.font.size = Pt(60) # 設定文字大小,PT代表磅
paragraph.font.name = '微軟雅黑' # 設定字型
paragraph.font.color.rgb = RGBColor(255, 255, 255) # 設定字型顏色
引數傳遞下,呼叫這個模板2,檢視下生成的效果:
接下來如法炮製剩下的三個模板,主要是難點是控制元件的位置和寬高設定,
有兩種操作:
最簡單的操作:
隨便填個座標和寬高,執行後開啟生成的PPT,自行調整
位置,然後記錄下何時的位置和寬高,然後改程式碼。
複雜點的操作:
自行計算,比如模板5,三個小標題,先減去左右的間隔,
然後三等分,迴圈動態計算小標題的起始位置。
3.配置檔案讀取
接下來編寫一個讀取檔案內容,呼叫對應方法的函式,程式碼如下
# 讀取配置檔案呼叫模板的方法
def read_rules(prs, filename):
if os.path.exists(filename):
with open(filename, 'r+', encoding='utf-8') as f:
for rule in f:
word_list = rule.replace('\n', '').split(',')
if 'png' in rule or 'jpg' in rule:
if len(word_list) == 1:
model_1(prs, os.path.join(c.res_pictures, word_list[0]))
else:
model_3(prs, word_list[0], os.path.join(c.res_pictures, word_list[1]))
else:
if len(word_list) == 1:
model_2(prs, word_list[0])
elif len(word_list) == 2:
model_4(prs, word_list[0], word_list[1])
elif len(word_list) == 4:
model_5(prs, word_list[0], word_list[1], word_list[2], word_list[3])
4.程式碼執行
呼叫配置檔案讀取的函式
if __name__ == '__main__':
t.is_dir_existed(c.outputs_documents_path)
ppt_existed(ppt_file_name)
presentation = Presentation(ppt_file_name)
read_rules(presentation, rules_path)
presentation.save(ppt_file_name)
執行結果:
4.有些東西要說說
批量生成是挺爽的,不過呢,不支援直接生成動畫哦!!!
然後這種簡單的PPT,其實貼上複製修改圖片的效率可能比起你一個個
模板編寫快一些…不得不說有些雞肋,哦,對哦,這個還支援生成圖表,
怎麼整可以自行查閱官方文件。
另外的win32com的庫,貌似功能更加強大,可能支援動畫吧,但是文件是
真的難啃,就沒有深入去研究了,有興趣可以自己去折騰折騰。附上用
win32com這個庫時遇到的問題的解決方法:
- 1.Python3安裝win32com
pip install pypiwin32
- 2.哪裡有win32com的文件
微軟官網有,不過看到腦殼痛,介紹個工具:oleview,網上一搜一堆
不過這個用的時候會遇到一個問題,這裡順帶記錄下筆者win10電腦遇到的
一些情況:
IVIEWERS.DLL缺失:
網上搜下這個dll檔案,下載完把檔案複製到Windows/system32,
然後管理員模式開啟命令提示符,鍵入:regsvr32 iviewers.dll
註冊這個dll執行庫就可以了。不過呢,win10 64位這樣的執行是會報錯的:
模組iviewers.dll可能與您正在執行的Windows版本不相容,檢查該模組是否與
regsvr.exe的x86或x64版本相容
你要做的是把dll檔案拷貝到Windows/SysWOW64,然後管理員模式開啟命令提示符
cd到這個目錄下,接著執行regsvr32 iviewers.dll即可。
如果出現:對DllRegisterServer的呼叫失敗,錯誤程式碼為0x80070005
那是UAC的緣故,你沒有以管理員模式開啟命令提示符。
如果解決了,應該能正常開啟,左側招到PowerPoint那項,雙擊開啟,
然後呢,這個工具不支援查詢,你可以把內容全選然後複製到如Sublime Text
這樣的程式碼檢視工具上,ctrl + f 查詢關鍵字,然後一步步定位出實現某個
功能需要用到的一些函式。
小結
本節講解了一波利用Python-pptx批量生成N張PPT的套路,不禁再一次感嘆
人生苦短,我用Python,最後祝六一兒童節快樂~
參考文獻:
附:最終程式碼(都可以在:https://github.com/coder-pig/ReptileSomething 找到):
import pptx
import config as c
import tools as t
from pptx import Presentation
from pptx.dml.color import RGBColor
from pptx.util import Inches, Pt
from pptx.enum.text import MSO_VERTICAL_ANCHOR, PP_PARAGRAPH_ALIGNMENT
import os
rules_path = os.path.join(c.res_documents, 'ppt_rules.txt')
ppt_bg_path = os.path.join(c.res_pictures, 'ppt_bg.png')
laoluo_bg_path = os.path.join(c.res_pictures, 'laoluo.jpg')
last_bg_path = os.path.join(c.res_pictures, 'last.png')
story_bg_path = os.path.join(c.res_pictures, 'story.png')
ppt_file_name = os.path.join(c.outputs_documents_path, 'result.pptx')
# 釐米轉英寸
def cm_to_in(cm):
return Inches(cm / 2.54)
# 判斷課件是否存在,不存在的新建一個空白
def ppt_existed(ppt_name):
if not os.path.exists(ppt_name):
prs = Presentation()
prs.slide_height = cm_to_in(14.35)
prs.slide_width = cm_to_in(25.5)
prs.save(ppt_name)
# 模板1:只有一張圖片
def model_1(prs, pic_path):
slide = prs.slides.add_slide(prs.slide_layouts[6])
slide.shapes.add_picture(pic_path, cm_to_in(0), cm_to_in(0), cm_to_in(25.4), cm_to_in(14.288))
# 模板2:只有一個標題
def model_2(prs, title):
slide = prs.slides.add_slide(prs.slide_layouts[6])
slide.shapes.add_picture(ppt_bg_path, cm_to_in(0), cm_to_in(0), cm_to_in(25.4), cm_to_in(14.288))
title_box = slide.shapes.add_textbox(cm_to_in(3.89), cm_to_in(5.35), cm_to_in(17.61), cm_to_in(3.59))
paragraph = title_box.text_frame.add_paragraph()
paragraph.text = title
paragraph.vertical_anchor = MSO_VERTICAL_ANCHOR.MIDDLE
paragraph.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER
paragraph.font.size = Pt(60)
paragraph.font.name = '微軟雅黑'
paragraph.font.color.rgb = RGBColor(255, 255, 255)
# 模板3:有字,有圖片
def model_3(prs, title, pic_path):
slide = prs.slides.add_slide(prs.slide_layouts[6])
slide.shapes.add_picture(ppt_bg_path, cm_to_in(0), cm_to_in(0), cm_to_in(25.4), cm_to_in(14.288))
img = slide.shapes.add_picture(pic_path, cm_to_in(0), cm_to_in(0), height=cm_to_in(11.72))
img.left = int(prs.slide_width / 2 + (prs.slide_width / 2 - img.width) / 2)
img.top = int((prs.slide_height - img.height) / 2)
title_box = slide.shapes.add_textbox(cm_to_in(2), cm_to_in(5.35), int(prs.slide_width / 3), cm_to_in(3.59))
paragraph = title_box.text_frame.add_paragraph()
paragraph.text = title
paragraph.font.size = Pt(44)
paragraph.font.name = '微軟雅黑'
paragraph.font.color.rgb = RGBColor(255, 255, 255)
# 模板4:兩行文字,一大一小
def model_4(prs, title, content):
slide = prs.slides.add_slide(prs.slide_layouts[6])
slide.shapes.add_picture(ppt_bg_path, cm_to_in(0), cm_to_in(0), cm_to_in(25.4), cm_to_in(14.288))
# 一級標題
title_box_1 = slide.shapes.add_textbox(cm_to_in(1.27), cm_to_in(2.04), cm_to_in(22.86), cm_to_in(3.18))
paragraph_1 = title_box_1.text_frame.add_paragraph()
paragraph_1.text = title
paragraph_1.vertical_anchor = MSO_VERTICAL_ANCHOR.MIDDLE
paragraph_1.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER
paragraph_1.font.size = Pt(44)
paragraph_1.font.name = '微軟雅黑'
paragraph_1.font.color.rgb = RGBColor(255, 255, 255)
# 二級標題
title_box_2 = slide.shapes.add_textbox(cm_to_in(7.46), cm_to_in(6.4), cm_to_in(10.47), cm_to_in(2.39))
paragraph_2 = title_box_2.text_frame.add_paragraph()
paragraph_2.text = title
paragraph_2.vertical_anchor = MSO_VERTICAL_ANCHOR.MIDDLE
paragraph_2.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER
paragraph_2.font.size = Pt(32)
paragraph_2.font.name = '微軟雅黑'
paragraph_2.font.color.rgb = RGBColor(255, 255, 255)
# 模板5:一行文字,多個小標題
def model_5(prs, title, *content):
slide = prs.slides.add_slide(prs.slide_layouts[6])
slide.shapes.add_picture(ppt_bg_path, cm_to_in(0), cm_to_in(0), cm_to_in(25.4), cm_to_in(14.288))
title_box_1 = slide.shapes.add_textbox(cm_to_in(1.27), cm_to_in(2.04), cm_to_in(22.86), cm_to_in(3.18))
paragraph_1 = title_box_1.text_frame.add_paragraph()
paragraph_1.text = title
paragraph_1.vertical_anchor = MSO_VERTICAL_ANCHOR.MIDDLE
paragraph_1.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER
paragraph_1.font.size = Pt(44)
paragraph_1.font.name = '微軟雅黑'
paragraph_1.font.color.rgb = RGBColor(255, 255, 255)
# 動態構建小標題
module_width = (prs.slide_width - cm_to_in(1.27) * 2) / len(content)
for i in range(0, 3):
title_box = slide.shapes.add_textbox(cm_to_in(1.27) + i * module_width, cm_to_in(6.4), module_width,
cm_to_in(2.39))
paragraph = title_box.text_frame.add_paragraph()
paragraph.text = content[i]
paragraph.vertical_anchor = MSO_VERTICAL_ANCHOR.MIDDLE
paragraph.alignment = PP_PARAGRAPH_ALIGNMENT.CENTER
paragraph.font.size = Pt(32)
paragraph.font.name = '微軟雅黑'
paragraph.font.color.rgb = RGBColor(255, 255, 255)
# 讀取配置檔案呼叫模板的方法
def read_rules(prs, filename):
if os.path.exists(filename):
with open(filename, 'r+', encoding='utf-8') as f:
for rule in f:
word_list = rule.replace('\n', '').split(',')
if 'png' in rule or 'jpg' in rule:
if len(word_list) == 1:
model_1(prs, os.path.join(c.res_pictures, word_list[0]))
else:
model_3(prs, word_list[0], os.path.join(c.res_pictures, word_list[1]))
else:
if len(word_list) == 1:
model_2(prs, word_list[0])
elif len(word_list) == 2:
model_4(prs, word_list[0], word_list[1])
elif len(word_list) == 4:
model_5(prs, word_list[0], word_list[1], word_list[2], word_list[3])
if __name__ == '__main__':
t.is_dir_existed(c.outputs_documents_path)
ppt_existed(ppt_file_name)
presentation = Presentation(ppt_file_name)
read_rules(presentation, rules_path)
presentation.save(ppt_file_name)
來啊,Py交易啊
想加群一起學習Py的可以加下,智障機器人小Pig,驗證資訊裡包含:
Python,python,py,Py,加群,交易,屁眼 中的一個關鍵詞即可通過;
驗證通過後回覆 加群 即可獲得加群連結(不要把機器人玩壞了!!!)~~~
歡迎各種像我一樣的Py初學者,Py大神加入,一起愉快地交流學♂習,van♂轉py。
相關文章
- 小豬的Python學習之旅 —— 3.正規表示式Python
- 小豬的Python學習之旅 —— 2.爬蟲初涉Python爬蟲
- 小豬的Python學習之旅 —— 12.Python併發之queue模組Python
- 小豬的Python學習之旅 —— 1.基礎知識儲備Python
- 小豬的Python學習之旅 —— 10.三分鐘上手Requests庫Python
- 小豬的Python學習之旅 —— 4.Scrapy爬蟲框架初體驗Python爬蟲框架
- 小豬的Python學習之旅 —— 18.Python微信轉發小宇宙早報Python
- 小豬的Python學習之旅 —— 7.Python併發之threading模組(1)Pythonthread
- 小豬的Python學習之旅 —— 11.Python併發之threading模組(2)Pythonthread
- 小豬的Python學習之旅 —— 6.捋一捋Python執行緒概念Python執行緒
- 小豬的Python學習之旅 —— 13.文字識別庫pytesseract初體驗Python
- # 小豬的Python學習之旅 —— 17.Python資料分析:我主良緣交友瞭解下Python
- 小豬的Python學習之旅 —— 9.爬蟲實戰:爬取花瓣網的小姐姐Python爬蟲
- 小豬的Python學習之旅 —— 20.抓取Gank.io所有資料儲存到MySQL中PythonMySql
- 小豬的Python學習之旅 —— 5.使用Selenium抓取JavaScript動態生成資料的網頁PythonJavaScript網頁
- 小豬的Python學習之旅 —— 8.爬蟲實戰:刷某部落格站點的訪問量Python爬蟲
- 小豬的Python學習之旅 —— 19.Python微信自動好友驗證,自動回覆,傳送群聊連結Python
- 小豬的Python學習之旅 —— 16.再嘗Python資料分析:採集拉勾網資料分析Android就業行情PythonAndroid就業
- Python學習之旅(十九)Python
- Python學習之旅(十七)Python
- Python學習之旅(七)Python
- python學習之旅(四)Python
- python學習之旅(五)Python
- Python學習之旅(三十)Python
- 小豬的Python學習之旅 —— 15.淺嘗Python資料分析:分析2018政府工作報告中的高頻詞Python
- Python的靜態型別之旅Python型別
- Python學習之旅(三十三)Python
- opencv-python學習之旅OpenCVPython
- Python學習之旅(二十三)Python
- Python學習之旅(二十一)Python
- Python學習之旅(二十五)Python
- Python學習小記Python
- 學習jQuery之旅jQuery
- 開發了5年android,我開始了go學習之旅AndroidGo
- Python學習之旅:訪問MySQL資料庫PythonMySql資料庫
- Dubbo架構的學習之旅架構
- 開始我的學習之旅。。。。
- java學習之旅-1Java