第2章 データ準備 / 想定学習時間:30〜40分 / 最終確認:2026年8月

2-2. ドキュメント抽出(PDF、HTML等からのテキスト抽出)

🎯 この節の学習目標

1. RAGの品質は抽出品質で決まる

RAGパイプラインの最初の実務作業が、ソース文書からのテキスト抽出です。ここで文字化けした、順序が崩れた、あるいは本文以外のノイズだらけのテキストを作ってしまうと、その後のチャンキング・埋め込み・検索・生成のすべてが劣化します。いわゆる garbage in, garbage out です。

重要なのは、「PDF」とひとくくりにせず、文書の実体がどんな形式かを見極めてから手法を選ぶことです。試験でも「この形式の文書には何を使うべきか」という選択問題が出題されます。

2. PDFからの抽出:パーサーとOCRの使い分け

PDFには大きく2種類あり、必要な技術がまったく異なります。

PDFの種類実体適切な手法代表的ツール
テキスト埋め込み型文字データがPDF内部に格納されている(コピー&ペーストできる)PDFパーサーで直接テキストを取り出すpypdf、pdfplumber など
スキャン画像型ページが画像として格納されている(文字を選択できない)OCR(光学文字認識)が必要。パーサーでは何も取れないTesseract等のOCRエンジン、OCR内蔵のパースサービス

Pythonでの最小例は次のとおりです。

# テキスト埋め込み型PDFの抽出(pypdf)
from pypdf import PdfReader

reader = PdfReader("/Volumes/prod/hr_qa/raw_docs/policy.pdf")
text = "\n".join(page.extract_text() for page in reader.pages)

実務では両者が混在するコーパスも多いため、「抽出結果がほぼ空のページはスキャン画像型とみなしてOCRに回す」といった振り分けを行います。また、unstructured のような汎用ライブラリは、PDF・HTML・Word・PowerPointなど多形式を統一的に扱い、要素(タイトル、段落、表など)の種類付きで抽出できるため、混在コーパスの処理によく使われます。

📝 試験のポイント

「スキャンされたPDF(画像ベースのPDF)からテキストを取得したい」という問いにはOCRが正解です。pypdfのような通常のパーサーを選ばせる誤答が並びます。逆に、テキスト埋め込み型のPDFにOCRをかけるのは、精度・コストの面で不利な過剰処理です。「文字を選択できるか否か」を見分けの基準として覚えましょう。

3. Databricksのai_parse_document

Databricksは、文書パースをプラットフォーム機能として提供する ai_parse_document 関数を持っています。SQLまたはPythonから呼び出し、Volume上のPDF等の非構造化文書からテキストや構造(要素・レイアウト)を抽出できます。AI(視覚モデル)ベースのパースであるため、複雑なレイアウトの文書にも対応しやすいのが特徴です。

-- SQLからVolume上の文書をパースする例
SELECT
  path,
  ai_parse_document(content) AS parsed
FROM READ_FILES('/Volumes/prod/hr_qa/raw_docs/', format => 'binaryFile');

外部ライブラリを持ち込まずに、Volume上の文書 → Deltaテーブルへのパース結果格納までをDatabricks内で完結できる点が利点です。試験対策としては、「Databricksネイティブの文書パース手段として ai_parse_document がある」と知っていれば十分です。

4. HTMLからの抽出:本文とボイラープレートの分離

WebページやイントラネットのHTMLをソースにする場合、課題はタグの除去だけではありません。HTMLには、ナビゲーションメニュー、ヘッダー、フッター、サイドバー、広告、Cookieバナーなど、本文と無関係なボイラープレートが大量に含まれます。これらを索引化すると、どのページにも同じ文言(「ホームに戻る」「プライバシーポリシー」等)が含まれることになり、検索結果がノイズで汚染されます。

BeautifulSoup などのHTMLパーサーで、本文領域(<main><article> タグ、本文用のclass)だけを選択的に抽出し、<nav><footer><script> 等を除去するのが基本です。

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, "html.parser")
for tag in soup(["nav", "footer", "header", "script", "style", "aside"]):
    tag.decompose()          # ボイラープレートを除去
main = soup.find("main") or soup.body
text = main.get_text(separator="\n", strip=True)

💼 例:製品ドキュメントサイトの取り込み

製品マニュアルサイト(HTML)をRAGに取り込んだところ、「〇〇の設定方法は?」という質問に対して、どのページにも共通のフッター文言を含むチャンクばかりが検索上位に並んでしまいました。原因は全ページ共通のナビゲーション・フッターを本文と一緒に索引化していたことです。<article> 要素のみを抽出する処理に変更したところ、検索結果に本文チャンクが並ぶようになり回答品質が改善しました。「共通部分の除去」は抽出段階の必須処理です。

5. 表・レイアウト・見出し構造の扱い

抽出で品質差が出やすいのが、表と文書構造の扱いです。

📝 試験のポイント

試験では「文書形式と抽出手法の対応」が問われます。整理すると:テキスト埋め込みPDF→パーサー(pypdf等)/スキャンPDF→OCR/HTML→タグ除去・本文抽出(BeautifulSoup等)/表を含む文書→表構造を保持できるツール。また「抽出後のテキストに見出し・構造を残す方が後続処理に有利」という方向性の選択肢は正解になりやすいと覚えておきましょう。

✅ この節のまとめ

練習問題

問1. 紙の契約書をスキャンして作成されたPDF(文字の選択・コピーができない)をRAGのソースにしたい。テキストを取得する手法として適切なのはどれか。

  1. pypdfでextract_text()を呼び出す
  2. OCR(光学文字認識)を適用する
  3. BeautifulSoupでパースする
  4. ファイルをUTF-8としてデコードする
解答と解説を見る

正解:B

文字を選択できないPDFはページが画像として格納されており、テキストデータを持ちません。pypdfのようなパーサー(A)は埋め込みテキストを読む道具なので、ほぼ空の結果しか返せません。BeautifulSoup(C)はHTML用です。バイナリのPDFを文字コードでデコード(D)しても意味のあるテキストは得られません。画像から文字を認識するOCRが唯一の適切な手段です。

問2. 社内WikiのHTMLページ群をRAGに取り込んだところ、どの質問に対しても各ページ共通のナビゲーションメニューやフッターを含むチャンクが検索上位に並び、回答品質が低い。最も適切な対処はどれか。

  1. チャンクサイズを2倍にして、本文が含まれる確率を上げる
  2. より大きなLLMに変更する
  3. 抽出段階で本文領域のみを抽出し、ナビゲーション・フッター等のボイラープレートを除去して再インデックスする
  4. top-kを増やして多くのチャンクを取得する
解答と解説を見る

正解:C

原因はインデックスがボイラープレートで汚染されていることなので、データ側の修正(抽出処理の改善と再インデックス)が根本対処です。A・Dはノイズを含んだままの弥縫策で、かえってプロンプトのノイズが増えます。Bは検索段階の問題に対して生成側を変えており、原因に対処していません。

問3. 料金表や仕様表など多数の表を含む製品カタログPDFをRAG化する。検索・回答品質を保つための抽出方針として最も適切なのはどれか。

  1. 表は画像なので無視し、地の文のみを抽出する
  2. 単純なテキスト抽出で得られた文字列をそのまま使う(セルの並び順は品質に影響しない)
  3. 表構造を認識できるパーサーで表を抽出し、Markdown表など構造がわかる形式でテキスト化して保持する
  4. 表のみ手作業で全件書き起こす以外に方法はない
解答と解説を見る

正解:C

表は「どの値がどの行・列に属すか」が意味のすべてであり、構造が崩れたテキストは検索品質を下げます。pdfplumber、unstructured、ai_parse_documentなど表構造を扱えるツールで抽出し、構造が伝わる形式で保持するのが定石です。Aは料金・仕様という中核情報を捨ててしまい、Bは表の意味を壊します。Dはツールで自動化可能なので誤りです。

問4. Unity CatalogのVolumeに格納した多様なレイアウトのPDF文書を、外部ライブラリを追加せずDatabricksのネイティブ機能でパースしてDeltaテーブルに格納したい。利用を検討すべき機能はどれか。

  1. ai_parse_document関数
  2. Auto Loaderのschema inference
  3. Delta LakeのChange Data Feed
  4. COPY INTOコマンド
解答と解説を見る

正解:A

ai_parse_documentはSQL/Pythonから呼び出せるDatabricksの文書パース関数で、PDF等の非構造化文書からテキスト・構造を抽出できます。Bはファイル取り込み時のスキーマ推定、Cはテーブルの変更差分の取得、DはファイルからテーブルへのロードのためのSQLで、いずれもPDFの内容をテキスト化する機能ではありません。