0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Cloud Vision で PDF を OCR するまでの手順

Posted at

このドキュメントは、Cloud Vision API の非同期OCR(PDF/TIFF → GCS出力)を実行するための準備と動作確認手順を、
実際に遭遇しやすいエラーの対処まで含めてまとめたものです。


0. ゴールと構成

  • ローカルの PDF を GCS バケットへアップロード
  • Cloud Vision API (asyncBatchAnnotateFiles) で OCR 実行(入力=GCS、出力=GCS JSON)
  • 出力 JSON をローカルにダウンロードして TXT に結合
  • 付随タスク:請求(Billing)サービスアカウント(SA)GCSバケット/IAM の準備と確認

1. 前提(インストール / 利用ツール)

1.1 gcloud CLI(Google Cloud SDK)

  • pip ではインストールできません。 OS用のインストーラで導入してください。
  • インストール後、gcloud --version が動作すること。

1.2 Python ライブラリ

python3 -m pip install --upgrade google-cloud-vision google-cloud-storage

2. gcloud の初期設定

# ログイン(ブラウザが開かない環境は --no-launch-browser を付ける)
gcloud auth login

# プロジェクト選択(例:ocr-project-xxxxxx)
gcloud config set project ocr-project-xxxxxx

# 設定確認
gcloud config list

メモ: You do not currently have an active account selected と出たら gcloud auth login を先に実行します。


3. 請求(Billing)の有効化(必須)

Vision・GCS の利用には 請求アカウントのリンク が必要です。

# 請求アカウント一覧表示
gcloud beta billing accounts list

# プロジェクトの請求状態
gcloud beta billing projects describe ocr-project-xxxxxx

# 請求アカウントをリンク
BILLING="012345-ABCDE0-123456"   # 例:上の一覧で得たIDに置換
gcloud beta billing projects link ocr-project-xxxxxx --billing-account="$BILLING"

HTTPError 403: The billing account ... is disabled が出る場合は、請求アカウント側/プロジェクト側の権限を見直してください。


4. サービスアカウント(SA)の作成とキー発行

# SA 作成(既に存在する場合はスキップしてOK)
gcloud iam service-accounts create vision-ocr-sa \
  --display-name="Vision OCR SA"

# SA のメール(例)
SA_EMAIL="vision-ocr-sa@ocr-project-xxxxxx.iam.gserviceaccount.com"

# JSON キー発行(組織ポリシーで禁止なら管理者に許可を依頼)
gcloud iam service-accounts keys create ./service-account.json \
  --iam-account="$SA_EMAIL"

アプリに鍵を使わせる(環境変数)

  • macOS / Linux
export GOOGLE_APPLICATION_CREDENTIALS="$PWD/service-account.json"
  • Windows PowerShell
$env:GOOGLE_APPLICATION_CREDENTIALS = "$PWD\service-account.json"

$PWD について: パスワードではなく「現在の作業ディレクトリのパス」です。PowerShell では $PWD.Path でも可。


5. GCS バケットの作成と権限付与

5.1 バケット作成

BUCKET="my-ocr-bucket-xxxxxx"   # 一意な名前(小文字/数字/ハイフン)
gcloud storage buckets create gs://$BUCKET --location=asia-northeast1

403 ... billing account ... absent請求のリンクが未設定。前章 3 を実施。

5.2 SA へのバケット権限付与

最低限、オブジェクトの読み書きができればOK(=roles/storage.objectAdmin)。

gcloud storage buckets add-iam-policy-binding gs://$BUCKET \
  --member="serviceAccount:$SA_EMAIL" \
  --role="roles/storage.objectAdmin"

バケットの 設定情報 (describe) を見たい 場合は、別途 storage.buckets.get を含むロールが必要です。
例(任意):

gcloud storage buckets add-iam-policy-binding gs://$BUCKET \
  --member="serviceAccount:$SA_EMAIL" \
  --role="roles/storage.legacyBucketReader"

6. 認証/権限のクイックチェック

6.1 Python 側が SA 鍵を使っているか

python - << 'PY'
from google.auth import default
creds, proj = default()
print("Project:", proj)
print("Creds type:", type(creds).__name__)
print("SA email:", getattr(creds, "service_account_email", "N/A"))
PY
# SA email が vision-ocr-sa@... ならOK

6.2 SA でオブジェクトを書けるか(手動テスト)

# SA を gcloud にアクティブ化(または env のみでも可)
gcloud auth activate-service-account "$SA_EMAIL" --key-file=./service-account.json

echo "ok" > /tmp/_gcs_check.txt
gcloud storage cp -v /tmp/_gcs_check.txt gs://$BUCKET/_gcs_check.txt
  • これが通れば storage.objects.create が機能 している証拠です。
  • storage.objects.get のエラーが出る場合は、オブジェクト/バケットの閲覧権限が不足しています(上の legacyBucketReader を追加するか、objectViewer などを検討)。

7. Vision の非同期 OCR スクリプトの実行

以下はサンプルの vision_pdf_ocr.py(要点のみ)です。ローカル PDF → GCS へアップロード → OCR → GCS の JSON をDL → TXT 結合。

from google.cloud import vision, storage
from pathlib import Path
import json, re

def upload_to_gcs(local_file, bucket_name, dst_path):
    client = storage.Client()
    bucket = client.bucket(bucket_name)
    blob = bucket.blob(dst_path)
    blob.upload_from_filename(local_file)  # ← ここで storage.objects.create が必要
    return f"gs://{bucket_name}/{dst_path}"

def async_ocr_pdf_gcs(gcs_source_uri, gcs_destination_uri, mime_type="application/pdf"):
    client = vision.ImageAnnotatorClient()
    feature = vision.Feature(type_=vision.Feature.Type.DOCUMENT_TEXT_DETECTION)
    req = vision.AsyncAnnotateFileRequest(
        features=[feature],
        input_config=vision.InputConfig(gcs_source=vision.GcsSource(uri=gcs_source_uri), mime_type=mime_type),
        output_config=vision.OutputConfig(gcs_destination=vision.GcsDestination(uri=gcs_destination_uri), batch_size=10)
    )
    op = client.async_batch_annotate_files(requests=[req])
    op.result(timeout=1800)

def merge_vision_jsons_to_txt(json_files, out_txt):
    def _key(p):
        m = re.search(r"output-(\d+)-to-(\d+)\.json$", p.name)
        return (int(m.group(1)), int(m.group(2))) if m else (10**9, 10**9)
    pages = []
    for jf in sorted(json_files, key=_key):
        data = json.loads(Path(jf).read_text(encoding="utf-8"))
        for resp in data.get("responses", []):
            txt = resp.get("fullTextAnnotation", {}).get("text", "")
            pages.append(txt)
    Path(out_txt).write_text("\n\n".join(pages), encoding="utf-8")

主要パラメータ

  • BUCKET_NAME:例 my-ocr-bucket-xxxxxx(権限付与済みのバケット名と完全一致に)
  • GCS_INPUT_PATH:例 "inputs/sample.pdf"
  • GCS_OUTPUT_PREFIX:例 "outputs/sample"(末尾の / は関数内で付与推奨)

実行例

python3 vision_pdf_ocr.py

8. よくあるエラーと対処

8.1 403 storage.objects.create / get denied

  • 原因: SA にバケットの権限が無い、または バケットが存在しない/他プロジェクト所有
  • 対処:
    • バケットの存在を確認:gcloud storage ls -b gs://$BUCKET
    • SA に付与:roles/storage.objectAdmin(最低限 objectCreator/objectViewer の組み合わせでも可)
    • バケットが他プロジェクトの場合は そのバケット側で SA にロールを付与。

8.2 INVALID_ARGUMENT: Role roles/vision.user is not supported for this resource

  • 説明: Vision 用の専用ロールが必須というわけではありません。今回のフローでは GCS 権限が肝
  • 対処: roles/vision.user の付与は不要。GCS のバケット権限に集中する。

8.3 The billing account ... absent

  • 原因: 請求アカウント未リンク。
  • 対処: 章 3 の手順でリンク。

8.4 Not found / Permission denied(バケット操作)

  • 原因: バケット名の重複、別プロジェクト所有、権限不足。
  • 対処: 一意な名前で 自分のプロジェクトに作成し直す。

9. 参考コマンド(ワンセット)

# 変数
PRJ="ocr-project-xxxxxx"
SA_EMAIL="vision-ocr-sa@${PRJ}.iam.gserviceaccount.com"
BUCKET="my-ocr-bucket-xxxxxx"

# ログイン & プロジェクト
gcloud auth login
gcloud config set project "$PRJ"

# (必要に応じて)請求リンク
# BILLING="012345-ABCDE0-123456"
# gcloud beta billing projects link "$PRJ" --billing-account="$BILLING"

# バケット作成(存在しなければ)
gcloud storage ls -b gs://$BUCKET || gcloud storage buckets create gs://$BUCKET --location=asia-northeast1

# SA へオブジェクト読み書き権限
gcloud storage buckets add-iam-policy-binding gs://$BUCKET \
  --member="serviceAccount:$SA_EMAIL" \
  --role="roles/storage.objectAdmin"

# (任意)バケット閲覧も必要なら
gcloud storage buckets add-iam-policy-binding gs://$BUCKET \
  --member="serviceAccount:$SA_EMAIL" \
  --role="roles/storage.legacyBucketReader"

# SA 鍵をアクティブ化
gcloud auth activate-service-account "$SA_EMAIL" --key-file=./service-account.json

# 手動テスト
echo "ok" > /tmp/_gcs_check.txt
gcloud storage cp -v /tmp/_gcs_check.txt gs://$BUCKET/_gcs_check.txt

10. 補足:Document AI との違い

  • Cloud Vision API:PDF/TIFF の 全文OCR(テキスト抽出中心)。
  • Cloud Document AI:請求書/フォーム等の 構造化抽出 に強い別プロダクト。今回のスクリプト(Visionの非同期OCR)とは API/ロールが異なります。

以上です。
このドキュメントどおりに進めると、403 などの典型トラブルを回避しながら Vision OCR を実行できます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?