はじめに
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