pdf-metadata-fillerlisted
Install: claude install-skill eUmeda/pdf-metadata-filler
# PDF Metadata Filler
PDF ディレクトリの Title/Author/DOI 欠損を多段フォールバックで補完する。
エンジンは OpenAlex/CrossRef/CiNii + OCR + LLM(Gemini/Groq, REST 直叩き)。
(earlier private tooling を統合・置換した公開版, 2026-06)
## 取得チェーン(`fill_pdf_metadata.py`)
```
ファイル名DOI → 本文DOI → OpenAlex(DOI) → CrossRef(DOI)
→ OpenAlex(title) → CrossRef(title) → CiNii(title=和文紀要に強い)
→ (スキャンPDF) OCR(eng+jpn) → LLM テキスト提案(Groq→Gemini)
```
- 書込: 本体は pypdf(アトミック書込: `.pdf.tmp` → `os.replace`。元 PDF は失敗時も無傷)。
helper の `upgrade_matched.py` / `fuzzy_fill.py` は exiftool 書込。
- **バックアップ契約(全書込スクリプト共通)**: 変更前に `<name>.pdf.bak` を**未存在時のみ**作成。
既存 `.bak` は原本なので再実行でも決して上書きしない。バックアップ失敗時はそのファイルを書き込まない。
- DOI は `/Subject` に格納(dedup キー)。title 類似度ゲート(0.6) で誤一致抑止。
LLM は本文に無ければ doi 空(捏造禁止)。
## スクリプト(`scripts/`)
| script | 役割 |
|---|---|
| `fill_pdf_metadata.py` | 本体。`<dir> [--dry-run] [--only-list FILE] [--redo] [--keys PATH]` |
| `verify_proposals.py` | LLM提案(done_groq_proposal)のタイトルを OpenAlex/CrossRef/CiNii 照合 → matched/unmatched/no_title/error(read-only。error=API一時障害、再実行で再照合�� |
| `upgrade_matched.py` | matched を実 DOI/著者で格上げ(exiftool) → status `done` |
| `fuzzy_fill.py` | no-title を 強制OCR(eng+jpn)+ファイル名で LLM ファジー全埋め → `done_fuzzy`(LLM 必須・キー未設定は設定エラーで即終了) |
- helper 3 スクリプトは対象 dir を第1引数(または環境変数 `PAPERS_DIR`)で受け取る。未指定は明示エラー。
- `--keys PATH` は全スクリプト共通。既定の解決順:
`--keys → リポジトリ直下(scripts/ の親)の api_keys.json →(fill_pdf_metadata.py のみ)走査対象 dir`。
- 書込対象パスは対象 dir 内に限定(containment チェック。`../` 等で外の PDF は書き換えない)。
- helper は `exifto