原本只打算發篇文簡單回顧 2020 年我寫了什麼文章
沒想到就慢慢演變成開發 pelican-stat ......
原本只打算寫一篇的回顧文,就莫名其妙變成了三篇文章的系列文
- 如何得到 pelican 文章資訊並用來做圖: 就是本文,主要會聊開發 pelican-stat 的過程
- 如何在 pelican 頁面中嵌入 HTML: 將產生的互動式趨勢圖嵌入 pelican 的文章中,遇到的各種雷
- 2020 過去了,我寫了什麼文章: 2020 主要發了什麼文章,並聊聊當初為什麼會想寫這些文章
什麼是 pelican-stat
pelican 是用來產生靜態網頁的工具,最常見的用途應該是寫部落格
你所看到的這個部落格就是透過這套工具產生的
pelican-stat 則是我這次開發來蒐集pelican 文章資料並作圖的工具
如何使用 pelican-stat
安裝
因為我把 pelican 的版本定在 4.5.4
為了避免跟你的 pelican 版本打架,強烈建議使用 pipx 安裝
pipx install pelican-stat
pelican-stat 目前支援 collect
和 plot
兩種指令
Usage: pelican-stat [OPTIONS] COMMAND [ARGS]...
Options:
--help Show this message and exit.
Commands:
collect Collect data from pelican project and export article metadata
plot Draw trend plot based on the frequency of new posts
collect
將文章的資訊整理並輸出成 json 檔
e.g.,
[
...,
{
"timestamp": 1560308220.0,
"category": "Travel",
"authors": [
"Lee-W"
],
"reader": "markdown",
"status": "published",
"tags": [
"Star Wars",
"Galaxy's Edge"
],
"timezone": "Asia/Taipei",
"title": "Star Wars: Galaxy's Edge - First Peek"
}
]
第一個參數吃的是 pelican 的設定檔,第二個則是輸出的位置
plot
就如同指令的名稱,它就是拿來做圖用的
目前只支援趨勢圖
使用上比 collect
複雜一點,有 5 個可以設定的參數
--pelican-conf-path [PATH]
: pelican 設定檔的路徑--articles-metadata-path [PATH]
: 用collect
指令所產生的文章資料 json 檔的路徑
上面兩個一定要有一個有值,不然 pelican-stat 不知道要去哪抓文章資料
--output-path [PATH]
: 輸出檔名--year [YEAR]
: 篩選特定年份的文章--groupby-category
: 作圖是否要根據文章類別分群
最後就能做出像這樣的圖
產生的會是可以互動的 HTML 檔案
設計 pelican-stat
在開始寫 pelican-stat 前,我有找到類似的工具 👉 panorama
不過它是作為 pelican-plug 來使用,而不是獨立的指令列工具
所以就只好自己來寫了
collect
第一個收集文章資訊的想法是寫 parser 去解析這些文章
但是這麼做的話,這個工具可能就很難被其他人使用
每個人指定 metadata 、放置文章的方式可能都不同
甚至有人根本是用 reStructuredText 寫的
(pelican 支援 reStructuredText 跟 markdown)
不過有個工具一定有辦法抓到這些資訊
沒錯💡
那就是 pelican 本身!
所以第二個想法是觀察 pelican 怎麼去解析這些文章
如果能的話,直接呼叫它的函式,不要重造輪子
從使用 pelican 指令到產生文章,會用這個順序追朔程式碼
- pelican/__main__.py#L9
- pelican/__init__.py#L491
- pelican/__init__.py#L501
- pelican/__init__.py#L403-418
這就是為什麼我的 _get_pelican_instance 會這樣寫
而我額外多做了兩個處理
settings["PLUGINS"] = []
settings["MARKDOWN"] = {}
原因是 MARKDOWN 跟 PLUGINS 都有可能有額外的相依套件
尤其是 pelican 自從 4.5.0 之後開始支援從 pip 安裝的 pelican-plugins
但它們對文章的 metadata 大多不會有影響
所以將他們從設定中清掉可以避免遇到相依套件沒裝的問題
接著繼續追程式碼
我透過 pdb 看到 generators[0]
是 ArticlesGenerator
看起來透過它就有很大的機會能取得文章資訊
它也會對應到我所寫的 pelican_stat/collector.py#L29-L43
這裡也是我會把 pelican-stat 相依的 pelican 釘在 4.5.4 的主因
_get_generator_classes 在 4.5.2 以前是 get_generator_classes
雖然可以用 getattr(pelican_instance, "get_generator_classes")
來支援不同的版本
但難保 pelican 什麼時候又會改 API
而且即使 pelican 的版本不同,對於文章 metadata 的格式應該都不會有改變
所以作為一個工具,使用特定版本的 pelican 應該就足夠了
最後在 pelican/__init__.py#L111-L113 執行完 generate_context()
就能從 article_generator.aricles
取得文章
而每篇文章都是 pelican.context.Article 的 instance
所以只要看裡面有哪些資訊是我要的,在進行輸出就可以了 👉 pelican_stat/collector.py#L47
plot
最初版測試用的 script,先了用我比較熟悉的 bokeh 寫
但上次有朋友安利我 ploty 很好用,就決定來玩玩看
使用上覺得兩個函式庫都還蠻直覺的
但 ploty 可以不用多做設定就有 hover tool ,還蠻方便的
因為這部分的程式碼大多都是看文件就能找到,就不特別聊了