Script Python pour convertir des posts Wordpress en Markdown
J’ai utilisé ce script pour convertir les anciens posts techoverflow.net basés sur Wordpress au format Markdown pour une utilisation avec Hugo. Il utilise les bibliothèques beautifulsoup4 et markdownify pour analyser le contenu HTML et le convertir en Markdown.
Partie 1 : Récupérer les catégories Wordpress
wp_to_md_part1.py
#!/usr/bin/env python3
from tqdm import tqdm
import requests
import json
import base64
import os
URL = "https://myblog.com"
USER = "uli"
PASSWORD = os.environ.get("WORDPRESS_API_PASSWORD")
if PASSWORD is None:
raise ValueError("WORDPRESS_API_PASSWORD environment variable is not set")
# Calculer l'en-tête d'authentification basic
auth_header = b"Basic " + base64.b64encode(f"{USER}:{PASSWORD}".encode("utf-8"))
def page_numbers():
"""Générateur infini de numéros de page"""
num = 1
while True:
yield num
num += 1
categories = []
for page in tqdm(page_numbers()):
# Récupérer les [pagesize=10] catégories suivantes
categories_page = requests.get(f"{URL}/wp-json/wp/v2/categories", params={"page": page, "per_page": 100, "context": "edit"},
headers={"Authorization": auth_header}).json()
# Vérifier le code d'erreur "dernière page"
if not len(categories_page):
break
# Pas de code d'erreur -> ajouter les catégories
categories += categories_page
with open("categories.json", "w") as outfile:
json.dump(categories, outfile)Partie 2 : Récupérer les posts WordPress
wp_to_md_part2.py
#!/usr/bin/env python3
from tqdm import tqdm
import requests
import json
import base64
import os
URL = "https://techoverflow.net"
USER = "uli"
PASSWORD = os.environ.get("WORDPRESS_API_PASSWORD")
if PASSWORD is None:
raise ValueError("WORDPRESS_API_PASSWORD environment variable is not set")
# Calculer l'en-tête d'authentification basic
auth_header = b"Basic " + base64.b64encode(f"{USER}:{PASSWORD}".encode("utf-8"))
def page_numbers():
"""Générateur infini de numéros de page"""
num = 1
while True:
yield num
num += 1
posts = []
for page in tqdm(page_numbers()):
# Récupérer les [pagesize=10] posts suivants
posts_page = requests.get(f"{URL}/wp-json/wp/v2/posts", params={"page": page, "per_page": 100, "context": "edit"},
headers={"Authorization": auth_header}).json()
# Vérifier le code d'erreur "dernière page"
if isinstance(posts_page, dict) and posts_page["code"] == "rest_post_invalid_page_number": # Dernière page trouvée
break
# Pas de code d'erreur -> ajouter les posts
posts += posts_page
with open("posts.json", "w") as outfile:
json.dump(posts, outfile)Partie 3 : Convertir les posts sauvegardés en Markdown
wp_to_md_part3.py
#!/usr/bin/env python3
import requests
import json
import re
import os
import os.path
import markdownify
from datetime import datetime
with open("posts.json") as infile:
posts = json.load(infile)
with open("categories.json") as infile:
categories = json.load(infile)
category_map = {category["id"]: category["name"] for category in categories}
def code_language_callback(elem):
lang = elem.attrs.get("data-enlighter-language", "")
filename = elem.attrs.get("data-filename", None)
return lang
def export_post(the_post):
title = the_post["title"]["raw"]
escaped_title = title.replace("\\", "\\\\").replace('"', '\\"')
slug = the_post["slug"]
slug = re.sub(r"%[a-f0-9]{2}", "", the_post["slug"]) # Supprimer les caractères spéciaux échappés
date_str = the_post["date"]
date = datetime.fromisoformat(date_str)
post_categories = [category_map[cat_id] for cat_id in the_post["categories"]]
content = the_post["content"]["raw"]
has_latex = "[latex]" in content
wp_post_id = the_post["id"]
author = the_post["author"]
if author == 1:
author = "Uli Köhler"
if author == 2:
author = "Yann Spöri"
if author == 6:
author = "Tobias Gutmann"
if author == 4:
author = "Joshua Simon"
if isinstance(author, int):
raise ValueError(f"Unknown author ID: {author}")
# Construire les catégories
category_header = None
for category in post_categories:
if category_header is None:
category_header = "categories:\n"
category_header += f" - {category}\n"
# Construire l'en-tête
header = f"""---
title: "{escaped_title}"
date: {date_str}
slug: "{slug}"
author: {author}
katex: {has_latex}
wordpress_import:
wp_post_id: {wp_post_id}
{category_header}
---\n\n"""
# Filtrer le contenu
filtered_content = content.replace("\r\n", "\n")
filtered_content = markdownify.markdownify(filtered_content, code_language_callback=code_language_callback)
# Exporter en Markdown
filename = f"content/post/{date.year}/{date.month}/{slug}.md"
os.makedirs(os.path.dirname(filename), exist_ok=True)
print(f"Writing to {filename}")
with open(filename, "w") as outfile:
outfile.write(header + filtered_content)
# Exporter le HTML brut pour le débogage
raw_filename = f"../raw_content/post/{date.year}/{date.month}/{slug}.html"
os.makedirs(os.path.dirname(raw_filename), exist_ok=True)
with open(raw_filename, "w") as outfile:
outfile.write(content)
for post in [post for post in posts]:
export_post(post)If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow