2つのPDFのテキストを比較して変更ページを特定
ウィンドウを何度も切り替えたり、目視だけに頼ったりせずに、2つのPDFを比較できます。各文書から抽出したテキストを1ページにつき1つの文字列として指定すると、異なるページ番号を正確に報告します。変更された各ページには、追加または削除された単語とその数を含む、短く決定論的な概要が表示されます。一方の版にしか存在しないページも特定します。比較処理はネットワークを使用せず、ページ順を維持し、抽出テキストがない文書は入力エラーとして扱います。
無料で実行
ページ構成を保ったテキストをご用意ください
まず、両方のPDFファイルから抽出済みのテキストをご用意ください。各文書は順序付きの配列として入力し、最初の文字列を1ページ目、2番目を2ページ目という形で並べます。結果は文書全体を一続きのブロックとして扱うのではなく、ページ番号ごとに差分を報告するため、ページ境界を保つことが重要です。抽出ツールによっては、空白、タブ、改行が重複して出力されることがあります。この比較では、テキストが変わったかを判定する前に連続する空白を正規化します。そのため、別の抽出ツールが文章を異なる位置で折り返しただけでは、変更ページとして扱いません。本機能は光学文字認識を実行せず、PDFファイル自体を開かず、不明なページ境界を推測しません。スキャン文書にテキストレイヤーがない場合は、先にOCRを実行し、ページ単位の結果を入力してください。フォント、段組み、表によって読み順が乱れる場合は、抽出品質もご確認ください。両方の入力には、空白以外のテキストを含むページが少なくとも1つ必要です。
変更ページの概要をご確認ください
空白を正規化した後、対応するページ位置どうしを比較します。正規化後のテキストが同一なら、差分項目は生成されません。ページが変更されている場合は、両方の版を単語に分割し、大文字と小文字を区別せずに出現回数を比較して、削除された単語数と追加された単語数を報告します。プレビューには削除語と追加語がそれぞれ最大5件表示されるため、更新された金額、日付、当事者名、契約用語などを見つけやすくなります。繰り返しも個別に数えるため、同じ語を2回削除すると削除数は2になります。単語自体が同じでも、順序、大文字表記、句読点が異なる場合は変更として記録し、概要でその理由を示します。これは簡潔な診断であり、文字単位のパッチではありません。また、意味上の重要性を推測したり、異なる表現が同じ意味だと判断したりしません。契約書、財務諸表、規制文書などでは、報告されたページ番号を使って人による確認範囲を絞り込んでください。
不足ページを解釈し、安全にご利用ください
2つの文書のページ数が同じとは限りません。一方の入力に追加のページ位置がある場合、そのページがPDF Aのみに存在するのか、PDF Bのみに存在するのかを、抽出された単語数とともに報告します。最上位の結果には、両文書のページ数、異なるページ番号の順序付き一覧、各差分の詳細、および自動処理に使える一致フラグが含まれます。このため、公開前チェック、承認ワークフロー、アーカイブ検証、文書取り込み処理に活用できます。一致フラグが真であることは、正規化した抽出テキストがページごとに一致したことを意味しますが、画像、注釈、署名、色、フォント、メタデータ、非表示レイヤー、配置まで同一であることは証明しません。逆に、抽出結果の差が意図的な編集ではなく、PDFの符号化方式によって生じる場合もあります。重要な確認では、本レポートでテキスト差分の場所を特定した後、元のページを確認し、文書に応じた法務、財務、業務上の判断を行ってください。
活用例
改訂された契約書の確認
署名済みまたは提案中の原本で対象条項を調べる前に、抽出された文言が変わったページを特定できます。
公開前の報告書チェック
草稿と最終版を比較し、金額、日付、ラベルの変更や、誤って追加・削除されたページを検出できます。
文書版管理の自動化
一致フラグと差分ページ一覧を使い、変更されたPDFだけを手動承認フローへ送れます。
よくある質問
PDFファイルを直接入力できますか?
いいえ。ページごとに1つの文字列として整理された、抽出済みのテキストを入力します。
一方の入力が空の場合はどうなりますか?
無効な入力として失敗します。各PDFには、空白以外の抽出テキストを含むページが少なくとも1つ必要です。
改行や重複する空白も変更として扱われますか?
いいえ。ページの一致判定前に空白を正規化するため、抽出時の折り返しだけによる違いは無視されます。
外観や書式の違いも検出できますか?
いいえ。抽出テキストだけを比較し、画像、書体、注釈、署名、メタデータ、ページ上の配置は検査しません。
追加または削除されたページはどう表示されますか?
対応する位置がないページは、PDF AまたはPDF Bのみに存在すると表示され、抽出単語数も示されます。
比較料金はいくらですか?
APIリクエスト1回につき$0.002です。決定論的なブラウザー実装はネットワーク呼び出しなしでも動作します。
開発者向け — APIアクセス
このページの機能はすべてAPIからも利用できます。自社システムに組み込みたいチーム向けのセクションです。それ以外の方は上のツールをそのままお使いください。
エンドポイント
Bearerトークンで認証し、POST1回でタスクをキューに登録します。結果はWebhookまたは署名付きリンクで受け取れます。
お使いのスタックから呼び出す
curl -X POST https://api.kit.forhosting.com/pdf/compare-text \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"pages_a":["Quarterly report\nRevenue was $2.4 million.","Operating expenses were $1.1 million."],"pages_b":["Quarterly report\nRevenue was $2.7 million.","Operating expenses were $1.1 million."]}'const res = await fetch("https://api.kit.forhosting.com/pdf/compare-text", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"pages_a": [
"Quarterly report\nRevenue was $2.4 million.",
"Operating expenses were $1.1 million."
],
"pages_b": [
"Quarterly report\nRevenue was $2.7 million.",
"Operating expenses were $1.1 million."
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/compare-text",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"pages_a": [
"Quarterly report\nRevenue was $2.4 million.",
"Operating expenses were $1.1 million."
],
"pages_b": [
"Quarterly report\nRevenue was $2.7 million.",
"Operating expenses were $1.1 million."
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/compare-text", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"pages_a":["Quarterly report\\nRevenue was $2.4 million.","Operating expenses were $1.1 million."],"pages_b":["Quarterly report\\nRevenue was $2.7 million.","Operating expenses were $1.1 million."]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"pages_a":["Quarterly report\nRevenue was $2.4 million.","Operating expenses were $1.1 million."],"pages_b":["Quarterly report\nRevenue was $2.7 million.","Operating expenses were $1.1 million."]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/compare-text", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)リクエスト例
{
"pages_a": [
"Quarterly report\nRevenue was $2.4 million.",
"Operating expenses were $1.1 million."
],
"pages_b": [
"Quarterly report\nRevenue was $2.7 million.",
"Operating expenses were $1.1 million."
]
}レスポンス例
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.compare_text",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}非同期APIです。task_idは即時に返ります。ポーリングは1秒あたり1リクエストまでです。
料金
単価はすべて公開しています。トークン換算や独自クレジットはありません。失敗したタスクは課金されません。
制限
max_mb | 25 |
max_pages | 200 |
エラー
| HTTP | コード | 意味 |
|---|---|---|
401 | unauthorized | APIキーが無効か、指定されていません。Authorizationヘッダーを確認してください。 |
402 | insufficient_balance | 残高が不足しています。チャージ後に再度お試しください。 |
404 | unknown_type | 指定されたタスクタイプは存在しません。タイプ名を確認してください。 |
429 | rate_limited | リクエストが多すぎます。しばらく待ってから再度お試しください。 |