Markdown文件批量轉(zhuǎn)PDF的Python腳本

Markdown文件批量轉(zhuǎn)PDF

Typora提供了單文件的PDF轉(zhuǎn)換功能,但沒(méi)有把這個(gè)功能集成到命令行里咐吼,因此對(duì)于需要同時(shí)轉(zhuǎn)換多個(gè)markdown文件時(shí)就比較麻煩了——因此這個(gè)小腳本主要支持批量轉(zhuǎn)換MarkdownPDF的功能:smile:

1.所需工具pandoc、wkhtmltopdf

  • wkhtmltopdf——是一個(gè)使用 Qt WebKit 引擎做渲染的喘沿,能夠把html 文檔轉(zhuǎn)換成 pdf 文檔 或 圖片(image) 的命令行工具奥帘。(強(qiáng)調(diào)一下:是 “命令行工具”

    1. 【下載請(qǐng)點(diǎn)擊這里】 【http://wkhtmltopdf.org/downloads.html】
    2. 設(shè)置環(huán)境變量
    3. 通過(guò)命令行: wkhtmltopdf -V檢驗(yàn)是否安裝成功
  • Pandoc——是一個(gè)由 John MacFarlane 開(kāi)發(fā)的通用文檔轉(zhuǎn)換工具骆莹,可以支持大量標(biāo)記語(yǔ)言之間的格式轉(zhuǎn)換,例如 Markdown 靶草、Microsoft Word蹄胰、PowerPoint、 Jupyter Notebook爱致、HTML烤送、PDF、LaTeX糠悯、Wiki帮坚、EPUB 格式之間的相互轉(zhuǎn)換。官方稱之為該領(lǐng)域中的“瑞士軍刀”互艾,并且給出了一個(gè)格式轉(zhuǎn)換的示意圖试和。

    Pandoc 可以自動(dòng)解析 Markdown 文件里的圖片鏈接,所以不論是本地存儲(chǔ)的圖片纫普,還是圖床上的圖片阅悍,都可以正確轉(zhuǎn)換并且顯示到 pdf 文件里。

2.文檔

采用之前很火”程序員菜譜”昨稼,其項(xiàng)目結(jié)構(gòu)為多層次的文件夾和markdown文件組成节视。

E:.
├─.github
│  └─workflows
├─dishes
│  ├─braised
│  │  └─紅燒肉
│  ├─breakfast
│  ├─condiment
│  ├─dessert
│  │  ├─提拉米蘇
│  │  └─烤蛋撻
│  ├─drink
│  │  └─百香果橙子特調(diào)
│  │      └─imgs
│  ├─home-cooking
│  │  ├─香干芹菜炒肉
│  │  ├─香菇滑雞
│  │  ├─雞蛋羹
│  │  └─黃油煎蝦
│  ├─semi-finished
│  │  └─速凍湯圓
│  ├─soup
│  │  ├─昂刺魚(yú)豆腐湯
│  │  └─西紅柿土豆燉牛肉
│  ├─staple
│  │  ├─pizza
│  │  ├─日式咖喱飯
│  │  ├─烙餅
│  │  └─老友豬肉粉
│  └─template
│      └─示例菜
└─tips
    ├─advanced
    └─learn

3.批量執(zhí)行腳本

  • 提供批量轉(zhuǎn)換功能
  • 文件夾嵌套處理
  • 統(tǒng)一導(dǎo)出到當(dāng)前目錄的./output/

md2pdf

直接采用Pandoc轉(zhuǎn)PDF的方法不太好使,所以采取了折中的方案:先將MarkdownPandoc轉(zhuǎn)換為HTML,然后再用wkhtmltopdf完成PDF轉(zhuǎn)換假栓。

Pandoc轉(zhuǎn)換為HTML幾乎完美寻行,但是需要補(bǔ)充HTML頭部以及CSS樣式等。所以前端大佬可以直接修改html_head.txt中的文件完善匾荆。

import pdfkit
import pypandoc
import os
from argparse import ArgumentParser


# 輸出目錄
OUTPUT_DIR = "output/"
os.makedirs(OUTPUT_DIR, exist_ok=True)


def get_file_name(mk_file_path, file_list, outlist):
    """找到mk_file_path路徑下的所有.md文件"""
    print(f'【{mk_file_path}】Markdown文件如下:')
    for root, dirs, files in os.walk(mk_file_path):
        for f in files:
            each = os.path.join(root, f)
            if ".md" in each:
                file_list.append(each)
                filename = each.replace('.md', '.pdf')
                f = filename.split("\\")[-1]
                outlist.append(os.path.join(OUTPUT_DIR, f))
    print('檢索完畢')
    print(f"一共有{len(outlist)}個(gè)文件, 分別為{outlist}")


def convert(input_file, output_file):
    pypandoc.convert_file(input_file, 'html', outputfile='tmp.html')
    html_head_file = open("html_head.txt", "r", encoding='utf-8')
    html_head = html_head_file.read()
    html_head_file.close()
    html_tail = "\n</body>\n</html>"
    html_body_file = open('tmp.html', "r", encoding='utf-8')
    html_body_txt = html_body_file.read()
    html_body_file.close()
    html_body = html_head + html_body_txt + html_tail
    # 先創(chuàng)建臨時(shí)的html文件
    with open('tmp.html', 'w', encoding='utf-8') as f:
        f.write(html_body)
        f.close()
    # 再將html文件轉(zhuǎn)成pdf文件
    pdfkit.from_file('tmp.html', output_file, options={"enable-local-file-access": None})
    if os.path.exists('tmp.html'):
        os.remove('tmp.html')
    print(input_file + '轉(zhuǎn)換成功拌蜘!')


def _init_argumentParser():
    a = ArgumentParser(usage="Markdown->PDF批量轉(zhuǎn)換助手")
    a.add_argument("-p", "--path", required=True, type=str, help="檢索路徑")
    return a.parse_args()


if __name__ == '__main__':
    # markdown文件路徑
    # mk_path = "HowToCook/dishes"
    args = _init_argumentParser()

    # 修改文件路徑List
    mk_file_list = []
    # 輸出文件路徑List
    output_pdf_file_list = []
    # 轉(zhuǎn)換失敗的文件
    failed = []

    # 獲得文件名
    get_file_name(args.path, mk_file_list, output_pdf_file_list)
    # 對(duì)文件進(jìn)行轉(zhuǎn)換
    for i in range(len(mk_file_list)):
        try:
            convert(mk_file_list[i], output_pdf_file_list[i])
        except Exception as e:
            print(f"{mk_file_list[i]} 出現(xiàn)了問(wèn)題 , 原因?yàn)? \n{e}")
            failed.append(mk_file_list[i])

    print(f"失敗的有{len(failed)}個(gè), {failed}")

Fork from : https://github.com/Dafeigy/md2pdf

demo-batch-markdown-to-pdf

from: 文章——如何把 Markdown 文件批量轉(zhuǎn)換為 PDF

from pathlib import Path
import os

work_dir = Path.cwd()

export_pdf_dir = work_dir / 'pdf'
if not export_pdf_dir.exists():
    export_pdf_dir.mkdir()

for md_file in list(work_dir.glob('*.md')):
    md_file_name = md_file.name
    pdf_file_name = md_file_name.replace('.md', '.pdf')
    pdf_file = export_pdf_dir / pdf_file_name
    cmd = "pandoc '{}' -o '{}' --pdf-engine=xelatex -V mainfont='PingFang SC' --template=template.tex".format(md_file, pdf_file)
    os.system(cmd)

:question:沒(méi)運(yùn)行成功

附錄

問(wèn)題解決

IOError: No wkhtmltopdf executable found: “”

python使用pdfkit中杆烁,如果使用pdfkit.from_url 或者pdfkit.from_string等,就會(huì)出現(xiàn)上述錯(cuò)誤简卧。而且如果你使用pip安裝了 wkhtmltopdf兔魂,還是會(huì)出現(xiàn)這個(gè)問(wèn)題:

IOError: No wkhtmltopdf executable found: “”
  1. 因此需要去安裝windows版本的*wkhtmltopdf*此處進(jìn)入下載網(wǎng)址
  2. 安裝完成之后添加環(huán)境變量后举娩,再運(yùn)行即可

pandoc報(bào)錯(cuò)

解決方案: pypandoc 轉(zhuǎn)換html 為word 報(bào)錯(cuò)

No pandoc was found: either install pandoc and add it to your PATH or or call pypandoc.download_pandoc(...) or install pypandoc wheels with included pandoc.

參考了資料 關(guān)于python用pypandoc問(wèn)題(python3)(探索ing)_曉星晨曦-CSDN博客_pypandoc未能解決析校,后面版本安裝,指定pypandoc用的版本1.6.3晓铆,可行勺良。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市骄噪,隨后出現(xiàn)的幾起案子尚困,更是在濱河造成了極大的恐慌,老刑警劉巖链蕊,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件事甜,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡滔韵,警方通過(guò)查閱死者的電腦和手機(jī)逻谦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)陪蜻,“玉大人邦马,你說(shuō)我怎么就攤上這事⊙缏簦” “怎么了滋将?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)症昏。 經(jīng)常有香客問(wèn)我随闽,道長(zhǎng),這世上最難降的妖魔是什么肝谭? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任掘宪,我火速辦了婚禮,結(jié)果婚禮上攘烛,老公的妹妹穿的比我還像新娘魏滚。我一直安慰自己,他們只是感情好坟漱,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布栏赴。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪须眷。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天沟突,我揣著相機(jī)與錄音花颗,去河邊找鬼。 笑死惠拭,一個(gè)胖子當(dāng)著我的面吹牛扩劝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播职辅,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼棒呛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了域携?” 一聲冷哼從身側(cè)響起簇秒,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秀鞭,沒(méi)想到半個(gè)月后趋观,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡锋边,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年皱坛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片豆巨。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡剩辟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出往扔,到底是詐尸還是另有隱情贩猎,我是刑警寧澤,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布瓤球,位于F島的核電站融欧,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏卦羡。R本人自食惡果不足惜噪馏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绿饵。 院中可真熱鬧欠肾,春花似錦、人聲如沸拟赊。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)吸祟。三九已至瑟慈,卻和暖如春桃移,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背葛碧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工借杰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人进泼。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓蔗衡,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親乳绕。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绞惦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容