以下の内容はhttps://touch-sp.hatenablog.com/entry/2025/04/05/140534より取得しました。


【Python】4つの方法でPDFからテキストを抽出してみた。

はじめに

PDFからテキストを抽出する関数と特定のページを抽出する関数を書きました。

テキスト抽出

Pythonスクリプト

def extract_text_from_pdf(input_pdf_path, library="pypdf2"):
    """
    指定されたPDFファイルから、テキストを抽出します。

    Args:
        input_pdf_path (str): 入力PDFファイルのパス。
        library (str): 使用するライブラリ。

    Returns:
        str: 抽出されたテキスト。エラーの場合は空文字列を返します。
    """
    text = ""

    match library:
        case "pypdf2":
            from PyPDF2 import PdfReader
            try:
                with open(input_pdf_path, 'rb') as pdf_file:
                    pdf_reader = PdfReader(pdf_file)
                    num_pages = len(pdf_reader.pages)
                    for page_num in range(num_pages):
                        page = pdf_reader.pages[page_num]
                        text += page.extract_text()
            except FileNotFoundError:
                print(f"エラー: ファイル '{input_pdf_path}' が見つかりません。")
            except Exception as e:
                print(f"エラーが発生しました: {e}")
        
        case "pdfminer":
            from pdfminer.high_level import extract_text
            try:
                text = extract_text(input_pdf_path)
            except FileNotFoundError:
                print(f"エラー: ファイル '{input_pdf_path}' が見つかりません。")
            except Exception as e:
                print(f"エラーが発生しました: {e}")

        case "pdfplumber":
            import pdfplumber
            try:
                with pdfplumber.open(input_pdf_path) as pdf:
                    for page in pdf.pages:
                        text += page.extract_text() + "\n"
            except FileNotFoundError:
                print(f"エラー: ファイル '{input_pdf_path}' が見つかりません。")
            except Exception as e:
                print(f"エラーが発生しました: {e}")

        case "pymupdf":
            import fitz
            try:
                with fitz.open(input_pdf_path) as doc:
                    for page in doc:
                        text += page.get_text()
            except FileNotFoundError:
                print(f"エラー: ファイル '{input_pdf_path}' が見つかりません。")
            except Exception as e:
                print(f"エラーが発生しました: {e}")

        case _:
            print(f"{library}が不適です。")

    return text

使い方

テキストを抽出してファイルに保存する使い方です。4つの方法すべてが実行されます。

from extract_text import extract_text_from_pdf

pdf_fname = "extracted.pdf"

methods = ["pypdf2", "pdfminer", "pdfplumber", "pymupdf"]

for method in methods:
    
    text = extract_text_from_pdf(pdf_fname, library=method)

    with open(f"result_{method}.txt", "w", encoding="utf-8") as f:
        f.write(text)

特殊な場合

左右2列になっている日本語横書きのPDFをたまに見かけます。その場合はこのようにしました。

import fitz  # pymupdfのインポート

# PDFファイルを開く
file_path = "extracted.pdf"  # PDFファイルのパスを指定
doc = fitz.open(file_path)

all_text = ""

# 各ページからブロックデータを抽出してソート
for page_number in range(1, len(doc)):
    
    left_column = ""
    right_column = ""

    page = doc[page_number]

    half_line = page.rect.width / 2
    
    # ページ内のブロックデータを取得 (x0, y0, x1, y1, text)
    blocks = page.get_text("blocks") 
    
    # y0(上から下)にソート
    sorted_blocks = sorted(blocks, key=lambda block: block[1])
    
    # 今回は上二つ、下一つを除外を除外(PDFタイトルやページ数など)
    sorted_blocks = sorted_blocks[2:-1]

    for block in sorted_blocks:
        if block[0] < half_line:
            left_column += block[4]
        else:
            right_column += block[4]
    
    all_text += left_column + right_column


# 抽出結果を表示
print(all_text.replace("\n", ""))

ページ抽出

import fitz

def extract_pdf_page(input_pdf_path, output_pdf_path, start_page, end_page):
    """
    指定されたPDFファイルから、指定したページ範囲を新しいPDFファイルとして抽出します。

    Args:
        input_pdf_path (str): 入力PDFファイルのパス。
        output_pdf_path (str): 出力PDFファイルのパス。
        start_page (int): 抽出を開始するページの番号(1から始まる)。
        end_page (int): 抽出を終了するページの番号(1から始まる)。
    """
    try:
        with open(input_pdf_path, "rb") as f:
            inbytes = f.read()
        src = fitz.open("pdf", inbytes)
        doc = fitz.open()

        # fitzのページ番号は0から始まるため、調整
        from_page = start_page - 1
        to_page = end_page - 1

        if 0 <= from_page < len(src) and 0 <= to_page < len(src) and from_page <= to_page:
            doc.insert_pdf(src, from_page=from_page, to_page=to_page)
            doc.save(output_pdf_path)
            print(f"'{input_pdf_path}' の {start_page} ページから {end_page} ページを '{output_pdf_path}' に抽出しました。")
        else:
            print("エラー: 指定されたページ範囲が不正です。")
            if not (0 <= from_page < len(src)):
                print(f"開始ページ {start_page} がPDFの範囲外です。")
            if not (0 <= to_page < len(src)):
                print(f"終了ページ {end_page} がPDFの範囲外です。")
            if from_page > to_page:
                print("開始ページが終了ページより大きいです。")

        src.close()
        doc.close()

    except FileNotFoundError:
        print(f"エラー: ファイル '{input_pdf_path}' が見つかりません。")
    except Exception as e:
        print(f"エラーが発生しました: {e}")

使用したライブラリ

pdfminer-six==20250327
pdfplumber==0.11.6
pymupdf==1.25.5
pypdf2==3.0.1






以上の内容はhttps://touch-sp.hatenablog.com/entry/2025/04/05/140534より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14