PDFからWordへの変換は、業務効率化のための代表的な自動化タスクです。しかし、PDFの種類によって最適なアプローチが異なります。本稿では、「テキスト埋込型PDF」と「スキャン画像型PDF」の2種類に対応したPython実装を、技術的背景と実装の意図を含めて解説します。
PDFの二つの性質
PDFは見た目が同じでも内部構造が大きく異なります。
- テキスト埋込型PDF:Wordやブラウザから直接出力されたもので、文字情報がベクタ形式で保持されています。OCR不要でテキスト抽出が可能です。
- スキャン画像型PDF:スキャナやスマートフォン撮影で生成されたもので、実際にはページごとのラスタ画像(JPEG/PNG相当)です。文字認識(OCR)が必要です。
テキスト埋込型PDF → Word変換
このケースでは、pdf2docxライブラリを活用します。PDF内のレイアウト情報を可能な限り維持しつつ、段落・表・フォントスタイルを再現します。
from pdf2docx import Converter
import os
def convert_text_pdf_to_docx(
input_path: str,
output_path: str,
start_page_index: int = 0,
end_page_index: int = None
) -> bool:
"""
テキストベースのPDFを.docx形式に変換
Args:
input_path: 入力PDFファイルパス
output_path: 出力Wordファイルパス
start_page_index: 変換開始ページインデックス(0始まり)
end_page_index: 変換終了ページインデックス(含む、Noneで全ページ)
Returns:
成功時はTrue、失敗時はFalse
"""
if not os.path.exists(input_path):
print(f"エラー: 入力ファイルが見つかりません → {input_path}")
return False
try:
converter = Converter(input_path)
# インデックス補正(pdf2docxは0始まり)
actual_start = max(0, start_page_index)
actual_end = end_page_index + 1 if end_page_index is not None else None
converter.convert(output_path, start=actual_start, end=actual_end)
converter.close()
print(f"✅ 変換完了: {output_path}")
return True
except Exception as error:
print(f"❌ 変換失敗: {error}")
return False
スキャン画像型PDF → Word変換(OCR統合)
ここでは、PDFを高解像度画像に分解し、tesserocrによるOCR処理を経て、結果をWordドキュメントに整形します。信頼度フィルタリングと段落単位の構造化を実装しています。
from pathlib import Path
import fitz # PyMuPDF
from PIL import Image
from docx import Document
from tesserocr import PyTessBaseAPI, PSM, OEM
import numpy as np
def ocr_scan_pdf_to_docx(
pdf_path: str,
docx_path: str,
confidence_threshold: float = 65.0,
dpi: int = 300,
lang_code: str = "chi_sim+eng",
tessdata_dir: str = "./tessdata"
) -> bool:
"""
スキャンPDFをOCRでテキスト化し、Word文書へ出力
Args:
pdf_path: 入力PDFパス
docx_path: 出力DOCXパス
confidence_threshold: OCR信頼度下限(0–100)
dpi: OCR用画像解像度
lang_code: 言語コード(例: "chi_sim+eng")
tessdata_dir: .traineddataファイル格納ディレクトリ
Returns:
成功時True
"""
if not Path(pdf_path).is_file():
print("❌ PDFファイルが存在しません")
return False
doc = Document()
pdf_doc = fitz.open(pdf_path)
# 各ページを高品質画像に変換
image_list = []
zoom = dpi / 72.0
mat = fitz.Matrix(zoom, zoom)
for page_num in range(len(pdf_doc)):
page = pdf_doc[page_num]
pix = page.get_pixmap(matrix=mat, alpha=False)
img = Image.frombytes("RGB", (pix.width, pix.height), pix.samples)
image_list.append(img)
# OCR実行(LSTMエンジン+自動レイアウト検出)
with PyTessBaseAPI(
path=tessdata_dir,
lang=lang_code,
psm=PSM.AUTO,
oem=OEM.LSTM_ONLY
) as api:
for idx, img in enumerate(image_list):
api.SetImage(img)
text = api.GetUTF8Text()
# 信頼度に基づくフィルタリング(簡易版)
confidences = api.AllWordConfidences()
words = text.split()
filtered_words = [
w for w, c in zip(words, confidences)
if c >= confidence_threshold
]
paragraph_text = " ".join(filtered_words).strip()
if paragraph_text:
doc.add_paragraph(paragraph_text)
try:
doc.save(docx_path)
print(f"✅ OCR変換完了: {docx_path}")
return True
except Exception as e:
print(f"❌ DOCX保存失敗: {e}")
return False
環境構築の要点
tesserocrを利用する際の注意点:
- tesseractバイナリ不要:conda/pip経由で
tesserocrをインストールすれば、組み込みのOCRエンジンが利用可能(Windows/macOS/Linux共通)。 - tessdataの配置:必要な言語モデル(例:
chi_sim.traineddata,eng.traineddata)を任意ディレクトリに配置し、path引数で明示的に指定します。 - 推奨インストール方法:
conda install -c conda-forge tesserocr(安定性・互換性が最も高い)。
OCRパラメータの選択指針
| パラメータ | 推奨値 | 用途 |
|---|---|---|
PSM |
PSM.AUTO(=3) |
汎用的レイアウト検出(多言語・複雑配置対応) |
OEM |
OEM.LSTM_ONLY(=1) |
手書き風・低解像度・複雑フォントにも強い |
lang |
"chi_sim+eng" |
中英混在文書向け(必要に応じて追加) |