このドキュメントは、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 を実行できます。