書名や著者名に対する読み仮名の情報を揃えたくなったので、国立国会図書館のAPIで検索してみた。
国立国会図書館のAPI
いくつか種類があるが、今回使うのはSRUというプロトコル。検索用API3つの中では最も高機能で、前方一致や完全一致、ソート順の指定などもできる。検索対象のフィールドとしてはタイトル、著者、出版社、NDC分類、ISBN、出版年などが使える。
GETでXMLが落ちてくるので、例えば https://iss.ndl.go.jp/api/sru?operation=searchRetrieve&recordPacking=xml&recordSchema=dcndl&maximumRecords=1&query=title%3D%E3%81%86%E3%82%89%E3%82%89%E8%BF%B7%E8%B7%AF%E5%B8%96%201 をブラウザで開くと見れる。
クエリパラメータを簡単に解説するとこういう感じ。
operation=searchRetrieve
コマンド的なものrecordPacking=xml
検索結果をそのままXMLに埋め込む指定。デフォルトはtextで、XMLが文字列として入ってくる。recordSchema=dcndl
レコードのスキーマを色々選べる。デフォルトのdc
はdcndl
よりもシンプルで、カナ情報とかは入っていない。maximumRecords=1
いわゆるlimitquery=...
検索クエリを CQL (Contextual Query Language) で記述する。ここではtitle=うらら迷路帖 1
。後述。
そしてお目当てのカナ情報は <dcndl:transcription>
タグに入っている。
なおここで取れるデータは別組織から提供を受けたものもあるため、メタデータのライセンスはデータプロバイダごとに異なる。国立国会図書館オンラインのデータだとCC-BY 4.0、とか。
CQLと戦う
queryパラメータに指定するクエリについてはAPIのドキュメントにも説明はあるものの、CQLを知っている前提の説明なのでこれだけだとよくわからない。特に前方一致に使う ^
が exact
等と並列に書かれていてさんざんはまった *1。なのでCQL自身については別途 https://www.loc.gov/standards/sru/cql/spec.html や https://www.loc.gov/standards/sru/cql/contextSets/theCqlContextSet.html などを読むのがよさそう。
もしくは同様のAPIである 国立国会図書館東日本大震災アーカイブのAPIドキュメント を読むと、基本的な使い方や雰囲気は掴める。
とはいえ結局 field =|==|exact|all|any "term" [and/or ...]
で、加えるとしたらソート条件ぐらいだろう。
=
と==
- 半角スペースを含んでいてもフレーズ検索される
- 全角スペースを含むとフレーズ検索ではなくなる
^
は==
だと無視される
exact
での完全一致- 日本語扱いの英字?(NEW GAME! とか)は全角でも半角でもマッチするが、英語扱いの英字は半角でないとマッチしない
NEW GAME!
で言うところのスペースや感嘆符は半角にしないとマッチしない
- メタ文字
^
での前方一致- 前述の「日本語扱いの英字」は全角英字にしないとヒットしない
title = "^NEW" AND creator = 得能正太郎
はよくてtitle = "^NEW" AND creator = 得能正太郎
はダメtitle exact "NEW GAME!"
やtitle = "NEW GAME!"
は大丈夫
- 空白を含むフレーズの前方一致ができない
title = "^foo bar"
は検索結果が0件になるtitle all "^foo bar"
はできるが、これはfooとbarが連続している保証がない- つまり
title = "^foo" and title = "foo bar"
とするのが一番近いだろうか…
- つまり
- CQLの資料を見るに、
adj
とか/string
とかprox
とかが使えればあるいはという気もするが、対応していない様子
- 前述の「日本語扱いの英字」は全角英字にしないとヒットしない
取得結果を読み取る
JSなら例えばこんな感じで。
const title = "..."; const creator = "..."; const xml = await fetch("https://iss.ndl.go.jp/api/sru?operation=searchRetrieve&recordPacking=xml&recordSchema=dcndl&onlyBib=true&maximumRecords=1&query="+encodeURIComponent(`title = "${title}" and creator = "${creator}" and sortBy=issued_date/sort.ascending`)).then(x => x.text()); const doc = new DOMParser().parseFromString(xml, "application/xml"); const title_kana = doc.querySelector('title transcription')?.textContent; const creator_kana = doc.querySelector('creator transcription')?.textContent; console.log(`${title}(${title_kana}) - ${creator}(${creator_kana})`);
XMLはDOMParserを通せばDOMで触れるので、あとはquerySelectorでもなんでも。本当は名前空間を指定した方がいいのだろうけど、querySelectorでやるのも面倒だったので省略。
おまけ
ところでKindleの芳文社創立70周年セールが話題ですね。いい機会なので、たまにはアソシエイトIDを活用してみましょう。
擬人化されていないやつは苦手です、ええもちろん。