
ホンヨムには、本のバーコードからISBNを読み取り、タイトルや著者名などを登録する機能があります。
当初は、ISBNで本を検索すれば、書誌情報と一緒に表紙も取得できると考えていました。
ところが実際に使ってみると、本そのものは見つかっているのに表紙だけ表示されないケースがあります。同じISBNでも、時間を置いて検索すると取得できる場合があり、単純に「表紙なし」と判断することもできません。
取得処理を見直すため、まず利用していたサービス側の状況を確認しました。
調べてみると、openBDでは2023年にデータ提供の仕組みが変わっています。さらに、国立国会図書館サーチでは2026年3月31日に書影APIが終了しました。
そこで現在のホンヨムでは、書誌情報を探す処理と表紙を探す処理を分けています。
この記事では、外部サービス側で起きた変化を確認しながら、ISBNから本を登録する処理をどのように組み直したのかを紹介します。
openBDでは書影の収録状況が変わっていた
ホンヨムでは、ISBNから本を探す最初の取得先としてopenBDを利用しています。
openBDでは、2023年6月5日からJPROによる新しい書誌・書影データの配信が停止しました。
この影響について、openBDは版元ドットコム会員社以外の出版社ではデータ更新に遅れが生じると案内しています。
同年8月には、それまでJPROから提供されていた書誌・書影情報について、国立国会図書館が提供する書誌情報へ切り替える作業が始まりました。
この変更に伴い、openBDは書影の収録範囲が大幅に減少する見込みだと説明しています。
つまり、openBDでISBNに対応する書誌が見つかっても、表紙まで取得できるとは限りません。
ここで「openBDから表紙が返らなかったから表紙なし」と処理すると、別のサービスでは取得できる書影まで探さなくなります。
そのためホンヨムでは、openBDから書誌情報を取得できた場合でも、表紙がなければ書影だけ別の取得先へ回すようにしました。
NDLサーチは書誌情報の取得に使う
openBDで書誌情報が見つからない場合は、国立国会図書館サーチを確認します。
NDLサーチでは現在、次の検索用APIが提供されています。
- SRU
- OpenSearch
- OpenURL
ホンヨムでは、このうちOpenSearchを使って書誌情報を検索しています。
APIの仕様は、NDLサーチの公式ページで確認できます。
一方、ISBNなどを指定して書影を取得できた書影APIは2026年3月31日で終了しました。
国立国会図書館は、データ提供元であるJPROの利用規約改定に伴う対応として終了を案内しています。
そのため、現在のホンヨムではNDLサーチを書誌情報の取得先として利用し、表紙の取得には使っていません。
ISBN検索の流れを簡略化すると、次のようになります。
ISBN
│
├─ キャッシュを確認
│
├─ openBD
│ ├─ 書誌情報
│ └─ 表紙があれば利用
│
└─ NDL Search
└─ 書誌情報
ここで取得するのは、タイトル、著者名、出版社、刊行日などの書誌情報です。
表紙が見つからなかった場合は、別の取得処理へ進みます。
書誌情報と表紙の取得元を分けて管理する
現在のコードでは、書誌情報を取得したサービスと表紙を取得したサービスを別々に記録しています。
enum BookMetadataSource: String, Codable {
case openBD = "openbd"
case ndlSearch = "ndl"
}
enum BookCoverSource: String, Codable {
case openBD = "openbd"
case rakutenBooks = "rakuten"
case openLibrary = "openlibrary"
case googleBooksProxy = "googlebooks-proxy"
case googleBooks = "googlebooks"
}
たとえば、書誌情報はNDLサーチから取得し、表紙はOpen Libraryで見つかる場合があります。
反対に、openBDだけで書誌と表紙の両方が揃えば、後続の表紙検索は不要です。
こうした判断は、現在BookMetadataResolverへまとめています。
検索画面、再取得処理、おすすめ表示などが個別に取得順を持つと、修正した際に画面ごとの挙動がずれるためです。
なお、実際にどの表紙取得先まで使うかは、アプリ側の設定や利用条件によって変わります。登録したサービスをすべて無条件で呼び出しているわけではありません。
Open LibraryではISBNから書影を取得できる
表紙の補完先として利用しているサービスの一つがOpen Libraryです。
Open LibraryのCovers APIでは、ISBNを指定して書影を取得できます。
https://covers.openlibrary.org/b/isbn/{ISBN}-L.jpg
また、?default=falseを付けることで、該当する表紙がない場合に404を返すよう指定できます。
https://covers.openlibrary.org/b/isbn/{ISBN}-L.jpg?default=false
これによって、少なくとも
- 通信そのものに失敗した
- そのISBNでは表紙が見つからなかった
という状態を分けやすくなります。
仕様は公式ドキュメントで確認できます。
ただし、Covers APIにはリクエスト制限があります。
ISBNなど、CoverID・OLID以外の識別子を使ったアクセスでは、5分間に100リクエスト/IPという制限が案内されています。また、大量の書影を一括取得する用途も想定されていません。
そのため、ホンヨムの一括表紙取得では対象を順番に処理しています。
多数のISBNへ一斉にリクエストする方式は採用していません。
「表紙がない」と「取得に失敗した」を分ける
複数の取得先を使い始めると、表紙を取得できなかった理由も分ける必要が出てきました。
現在は、表紙取得の結果を主に次の状態へ分類しています。
found
confirmedAbsent
transientFailure
notConfigured
confirmedAbsentは、問い合わせ自体は成立したものの、表紙が見つからなかった状態です。
一方、タイムアウト、HTTP 429、5xxなどはtransientFailureとして扱います。
この区別が必要なのは、キャッシュへ保存する内容が変わるためです。
一時的な通信障害まで「表紙なし」と記録してしまうと、次回の検索でもその結果を再利用することになります。サービスが復旧していても、表紙を探し直せません。
そこでホンヨムでは、書誌情報をキャッシュから利用しつつ、表紙取得が確定していない場合には書影だけ再検索できるようにしています。
キャッシュには、次の値も保存しています。
let coverLookupWasDefinitive: Bool?
この値によって、表紙が存在しないところまで確認できた場合と、途中で通信に失敗した場合を分けています。
ISBNそのものが見つからなかった場合は5分だけ記録する
ISBNを検索して書誌情報そのものが見つからなかった場合も、永続的な「存在しない本」としては保存していません。
新刊などでは、検索した時点で外部サービス側へデータが反映されていない可能性があります。
しかし、同じISBNを短時間に何度も検索するたび、すべての取得先へ問い合わせるのも無駄になります。
そこで現在は、ISBN検索で何も見つからなかった結果をメモリ上で5分間だけ保持しています。
private static let missCache = ISBNResolutionMissCache()
同じISBNへの短時間の連続アクセスは避けながら、時間が経過すれば再び検索できる仕組みです。
一括表紙取得ではISBNがある本だけを対象にした
ホンヨムには、表紙が設定されていない本をまとめて検索する機能があります。
この処理では、ISBNを持つ本だけを対象にしました。
タイトル検索まで使えば、ISBNを登録していない本にも表紙を付けられる可能性はあります。
ただし、同じタイトルでも次のような違いがあります。
- 単行本
- 文庫版
- 新装版
- 改訂版
- 上下巻やシリーズ違い
個別検索であれば、ユーザーが候補を見て選択できます。一括処理では、一冊ずつ候補を確認しません。
異なる版の表紙を自動登録する可能性があるため、現在はISBNで本を特定できる場合だけ処理する方針にしています。
既に設定されている表紙も上書きしません。
取得できる件数を増やすより、誤った表紙を登録しないことを優先しました。
APIを追加すると利用条件の確認も必要になる
表紙の取得先を増やす過程では、APIの技術仕様だけでなく、各サービスの利用条件も確認しました。
openBD
openBDでは、APIから取得した書誌・書影などについて、本の販促・紹介目的での利用条件が定められています。
また、キャッシュしたデータには変更をできるだけ早く反映し、削除要請があった場合には対応する必要があります。
NDLサーチ
NDLサーチでは、APIを利用するサイトやアプリに対して、NDLサーチのAPIを利用していることの明記が求められています。
メタデータの利用条件はデータ提供機関によって異なるため、実際に利用するデータごとの確認も必要です。
楽天ウェブサービス
楽天ウェブサービスにはクレジット表示のルールがあります。
公式ガイドではテキストによる表示方法の一つとして、次の表記が案内されています。
Supported by Rakuten Developers
Google Books
Google Books APIにも独自の利用規約があります。
現在公開されている規約には、Googleとの別契約または書面による許可がない場合の料金徴収に関する条件などが記載されています。
利用規約の条項が個別のアプリへどのように適用されるかは、コードだけでは判断できません。
そのためホンヨムでは、APIへ接続できることと現在の提供方法で利用できることを分けて確認しています。
調査後に「アプリについて」も修正した
各サービスの利用条件を確認した結果、ホンヨム側にも修正を入れました。
設定画面には以前から「アプリについて」があったため、その中へ**「データと外部サービス」**を追加しています。
現在は、次のサービス名と公式ページへのリンクを確認できます。
- NDL Search API
- openBD
- Open Library
- Google Books
- Supported by Rakuten Developers
表紙取得画面や本棚へクレジットを並べるのではなく、外部サービスに関する情報を「アプリについて」から確認できる構成にしました。
Open Libraryも、公開画面で表紙を利用する場合には、個別の本のページ、Aboutページ、フッターなどからOpen Libraryへリンクすることを推奨しています。
今回の記事を書くために一次情報を確認したことで、記事だけではなくアプリ側にも修正が必要だと分かりました。
取得処理はBookMetadataResolverへまとめた
書誌情報と表紙の取得先が増えると、画面ごとにフォールバック処理を書く方法では管理しにくくなります。
現在は、ISBNから本を取得する処理をBookMetadataResolverへまとめています。
検索・再取得など
│
▼
BookMetadataResolver
│
├─ キャッシュ
├─ openBD
├─ NDL Search
└─ 表紙取得
外部サービス側に変更があった場合は、まずResolver側を確認すれば済みます。
今回のように書影の提供状況が変わっても、検索画面や本棚へ同じ修正を繰り返し入れる必要はありません。
ISBNから本を登録する機能だけを見ると、小さな処理に見えます。
しかし、実際に運用すると、少なくとも次の要素を分けて扱う必要がありました。
- 書誌情報
- 書影
- 通信失敗
- データが存在しない状態
- キャッシュ
- 外部サービスごとの利用条件
現在の構成も固定ではありません。
取得元の仕様や利用条件が変わった場合は、BookMetadataResolverを中心に処理を見直す前提で運用しています。
※この記事で紹介した処理は、iPhone向け読書記録アプリ「ホンヨム」で実際に使っています。