2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

お題は不問!Qiita Engineer Festa 2023で記事投稿!

【Python】マークダウン形式のファイルをPDF形式のファイルに変換する

Posted at

本記事の題名の通り、Markdown形式のファイルをPDF形式のファイルに変換する方法を調べたので、その備忘録をこちらに残します。
今回使用したのはPythonで、使用したライブラリなどは以下の通りです。

requirements.txt
Python 3.11.1
beautifulsoup4==4.11.2
Markdown==3.4.3
pdfkit==1.0.0

使用用途は以下の通り:

  • beautifulsoup4はMarkdown形式のファイルを一度HTMLに変換した際に、HTMLのフォーマットを整形する際に使用
  • MarkdownはMarkdown形式のファイルの中身をHTMLに変換した文字列に変換するために使用
  • pdfkitはHTML形式のファイルをPDF形式のファイルに変換するために使用

さらに、pdfkitでHTMLからPDFへの変換を行う際に、wkhtmltopdfを内部的に使用しているためこちらのインストールも必要です。

また、本記事を書くにあたり参考にした記事が以下の通りです。

1つ目の記事をよく参考にさせていただきました。2つ目の記事についてはHTMLからPDFに変換する際に生じたエラーを調べた際にたどり着いたものです。

本記事は以下の構成で紹介します。

  1. MarkdownをHTMLに変換
  2. HTMLをPDFに変換
  3. MarkdownからPDFまで一気に変換
  4. まとめ

1. MarkdownをHTMLに変換

Markdownファイルは拡張子*.mdで作成することができます。ここではサンプルとして、sample.mdとします。

sample.md
# Markdown sample
* list1
* list2
* list3

Pythonによりこのファイルを読み取り、markdown#markdownによりHTML形式のテキストに変換します。
以下にサンプルコードを記載(Pythonコードと同階層に作成した場合を仮定。):

from markdown import markdown

with open("sample.md", mode="r", encoding="utf-8") as f:
    html_content = markdown(f.read())
with open("sample.html", mode="w", encoding="utf-8") as w:
    w.write(html_content)
sample.html
<h1>Markdown sample</h1>
<ul>
<li>list1</li>
<li>list2</li>
<li>list3</li>
</ul>

2. HTMLをPDFに変換

1.の工程まででMarkdown形式のファイルからHTML形式のファイルsample.htmlを作成することができました。
次に、HTML形式のファイルからPDF形式のファイルを作ります。そのためにpdfkitを使用します。ここで、注意点としてwkhtmltopdfがインストール済みであることを仮定します。環境変数を設定していない場合は、どこにインストールされているかを明示的に設定する必要があります。インストール手順に沿っていった場合は、

ENV_PATH = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe' 

にインストール済みとなっているかと思います。
ここまで確認ができれば、後は変換のプロセスのみです。HTMLを変換する際に

  1. ファイルから作成する pdfkit#from_file
  2. URLから作成する pdfkit#from_url
  3. テキストから作成する pdfkit#from_string

のオプションがありますが、今回はついでにHTMLファイルを作成したので1つ目のメソッドを使用しました。
pdfkit#from_fileを用いて、次のように変換を行います:

from pdfkit import configuration, from_file

# pdfkitライブラリを使用するために「wkhtmltopdf」が必要
ENV_PATH = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe' 
config = configuration(wkhtmltopdf = ENV_PATH)
from_file("sample.html","sample.pdf",configuration =config)

ここで先ほど注意した、wkhtmltopdfの場所をメソッド内で指定することをお忘れなく。
こちらのコードを実行し、同階層にsample.pdfがあれば成功です。

3. MarkdownからPDFまで一気に変換

1.と2.で行ったことをまとめ、それに加えてMarkdown内でコードが記載されていた場合に、シンタックスハイライトが付くように設定しました。シンタックスハイライトにはCDNを使用しており、HTML内で以下のタグを追加しています。詳しくはこちらを参照のこと。

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>

さて、雑ではありますが最終的な成果物がこちらです:

from pdfkit import configuration, from_file
from markdown import markdown
from bs4 import BeautifulSoup

# pdfkitライブラリを使用するために「wkhtmltopdf」が必要
ENV_PATH = r'C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe' 
config = configuration(wkhtmltopdf = ENV_PATH)
options = {
    'margin-top': '0.2in',
    'margin-right': '0.2in',
    'margin-bottom': '0.2in',
    'margin-left': '0.2in',
    'encoding': "UTF-8",
    'enable-local-file-access': '',
}

def html_formatting(html_content):
    html_text = ''
    html_text += '<html lang="ja"><meta charset="utf-8"><body>'
    html_text += '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/default.min.css">'
    html_text += '<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>'
    html_text += '<script>hljs.highlightAll();</script>'
    html_text += html_content
    html_text += '</body></html>'
    soup = BeautifulSoup(html_text, "html.parser")
    return soup.prettify()

def markdown_to_pdf(input_file, output_file):

    with open(input_file, mode="r", encoding="utf-8") as f:
        html_content = markdown(f.read(), extensions=["extra", "nl2br", "toc", "smarty"]) # md to html string
        html_text = html_formatting(html_content)
        output_html = f"{output_file}_html.html"
        output_pdf = f"{output_file}_pdf.pdf"
        with open(output_html, "w", encoding="utf-8") as w:
            w.write(html_text)
        from_file(output_html,output_pdf,configuration =config, options=options) # html to pdf


if __name__ == "__main__":
    markdown_file = "flet.md"
    pdf_file = 'test' 
    markdown_to_pdf(markdown_file, pdf_file)

このコードではMarkdownファイルからHTMLおよびPDFファイルをそれぞれ出力します。

4. まとめ

MarkdownからHTMLおよびPDFファイルを出力するコードを作成することができましたが、内でのCDNがPDFでは反映されていないようなので、今後の課題として残っています。
いつか修正します。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?