大量文件字數統計:LibreOffice 篇
先前 DR 在自動化處理大量 Word 檔案之字數統計一文中說明過使用 Python 去呼叫 Microsoft Word 以取得字數統計的作法。那如果手上沒有 Microsoft Word 怎麼辦?沒關係,同樣的需求也可以使用跨平台而且免費的 LibreOffice 來達成。
未曾聽聞過 LibreOffice 的人可以看一下 DR 的簡短介紹(反之就可以直接跳過):LibreOffice 其實就是知名的開源碼辦公軟體 OpenOffice.org(OOo)的後繼者之一,這個專案之所以誕生主要是由於原本持有 OOo 版權的昇陽(Sun)公司被甲骨文(Oracle)收購後,一些開發人員看到 OOo 的前景不明,便決定創建非營利的文件基金會(The Document Foundation)以既有的 OOo 原始碼為基礎繼續發展,而成果便是 LibreOffice。至於原本的 OOo 版權及有關資產則被甲骨文全數捐贈給 Apache 基金會,並定名為 Apache OpenOffice。
所以說,OpenOffice.org 已經分家了,一個是 Apache OpenOffice,另一個則是 LibreOffice。由於實至目前為止,LibreOffice 的更新、發展速度相對於 Apache OpenOffice 都快得多,多數的 Linux 發行版也都選擇 LibreOffice 作為預設的辦公軟體套裝,包含 DR 自己也是使用者之一,因此本文是使用 LibreOffice 做範例。另外,LibreOffice 3.6 版也是 OOo 及其衍生產品中第一個修正字數統計錯誤的版本(終於),在此之前的版本其實在字數統計上都存在著漏洞。
本文是以 Windows 為測試環境,使用 LibreOffice 內建的 Python 去呼叫 UNO(Universal Network Objects)模組來控制 LibreOffice 元件。由於 LibreOffice 無法像 Microsoft Office 那樣、有 COM 介面直接去啟動軟體,而且在啟動後,預設也不會開啟通訊介面。因此必須使用以下參數來啟動 LibreOffice 才能和外部程式通訊:
- soffice.exe "--accept=socket,host=localhost,port=2002;urp;"
接著便是字數統計的 Python 程式範例:
import os, sys import uno from com.sun.star.beans import PropertyValue appdir = os.path.abspath(os.path.dirname(sys.argv[0])) os.chdir(appdir) doc_dir = "docs" doc_ext = (".txt", ".doc", ".docx", ".rtf", ".odt") localContext = uno.getComponentContext() resolver = localContext.ServiceManager.createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", localContext) ctx = resolver.resolve("uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext") smgr = ctx.ServiceManager desktop = smgr.createInstanceWithContext("com.sun.star.frame.Desktop", ctx) property = PropertyValue() property.Name = "Hidden" property.Value = True print "Filename,Words,Characters" for fn in os.listdir(doc_dir): if filter(fn.lower().endswith, doc_ext): url = uno.systemPathToFileUrl(os.path.join(appdir, doc_dir, fn)) model = desktop.loadComponentFromURL(url, "_blank", 0, (property,)) words = model.WordCount chars = model.CharacterCount model.close(True) line = fn + "," + str(words) + "," + str(chars) print line ctx.ServiceManager
程式碼的大部分內容是直接從 hello_world.py 範例複製而來,原範例有詳細的註解說明可以參考。程式碼的測試方式如下:
- 確認 LibreOffice 已啟動並開啟通訊介面
- 將程式碼儲存為 word_count.py
- 在存放 word_count.py 的同一個路徑下建立 docs 目錄,將要統計字數的文件放置在該目錄裡
- 開啟命令行,移動到 word_count.py 的路徑
- 在命令行下使用 LibreOffice 內建的 Python 執行程式:「"C:\Program Files (x86)\LibreOffice 3.6\program\python.exe" word_count.py」
- 統計結果會顯示在命令行
附註:撇開字數統計的臭蟲不談,本文的程式碼完全相容於 OOo 和 Apache OpenOffice。