概要
PDFファイルをMarp形式のMarkdownに変換するPythonスクリプトを作成しました。このスクリプトは、PDFからテキストを抽出し、適切なMarkdown形式に整形して保存します。
モチベーション
生成AIを使ってスライドを作成する際の利便性を向上させるために、このスクリプトを開発しました。多くのスライドはCanvaを使って作成されており、過去のスライドの文言やチャート(図解や絵)を再利用して新しいスライドを作成したいと考えています。
課題
さまざまな生成AIを試しましたが、1ファイルが25MBを超えると読み込めなかったり、解析に時間がかかる割に認識率が低いという問題がありました。Canvaのスライドのレイアウトを再現することは難しく、手作業でひとつひとつ入力するのは避けたいと考え、このツールを作成しました。
解決策
このスクリプトを使うことで、PDFからテキストを抽出し、Marp形式のMarkdownに変換することができます。これにより、手作業での入力を減らし、効率的にスライドを作成することが可能です。
補足
本記事では、CanvaからMarkdownへの変換について説明していますが、逆にMarp CLIを使ってPDF出力し、そのPDFをCanvaで読み込ませることも可能です。
このような形でいかがでしょうか?他に修正や追加が必要な点があれば教えてくださいね。
最終的なコード
import os
import re
import sys
import glob
from PyPDF2 import PdfReader
def extract_text_from_pdf(pdf_file):
text = []
with open(pdf_file, 'rb') as file:
reader = PdfReader(file)
for page in reader.pages:
text.append(page.extract_text())
return text
def clean_and_format_markdown(content):
# 重複行の削除
lines = content.split('\n')
unique_lines = []
for line in lines:
if not unique_lines or line != unique_lines[-1]:
unique_lines.append(line)
content = '\n'.join(unique_lines)
# 見出しの設定
content = re.sub(r'^#\s', '## ', content, flags=re.MULTILINE)
# レイアウトの改善
content = re.sub(r'^▶', '- ', content, flags=re.MULTILINE)
content = re.sub(r'^●', '### ', content, flags=re.MULTILINE)
return content
def convert_pdf_to_marp(pdf_file):
base_name = os.path.splitext(pdf_file)[0]
md_file = f"{base_name}.md"
try:
# PDFからテキストを抽出
extracted_text = extract_text_from_pdf(pdf_file)
# Marpのフロントマター
marp_content = "---\nmarp: true\ntheme: default\n---\n\n"
# 各ページを処理
for page_text in extracted_text:
cleaned_text = clean_and_format_markdown(page_text)
marp_content += cleaned_text + "\n\n---\n\n" # ページ区切りを追加
# 変更を保存
with open(md_file, "w", encoding="utf-8") as file:
file.write(marp_content)
print(f"Converted {pdf_file} to {md_file}")
except Exception as e:
print(f"Unexpected error occurred while processing {pdf_file}: {e}")
def main():
if len(sys.argv) > 1:
pdf_files = sys.argv[1:]
else:
pdf_files = glob.glob("*.pdf")
if not pdf_files:
print("No PDF files found or specified.")
return
for file in pdf_files:
if os.path.isfile(file) and file.lower().endswith('.pdf'):
convert_pdf_to_marp(file)
else:
print(f"Skipping {file}: Not a valid PDF file.")
if __name__ == "__main__":
main()
使用手順
-
必要なライブラリのインストール:
pip install PyPDF2
-
スクリプトを適当な名前(例:
pdf_to_marp.py
)で保存します。 -
コマンドラインで、スクリプトが保存されているディレクトリに移動します。
-
以下のコマンドを実行して、PDFファイルをMarp形式のMarkdownに変換します:
- 特定のPDFファイルを変換する場合:
python pdf_to_marp.py path/to/your/file.pdf
- カレントディレクトリ内のすべてのPDFファイルを変換する場合:
python pdf_to_marp.py
- 特定のPDFファイルを変換する場合:
-
変換が完了すると、入力PDFファイルと同じ名前で
.md
拡張子のファイルが生成されます。 -
生成されたMarkdownファイルをMarp対応のエディタ(例:VS Code with Marp extension)で開いて確認し、必要に応じて手動で調整します。
Pandocを使った試行錯誤の過程
-
最初のアプローチ:
当初、PDFからMarkdownへの変換にPandocを使用しようとしました。以下のようなコマンドを試みました:pandoc -f pdf -t markdown input.pdf -o output.md
しかし、このアプローチは「Unknown input format pdf」というエラーで失敗しました。
-
中間フォーマットの使用:
次に、PDFをテキストに変換してから、そのテキストをMarkdownに変換する2段階のプロセスを試みました:pdftotext input.pdf temp.txt pandoc -f plain -t markdown temp.txt -o output.md
これは部分的に機能しましたが、PDFの構造が失われ、結果が理想的ではありませんでした。
-
入力フォーマットの指定:
Pandocの入力フォーマットとしてplain
やtext
を指定しましたが、これらは直接サポートされていないことがわかりました。 -
Markdownとして扱う:
最後に、入力を直接Markdownとして扱うことを試みました:pandoc -f markdown -t markdown input.txt -o output.md
これは機能しましたが、PDFの構造やフォーマットを適切に保持できませんでした。
-
結論:
これらの試行錯誤を経て、Pandocは本ケースでは最適なツールではないと判断しました。PDFの構造を保持し、Marp形式に適したMarkdownを生成するには、カスタムのPythonスクリプトを作成する方が効果的であることがわかりました。
この過程を経て、最終的に上記のPythonスクリプトを開発し、PDFからMarp形式のMarkdownへの直接変換を実現しました。このアプローチにより、PDFの構造をより適切に保持し、Marpに適したフォーマットを生成することができました。
生成AIの使用
- Perplexity(CLAUDE 3.5 SONNET)とMicrosoft Copilot(Microsoft 365等ライセンス支払いなし、無料)を使用して作成しました
- なお、開発・実行環境はMicrosoft Windows 11を搭載するPC上です