【Python】Python-Markdownでマークダウン記法をHTMLに変換する


投稿日 2021年2月19日 >> 更新日 2023年3月1日

今回はPython外部ライブラリのPython-Markdownを使用してマークダウンで記述した記号をHTMLに変換を行う実装をしていきます。

HTMLはご存知の通りブラウザを通して様々な表現を表すために使用されるマークアップ言語の1つです。

サイトのページはもちろんの事、ブログを書くためのエディターでもHTMLを使うことによって特定の文章を強調表示させることができます。

例えば見出しでよく使われる「<h1>」や「<h2>」というHTMLのタグがありますが、マークダウンで記述すると「#=<h1>」と「##=<h2>」という風に書くことができ、その記号はそれぞれのタグに変換されてサイトのページに表示されます。

Python-Markdownでは機能を拡張することによって様々なHTMLへの変換及びCSSの属性を操作することができるので大変高機能なライブラリです。

この記事では拡張機能の実装は行いませんが、デフォルトでどの程度のマークダウンを記述できるか一つ一つ見ていきます。

拡張機能に関しては以下の記事をご参照ください。

実行環境&使用ライブラリ

実行環境
WIndows Subsystem for Linux
Python 3.6.9
pip 9.0.1
使用ライブラリ ライセンス
bottle==0.12.19 MIT
Markdown==3.3.3 BSD

BottleでMarkdownの結果をブラウザで表示する

PythonインタープリターやJupyter notebookで実装する場合はマークダウンの記述がそのままHTMLタグの文字列として受け取るため、どのような表現がされているか確認したい場合があります。

そこで、軽量なWebフレームワークのBottleを使用して、逐次結果を表示できるアプリを作成します。

不要な方は読み飛ばしてください。

非常に簡単で、慣れれば秒で構築できるのでお勧めです。

まずは必要なライブラリをpipインストールします。

$ pip install bottle markdown

インストールが終わったら、「bottle.py」以外の名前のPythonファイルを作成して以下のように記述します。

# bottle_1.py

from bottle import route, run
import markdown


# マークダウンで記述されたテキストファイル
# カレントディレクトリにあるtext.txtを読み込む
with open('text.txt', 'r', encoding='utf-8') as file:
    text = file.read()


@route('/')
def home():
    html = markdown.markdown(text) # HTMLに変換後
    return '<h1 style="color: red;">HTMLに変換後</h1>{}'.format(html)


# ローカルのサーバーを設定
run(host='localhost', port=8000)

あとは上記の「open()」関数に定義しているファイル名と同じテキストファイル「text.txt」を作成します。

「text.txt」の中身は、「#」によるマークダウンを記述した以下のような内容です。

# Hello World 1
## Hello World 2
### Hello World 3
#### Hello World 4

これで「bottle_1.py」を起動するだけでマークダウンで記述された結果をブラウザ上で表示することができます。

$ python3 bottle_1.py
Bottle v0.12.19 server starting up (using WSGIRefServer())...
Listening on http://localhost:8000/
Hit Ctrl-C to quit.

上記のように起動されたら、お使いのブラウザに「localhost:8000」もしくわ「127.0.0.1:8000」を打ち込むと以下のように表示されるはずです。

※GoogleChromeのデベロッパーツールを開いています。

マークダウンの記述は「text.txt」に書き込んで、Bottleアプリをリロードすれば読み込まれるのでぜひ試してみて下さい。

Python-Markdownの実装

Python-Markdownのライブラリはpipでインストールすることができます。

pip install markdown

公式ドキュメントはこちらです。

インストールが完了したら、基本操作を実装していきます。

Python-Markdownの基本操作

Python-Markdownではデフォルトで設定されているマークダウン記法と拡張機能により追加されるマークダウン記法があります。

デフォルト設定はそのままstr型のオブジェクトを「markdown.markdown(text)」関数の第一引数に渡せばHTMLへと変換することができます。


import markdown


text = """
# Hello World 1
## Hello World 2
### Hello World 3
#### Hello World 4
"""

html = markdown.markdown(text)

print(html)
<h1>Hello World 1</h1>
<h2>Hello World 2</h2>
<h3>Hello World 3</h3>
<h4>Hello World 4</h4>

他の方法としては、「markdown.Markdown()」クラスを一度初期化してから、「convert()」メソッドでHTMLに変換することができます。


import markdown


text = """
# Hello World 1
## Hello World 2
### Hello World 3
#### Hello World 4
"""

#html = markdown.markdown(text)
md = markdown.Markdown()
html = md.convert(text)

print(html)
<h1>Hello World 1</h1>
<h2>Hello World 2</h2>
<h3>Hello World 3</h3>
<h4>Hello World 4</h4>

上記は「markdown.markdown()」関数を実行した手順を手動で実行しているに過ぎないので、この記事では手間を省くために最初に行った実装でHTML化します。

デフォルトで使用できるマークダウン

デフォルトで使用できるマーダウンというのは、「markdown.markdown(text, extensions)」の第二引数「extensions」にPython-Markdownが元々備えている拡張機能を設定しない場合を指します。

尚、ここでの実装は私の知っている限りのマークダウン記法を元に試してみた結果なので、網羅しているという方はデフォルト値でどこまで記述できるか試してみて下さい。

拡張機能「その1」のマークダウン一覧はこちらです。

※デフォルトの場合

内容 マークダウン(半角記号) HTML(頭タグ)
見出し #...
##...
<h1>
<h2>
番号付きリスト 1.
2.
<ol>
<li>...
<li>...
リスト - ...
- ...

* ...
* ...
<ul>
<li>...
<li>...
引用 > ... <blockquote><p>
太文字 **...**
__...__
<p><strong>
斜体 *...*
_..._
<p><em>
水平線 ---
***
<hr />
脚注 内容→[リンク先]
[リンク先]:/path
<p>内容<a href="/path">リンク先
インライン `code' <p><code>
リンク [リンク](/path/) <p>リンク<a href="/path/">
画像 ![内容](/img) <p><img alt="内容" src="/img" />
エスケープ \# <p>#

見出し

見出しは段落の1列目にシャープ(#)を添えることによって「<h1>」や「<h2>」のタグで結果を表示できます。


text = """
# 見出し1
## 見出し2
### 見出し3
#### 見出し4
##### 見出し5
"""

html = markdown.markdown(text)
print(html)
<h1>見出し1</h1>
<h2>見出し2</h2>
<h3>見出し3</h3>
<h4>見出し4</h4>
<h5>見出し5</h5>

番号付きリストとリスト

番号付きリストでは段落の1列目に番号とドット(1.や2.)を組み合わせることで「<ol><li>」によるタグの結果を表示できます。


text = """
1. 番号付きリスト1
2. 番号付きリスト2
3. 番号付きリスト3
4. 番号付きリスト4
5. 番号付きリスト5
"""

html = markdown.markdown(text)
print(html)
<ol>
<li>番号付きリスト1</li>
<li>番号付きリスト2</li>
<li>番号付きリスト3</li>
<li>番号付きリスト4</li>
<li>番号付きリスト5</li>
</ol>

リストの場合は段落の1列目にハイフンもしくはアステリスク(「-」や「*」)を添えることで「<ul><li>」によるタグの結果を表現します。


text = """
- リスト1
    - リスト1.2
        - リスト1.3

- リスト2
- リスト3
"""

html = markdown.markdown(text)
print(html)
<ul>
<li>
<p>リスト1</p>
<ul>
<li>リスト1.2<ul>
<li>リスト1.3</li>
</ul>
</li>
</ul>
</li>
<li>
<p>リスト2</p>
</li>
<li>リスト3</li>
</ul>

引用

引用は段落1列目に不等号(>)を添えることで「<blockquote>」のタグで結果が表示されます。


text = """
> 引用1
>> 引用2
>>> 引用3
>>>> 引用4
>>>>> 引用5
"""

html = markdown.markdown(text)
print(html)
<blockquote>
<p>引用1</p>
<blockquote>
<p>引用2</p>
<blockquote>
<p>引用3</p>
<blockquote>
<p>引用4</p>
<blockquote>
<p>引用5</p>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>

太文字と斜体

太文字は、ターゲットの文字列の両脇にアステリスク2個(**...**)もしくはダブルアンダースコア(__...__)を添えることで「<strong>」のタグで結果を表示します。


text = """
**太文字**

__太文字2__
"""

html = markdown.markdown(text)
print(html)
<p><strong>太文字</strong></p>
<p><strong>太文字2</strong></p>

斜体は、ターゲットの文字列の両脇にアステリスク1個(*...*)もしくはアンダースコア(_..._)を添えることで「<em>」のタグで結果を表示します。


text = """
*Italic*

_Italic_
"""

html = markdown.markdown(text)
print(html)
<p><em>Italic</em></p>
<p><em>Italic</em></p>

水平線

水平線は段落の1列目にハイフン3つ以上(---)もしくはアステリクス3つ以上(***)を添えることで「<hr />」のタグで結果を表示します。

※文字列のある2段落目でハイフンを3つ以上添えると上段の文字列が「<h2>」のタグで囲まれてしまうので注意してください。


text = """
1
***

2
---

3
- - -

4
----

---

"""

html = markdown.markdown(text)
print(html)
<p>1</p>
<hr />
<h2>2</h2>
<p>3</p>
<hr />
<h2>4</h2>
<hr />

脚注

脚注と言われたり注釈と言われたりしますが、双方微妙に意味が異なるので、ここでは脚注と呼びます。

脚注は、脚注したい文章中に角括弧([...])で注意書きを挟み、他の段落で同じ注意書きされた角括弧にコロン(:)と参照先のパスを追加([...]:path)することによって、「意味<a href="path">脚注</a>」のようなタグで結果が表示されます。


text = """
プログラミングにおいてPython[※1]はバックエンドで、HTML[※2]はフロントエンドです。

[※1]:/path/python
[※2]:/path/html
"""

html = markdown.markdown(text)
print(html)
<p>Python<a href="/path/python">※1</a>はバックエンドです。
HTML<a href="/path/html">※2</a>はフロントエンドです。</p>

インライン

インラインは、文章中の強調表示したい文字列をバッククォート(`)で囲むことにより「<code>」のタグで結果を表示します。

クォート(')と間違えることがあるので注意しましょう。


text = """
文章中に`code`をインラインする
"""

html = markdown.markdown(text)
print(html)
<p>文章中に<code>code</code>をインラインする</p>

リンクと画像

リンクは文章中に角括弧([...])で文字列を挟み、括弧((...))内にリンク先のURLを充てることで「<a href="...">」のタグで結果を表示します。


text = """
意味は[こちらです](/path/)。
"""

html = markdown.markdown(text)
print(html)
<p>意味は<a href="/path/">こちらです</a>。</p>

画像は文章中にリンク記法の頭にビックリマーク(![...](...))を添えることで「<img alt="..." src="...">」のタグで結果を表示します。


text = """
![画像](/path/img)
"""

html = markdown.markdown(text)
print(html)
<p><img alt="画像" src="/path/img" /></p>

エスケープ

エスケープは、マークダウン記法を通常の記号として表したい記号の手前でバックスラッシュ(\)を添えることでHTML化を無効にできます。

※Windowsの場合は円マーク


text = """
\# マークダウンのエスケープ
"""

html = markdown.markdown(text)
print(html)
<p># マークダウンのエスケープ</p>

Python-Markdownの拡張機能について

拡張機能については別の記事でご紹介しているので、以下の記事をご参照ください。

それでは以上となります。

最後までご覧いただきありがとうございました。