Python で PDF データを扱う方法

Python で PDF データを扱う方法

Aspose.PDF FOSS for Python は、PDF 文書の XMP メタデータを、XmpPacket、XmpField、XmpArray、XmpStruct、および XmpProperty オブジェクトから構築されたインメモリ データモデルとして表現し、NamespaceProvider が名前空間プレフィックスを URI に解決します。これにより、RDF/XML を手書きすることなく、タイトル、日付、キーワードリスト、カスタムフィールドなどの構造化メタデータを読み取り、作成、再書き込みできます。このライブラリは純粋な Python で、以下のコマンドでインストールできます。

ステップバイステップ ガイド

ステップ 1: パッケージをインストールする

Aspose.PDF FOSS パッケージをインストールする:

git clone https://github.com/aspose-pdf-foss/Aspose-PDF-FOSS-for-Python.git
cd Aspose-PDF-FOSS-for-Python
pip install -e .

XmpPacket をインポートし、確認メッセージを出力してインストールを検証する:

from aspose_pdf import XmpPacket
print("aspose-pdf-foss-for-python is ready.")

ステップ 2: 必要なクラスをインポート

XMP データモデルクラスと名前空間リゾルバをインポートします:

from aspose_pdf import (
    NamespaceProvider,
    XmpArray,
    XmpField,
    XmpPacket,
    XmpProperty,
    XmpStruct,
)

ステップ 3: パケットを作成し、シンプルなプロパティを設定

XmpPacket() は空のフィールドリストで開始します。set_value(prefix, name, value, uri=...) はシンプルなプロパティを設定または置き換え、get(prefix_or_uri, name) はそれを XmpField として読み戻します;get は登録済みプレフィックスまたは完全な名前空間 URI のいずれかを受け付けます:

from aspose_pdf import XmpPacket

packet = XmpPacket()
packet.set_value("dc", "title", "Quarterly Report")
packet.set_value(
    "dc", "creator", "Automation Pipeline",
    uri="http://purl.org/dc/elements/1.1/",
)

title_field = packet.get("dc", "title")
print(title_field.value)  # "Quarterly Report"

ステップ 4: 型付き値を保存

XmpPacket は、XMP が内部で保持するプレーンテキスト形式に変換・逆変換する型付き便利アクセサを提供します: set_date/get_date, set_int/get_int, set_real/get_real, および set_bool/get_bool。各 getter は、プロパティが存在しない場合に例外を発生させる代わりに None を返します:

from datetime import datetime

packet.set_date("xmp", "CreateDate", datetime(2026, 7, 29, 9, 30))
packet.set_int("pdf", "PageCount", 42)
packet.set_real("custom", "ConfidenceScore", 0.97, uri="https://example.com/ns/custom/1.0/")
packet.set_bool("custom", "IsFinal", True, uri="https://example.com/ns/custom/1.0/")

print(packet.get_date("xmp", "CreateDate"))
print(packet.get_int("pdf", "PageCount"))
print(packet.get_real("custom", "ConfidenceScore"))
print(packet.get_bool("custom", "IsFinal"))

ステップ 5: ローカライズされたテキストと順序付き配列を保存

set_localized_text は、言語代替 (rdf:Alt) プロパティを、たとえば dc:title のように特定の言語で書き込み、デフォルトは "x-default" にします。set_array は、プレーンな値リストから順序付き (Seq)、順序なし (Bag)、または代替 (Alt) 配列を書き込み、get_array はそれを文字列のリストとして読み戻します:

packet.set_localized_text("dc", "description", "Quarterly summary", lang="en")
packet.set_localized_text(
    "dc", "description", "Resumen trimestral",
    uri="http://purl.org/dc/elements/1.1/", lang="es",
)
print(packet.get_localized_text("dc", "description", lang="es"))

packet.set_array("dc", "subject", ["finance", "quarterly", "internal"], kind="Bag")
print(packet.get_array("dc", "subject"))

ステップ 6: XmpStruct を使用して構造化値を構築する

一部の XMP プロパティ(次元レコード、履歴エントリなど)は、単純なテキストではなく構造化値です。XmpStruct で構造体を作成し、XmpField オブジェクトを add で追加し、get で名前でメンバーを取得し、最後に add で構造体をパケットに添付します:

dimensions = XmpStruct()
dimensions.add(XmpField(prefix="stDim", name="w", value="612"))
dimensions.add(XmpField(prefix="stDim", name="h", value="792"))
dimensions.add(XmpField(prefix="stDim", name="unit", value="pt"))

print(dimensions.get("w").value)  # "612"

packet.add(XmpField(prefix="xmpTPg", name="MaxPageSize", value=dimensions))

ステップ 7: カスタム XMP 名前空間を登録する

NamespaceProvider には標準の XMP 名前空間(Dublin Core、Adobe XMP、PDF など)が事前にロードされています。register(prefix, uri) を呼び出してカスタムマッピングを追加します — このメソッドはプロバイダー自身を返すので呼び出しをチェーンできます — その後、プロバイダーをパケットに添付し、シリアライズ時にカスタムプレフィックスをその URI に解決できるようにします:

from aspose_pdf import NamespaceProvider, XmpPacket

provider = NamespaceProvider()
provider.register("custom", "https://example.com/ns/custom/1.0/")

packet = XmpPacket(namespace_provider=provider)
packet.set_value("custom", "batch_id", "run-2026-07-29")

ステップ 8: パケットを解析およびシリアライズする

XmpPacket.parse(data, provider=...) は生の XMP パケットバイトまたはテキストを XmpPacket に読み込みます。serialize() と to_bytes() はどちらもパケットを XMP パケットバイトに再変換します:

xmp_bytes = packet.to_bytes()

restored = XmpPacket.parse(xmp_bytes)
print(restored.get("dc", "title").value)

一般的な問題と対策

get() または型付き getter が返す None プロパティを設定したばかりなのに

prefix(または URI)引数が get/get_int/get_date/etc. に対して、対応する set_* 呼び出しに渡されたものと正確に一致していることを確認してください — get はフィールドのプレフィックスと名前空間 URI の両方で一致しますが、片方の呼び出しでカスタムプレフィックスが不一致で、もう一方で URI が使用されていると一致しません。

カスタム名前空間プレフィックスはシリアライズ時に不完全な出力を生成します

標準の XMP 名前空間(dc、xmp、pdf など)に含まれないプレフィックスは、すべての set_* 呼び出しで明示的な uri= 引数を指定するか、NamespaceProvider にそのプレフィックスを登録し、XmpPacket(namespace_provider=provider) を通じてパケットに添付してから serialize()/to_bytes() を呼び出す必要があります。

get_bool, get_int、または get_real returns None 設定されていることが分かっている値に対して

これらの型付き getter は、保存されたテキストが期待する型に解析できない場合に None を返します — 例えば、値が set_value で自由形式テキストとして設定され、set_int ではなく get_int が使用されたプロパティです。getter の解析ロジックが書き込みパスと一致するように、対応する型付き setter(set_int、set_real、set_bool)を使用してください。

XmpPacket.parse raises ValueError 信頼できないソースからのパケット上で

parse は、XXE や billion-laughs 攻撃に対する hostile-input ガードとして、あらゆる <!DOCTYPE または <!ENTITY 宣言を拒否します。正規の XMP パケットは DTD を必要としません;例外はソースストリームが不正または安全でないことを示すシグナルとみなし、ガードを回避しようとしないでください。

get_array returns None リストの代わりに

get_array は、指定されたプロパティが存在しないか、XmpArray として保存されていない場合(例として、set_array の代わりに set_value で設定された場合)に None を返します。プロパティを書き込む際は、保存された値が get_array が期待する形状と一致するように set_array を使用してください。

よくある質問

set_value と、set_int のような型付きセッターとの違いは何ですか?

set_value は、渡された value をそのまま保存します。型付きセッター(set_date、set_int、set_real、set_bool)は、入力を XMP が内部で使用するプレーンテキスト形式に変換し、対応する型付きゲッターと組み合わせて再び解析できるようにします。そのため、生の文字列ではなく往復の型安全性が必要な場合にこれらを使用してください。

XmpArray の種類(Bag、Seq、Alt)はどのように異なりますか?

Bag は順序のない値の集合で、Seq は順序付きリスト、Alt は代替値(多くの場合、set_localized_text が使用する言語代替)を保持します。目的の種類を set_array(..., kind="Bag") に渡すか、直接 XmpArray(kind=...) を構築してください。

パケット上のプロパティの生のリストを、事前に名前を知らなくても取得できますか?

はい — packet.fields を反復処理します。packet.fields は、パケットに挿入順で追加されたすべての XmpField、XmpArray、および XmpProperty を保持します。

標準の XMP 名前空間に対して NamespaceProvider が必要ですか?

いいえ。dc、xmp、pdf、および他の標準プレフィックスは自動的に解決されます。NamespaceProvider は、独自に作成したカスタムプレフィックスが必要な場合にのみ使用します。

XmpProperty 修飾子は、単なる XmpField とどう違うのですか?

XmpProperty は、基本の XmpField を add_qualifier で追加された修飾子フィールドのリストとともにラップし、プロパティ自体にその値に付随する追加の RDF メタデータが必要な、まれなケースで使用されます。これは、XmpField.language がすでにカバーしている xml:lang 修飾子を超える場合です。

参照

 日本語