【Pythonブログ投稿自動化】画像パスの修正

ブログ

今回の内容

今回は、フォルダ構造変更により、ファイルを移動した場合、画像の参照パスが変わってしまう問題の解決方法を考えたいと思います。
VSCodeのマークダウンへの画像貼り付けの場合、パスは相対パスでの貼り付けになってしまいます。
そのため、マークダウンファイルを、別のフォルダに移動した場合、パスが変わってしまい、画像へのリンクが無効になってしまいます。
本来は、貼り付けを絶対パスにできれば解決できるのですが、その方法は見つかりませんでした。

解決策1:Paste Imageを使う

VSCodeにデフォルトで画像貼り付け機能が導入されるまでは、Markdownに画像を貼り付ける方法として、Paste Imageが便利でした。Paste Imageは絶対パスでの貼り付けが可能なため、マークダウンファイルを移動しても画像はそのままのフォルダに保存したいという場合には、Paste Imageの利用がおすすめです。
Paste Imageの使い方は以下の記事で紹介しています。

解決策2:Pythonスクリプトなどを使って、パスを書き換え

もう一つの解決策は、Pythonなどでマークダウンファイルを読み込んで、パスを書き換える方法です。
この場合は、あらかじめ、画像の保存先のルートディレクトリは決まっている必要がありますが、フォルダ構造に応じて画像ファイルを移動することも可能です。

import re
md_base_path = 'マークダウンファイル群を管理しているフォルダーのパス'
img_base_path = '画像を管理しているフォルダーのパス'
def update_img_path(md_file_path):
    with open(md_file_path, 'r', encoding='utf-8') as file:
        content = file.read()

    img_new_folder = os.path.dirname(md_file_path).replace(md_base_path, img_base_path)


    # 画像パスの正規表現
    img_pattern = re.compile(r'!\[(.*?)\]\((.*?)\)')

    def replace_image_path(match):
        alt_text = match.group(1)
        img_path = match.group(2)

        # 画像ファイル名を取得
        img_name = os.path.basename(img_path)
        if img_path[:4]=='http':
            return f'![{alt_text}]({img_path})'
        if 'G:/' in img_path:
            # 絶対パスから相対パスへ変換
            original_img_path = img_path.replace('G:/','/workspaces/')
            new_img_path = os.path.join(img_new_folder, img_name)
        else:
            # 相対パスを絶対パスに変換してから新しいパスへ移動

            original_img_path = img_base_path + img_path.split('/images/', 1)[-1]

            new_img_path = os.path.join(img_new_folder, img_name)
        # 画像ファイルが存在する場合は移動
        if os.path.exists(original_img_path):
            new_img_dir = os.path.dirname(new_img_path)
            if not os.path.exists(new_img_dir):

                os.makedirs(new_img_dir, exist_ok=True)
            if original_img_path != new_img_path:
                shutil.move(original_img_path, new_img_path)

        # 新しい相対パスに書き換え
        relative_new_img_path = os.path.relpath(new_img_path, start=os.path.dirname(md_file_path))
        new_path = f'![{alt_text}]({relative_new_img_path})'

        return new_path
    new_content = img_pattern.sub(replace_image_path, content)

    # 更新された内容でファイルを上書き
    with open(md_file_path, 'w', encoding='utf-8') as file:
        file.write(new_content)
md_file_path = "file path"
update_img_path(md_file_path)

例えば、以下のようなフォルダ構造を考えます

  • blog
  • category1
    • category1-1
    • article1.md
  • category2
  • images
  • category1
    • category1-1
  • category2

この時、article1.mdをcategory1からcategory1-1に移動したとします。画像をimages/category1に保存していた場合、パスが変わってしまいます。

そこで、imagesと、blogをbaseのパスとしてとらえることで、パスを書き換え、category1に保存していた画像は、category1-1に移動します。

この例の場合は、パスを以下のようにします。

md_base_path = 'blog/'
img_base_path = 'images/'
md_file_path = "blog/category1/category1-1/article1.md"

この設定を行い、update_img_path(md_file_path)を実行することで、パスの書き換えと、ファイル移動が可能です。

ファイルを書き換える処理になるので、きちんと実行できることが確認できるまではバックアップを念のため取ってから実行してください。

このような処理をするのは面倒と思う場合には、
画像貼り付けはPaste Imageで行うか、記事はすべて一つのフォルダで管理し、csvもしくは、記事の上部にカテゴリ情報が記述するようにする方法がおすすめです。

タイトルとURLをコピーしました