PythonでObsidianのwikiリンクを標準Markdownに一括変換する
Obsidianで書いたMarkdownを他のプラットフォームに持っていくとき、二重角カッコのwikiリンクと画像リンクが標準Markdownと違うので表示が崩れます。フォルダを選ぶだけで配下のmdファイルをまとめて標準Markdown形式に書き換えるPythonスクリプトの全文と、正規表現の中身の解説、実際に変換したときの画面をまとめました。標準ライブラリだけで動きます。
はじめに
今回は、ObsidianのMarkdownファイルを他のプラットフォーム用に変換するツールを作る方法をご紹介します。
「Obsidianで書いた記事をZennやQiitaに投稿したいけど、画像リンクやWikiリンクの形式が違うから手作業で直すのが大変…」
ほとんどの人はそんな経験はないと思いますが、私はまさにこの問題に直面したので、解決するためのPythonツールを紹介します。
ちなみに、Obsidianの設定でwikiリンク化をオフにしていれば、この問題は発生しません。
Obsidianと標準Markdownの違い
以下のようにObsidianと標準Markdownではリンク形式が異なる部分があります。
この違いを自動で変換するツールを作ります。
Obsidianの画像リンク形式
![[cute_cat.png]]
標準的なMarkdownの画像リンク形式

Obsidianのwikiリンク形式
[[マイページ]]
標準的なMarkdownのリンク形式
[マイページ](マイページ.md)
コード全文
作成したコードはこちらです。
標準ライブラリだけで作成しているので、コピペで使えると思います。
import os
import re
import tkinter as tk
from tkinter import filedialog
import tkinter.messagebox as messagebox
def convert_links(folder_path):
# 画像リンクのパターン(画像は.mdを付けない)
image_pattern = r'!\[\[(.+?)\]\]'
image_replacement = r''
# 通常のWikiリンクのパターン(.mdを付ける)
wiki_pattern = r'\[\[(.+?)\]\]'
wiki_replacement = lambda m: f'[{m.group(1)}]({m.group(1)}.md)'
for root, dirs, files in os.walk(folder_path):
for file in files:
if file.endswith('.md'):
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 画像リンクを先に変換
new_content = re.sub(image_pattern, image_replacement, content)
# 通常のWikiリンクを変換(.mdを付ける)
new_content = re.sub(wiki_pattern, wiki_replacement, new_content)
if new_content != content:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(new_content)
print(f"変換完了: {file_path}")
except Exception as e:
print(f"エラー発生 {file_path}: {str(e)}")
def select_folder():
root = tk.Tk()
root.withdraw() # メインウィンドウを表示しない
folder_path = filedialog.askdirectory(title="変換するマークダウンファイルを含むフォルダを選択してください")
if folder_path:
try:
convert_links(folder_path)
messagebox.showinfo("完了", "すべてのマークダウンファイルの変換が完了しました。")
except Exception as e:
messagebox.showerror("エラー", f"変換中にエラーが発生しました: {str(e)}")
else:
messagebox.showwarning("警告", "フォルダが選択されませんでした。")
if __name__ == "__main__":
select_folder()
リンク変換
ポイントとなるのはこの部分です。
この部分では正規表現を使って、変換前と変換後の文字列を指定しています。
def convert_links(folder_path):
# 画像リンクのパターン(画像は.mdを付けない)
image_pattern = r'!\[\[(.+?)\]\]'
image_replacement = r''
# 通常のWikiリンクのパターン(.mdを付ける)
wiki_pattern = r'\[\[(.+?)\]\]'
wiki_replacement = lambda m: f'[{m.group(1)}]({m.group(1)}.md)'
画像リンクの場合は、探すパターンが image_pattern = r'!\[\[(.+?)\]\]' です。
![[… Obsidianの画像リンクの始まりを表します(.+?)… ファイル名を取り出す部分です(例:cute_cat.png)]]… Obsidianの画像リンクの終わりを表します
置き換える側は image_replacement = r'' です。
![\1]… 標準Markdownの画像タイトル部分です(\1)… ファイルパス部分です
Wikiリンクの場合は、探すパターンが wiki_pattern = r'\[\[(.+?)\]\]' です。
[[… Wikiリンクの始まりです(.+?)… リンクテキストを取り出す部分です]]… Wikiリンクの終わりです
置き換える側は wiki_replacement です。
- リンクテキストを取り出して
- 標準的なMarkdownのリンク形式に変換し
.md拡張子を追加します
使い方の手順
それでは実際にこのコードを使ってみましょう。
今回はこのデモファイルを変換してみます。
wikiリンク変換デモ.md
# 日本の伝統文化
[[茶道]]は、日本を代表する伝統文化の一つです。[[千利休]]によって大成された茶道は、[[侘茶]]の精神を重視します。
![[sado-japan.jpg]]
このマークダウンファイルは以下の「wikiリンク変換」というフォルダに保存してあり、

中身はこのようになっています。

ここにすべてのファイルが保存してあるので、正しくリンクが貼られていればきちんと表示されるはずですが、この文章をVSCodeでプレビュー表示してみると、このようになります。

リンクが変換されずにそのままになっていますね。
コード実行
それではコードを実行していきます。
コードを実行するとフォルダ選択を求められるので、「wikiリンク変換」のフォルダを選択します。
変換が完了すると以下のポップアップが表示されます。

また、以下のような出力が出ていれば実行完了です。
変換完了: C:/your_directory/wikiリンク変換\wikiリンク変換デモ.md
それでは変換後のファイルを見てみましょう。
# 日本の伝統文化
[茶道](茶道.md)は、日本を代表する伝統文化の一つです。[千利休](千利休.md)によって大成された茶道は、[侘茶](侘茶.md)の精神を重視します。

このようにwikiリンクが変換されていれば成功です。
プレビューを見てみると、

このように画像がきれいに表示されています。
また、「茶道」「千利休」「侘茶」というリンクもクリックできるようになっており、例えば「茶道」をクリックすると、以下のように 茶道.md を表示することができます。

まとめ
いかがでしたか。
今回は、Obsidianのwikiリンクと画像リンクを、標準Markdownの形式に一括変換するPythonスクリプトをご紹介しました。
やることは、フォルダを選んで実行するだけです。
選んだフォルダの配下にあるmdファイルを順に開いて、画像リンクを先に、通常のwikiリンクを後に置き換えて上書き保存します。
このスクリプトが必要になる場面はなかなか無いと思いますが、Obsidianの記事を外部に持ち出したくなったときに思い出していただければと思います。
この記事が誰かの役に立てばうれしいです。
参考
数式(LaTeX)まわりの変換で困ったら、こちらの記事もどうぞ。
プログラミング
noteで数式を書く方法|インライン・複数行の記法とObsidianから転載するときの変換ルール
noteの数式記法の書き方をまとめました。noteの数式はKaTeXベースのTeX記法ですが、インラインは「ドル2つ+波カッコ」というnote独自の合図で、標準のMarkdownとずれています。インライン・複数行それぞれの書き方と使える場所、Obsidianなどから転載するときの書き換えルール3つ、表示されないときのトラブルシューティングを載せています。