WordPress記事をmarkdownifyでAstroに移行する方法と詰まりどころ

WordPressからAstroへの移行で一番時間を食うのは、記事の変換だ。エクスポートしたHTMLをそのままAstroに持ち込んでも動かない。markdownifyでMarkdownに変換する方法と、実際に詰まった箇所をまとめる。

markdownifyで変換する基本の流れ

WordPressのエクスポートは「ツール → エクスポート → すべてのコンテンツ」でXMLが出る。このXMLから各記事のHTMLを取り出し、markdownifyでMarkdownに変換するのが基本の流れだ。

import xml.etree.ElementTree as ET
from markdownify import markdownify as md
tree = ET.parse('wordpress.xml')
root = tree.getroot()
for item in root.iter('{http://wordpress.org/export/1.2/}post_content'):
html = item.text or ''
markdown = md(html, heading_style='ATX')
print(markdown)

markdownifyはHTMLをMarkdownに変換するPythonライブラリで、pip install markdownify で入る。heading_style='ATX' を指定すると ## 見出し 形式になる。指定しなければSETEXTスタイル(=== の下線)になって、Astroのレンダラーで崩れることがある。

frontmatterを自動生成する

Astroの記事には title / pubDate / category / slug などのfrontmatterが必要だ。WordPressのXMLにはこれらの情報が含まれているので、変換スクリプトで一緒に生成できる。

title = item.find('title').text or '無題'
pub_date = item.find('{http://wordpress.org/export/1.2/}post_date').text[:10]
slug = item.find('{http://wordpress.org/export/1.2/}post_name').text or pub_date
frontmatter = f"""---
title: "{title}"
pubDate: "{pub_date}"
category: "Tech"
tags: []
slug: "{slug}"
description: ""
---
"""

スラッグが空のケースがある。下書きのまま放置された記事はpost_nameが空になっていることが多い。その場合は日付をそのままスラッグにしてしまうのが手っ取り早い。

詰まりどころ①:文字化けと特殊文字

日本語の記事では   … & などのHTMLエンティティが残ることがある。markdownifyは基本的なエンティティを変換するが、漏れるものがある。変換後に html.unescape() を通すと大半は解消する。

import html
markdown_clean = html.unescape(markdown)

もうひとつ詰まるのが全角スペースだ。WordPressで記事を書くとき、インデント目的で  (U+3000)を使っているケースがある。Markdownでは意味を持たないが、Astroのビルド時にレイアウトが崩れることがある。正規表現で除去しておくのが無難だ。

詰まりどころ②:改行の扱い

WordPressの旧エディタ(クラシックエディタ)で書かれた記事は、<br> タグで改行が入っている。markdownifyはこれを \ に変換するが、Astroのレンダラーによっては \ が表示されてしまう。

convert_br=False は使えないので、変換後に置換するのが現実的だ。

markdown = markdown.replace('\\\n', '\n')

Gutenbergで書かれた記事は <p> タグ区切りなので、この問題は起きにくい。旧エディタ記事が多い場合は特に注意が必要だ。

WordPress移行は「昔の記事が動かない」が本番

スクリプト自体はすぐ動く。本番の作業時間を食うのは、2015〜2020年頃に書かれた古い記事のレイアウト修正だ。当時のWordPressテーマに依存したHTMLが混ざっていて、変換後に崩れる。全記事をチェックするよりも、PVのある記事を優先して手動修正するほうが費用対効果が高い。

Astroに移してしまえば、記事の管理がシンプルになる。ビルドが速く、MarkdownファイルをGitで管理できる状態になるのが一番大きい。移行作業そのものは地味だが、終わった後の快適さは本物だ。