PHPで国立国会図書館を検索

(1/1)
PHP で「国立国会図書館サーチ」を利用し、書籍を検索するプログラムを作ってみる。また、「PHP で ISBN コードを ASIN コードに変換する」を利用し、検索結果を Amazon にリンクさせる。

また、「PHP で Windows用国立国会図書館検索プログラムをつくる」や「C++で国立国会図書館検索」では、このプログラムを Windows アプリに移植したので参考にされたい。

(2021 年 1 月 6 日)書名読みがな追加,一覧表スタイル変更,PHP8 対応,エラー処理の厳格化

目次

サンプル・プログラムの実行例

PHPで国立国会図書館を検索

サンプル・プログラム

圧縮ファイルの内容
searchNDL.phpサンプル・プログラム本体

WebAPI:国立国会図書館サーチ(OpenSearch)

WebAPI
URL
https://iss.ndl.go.jp/api/opensearch
入力パラメータ
フィールド名 要否 内  容
title いずれか 書名、記事名など。UTF-8エンコード。部分一致。
creator いずれか 著者、編者など。UTF-8エンコード。部分一致。
publisher いずれか 出版社。UTF-8エンコード。部分一致。
ndc いずれか NDC分類。前方一致。
from 任意 検索を開始する出版年月日。YYYY-MM-DD。
until 任意 検索を終了する出版年月日。YYYY-MM-DD。
cnt 任意 取得する検索結果の件数。省略時は200。一度に取得できる最大件数は500。
isbn いずれか ISBNコード。10桁または13桁。前方一致。
mediatype 任意 資料種別
“1”:本
“2”:記事・論文
“3”:新聞
“4”:児童書
“5”:レファレンス情報
“6”:デジタル資料
“7”:その他
“8”:障害者向け資料(障害者向け検索対象資料)
“9”:立法情報
応答データ構造(xml) rss channel title 検索結果タイトル link リクエストURL description 検索結果メモ language 言語 item title タイトル link 国会図書館内URL description 内容 author 作者 category 分類 guid 国会図書館内URL pubDate 出版日 dc:title タイトル dcndl:titleTranscription タイトル(読みがな) dcndl:volume 巻数 dcndl:seriesTitle シリーズ・タイトル dc:publisher 出版社 dc:identifier ISBN dc:identifier JPNO dc:subject NDC item title 繰り返し link ...

解説:初期値設定

0015: define('INTERNAL_ENCODING', 'UTF-8');
0016: mb_internal_encoding(INTERNAL_ENCODING);
0017: mb_regex_encoding(INTERNAL_ENCODING);
0018: define('MYSELF', basename($_SERVER['SCRIPT_NAME']));
0019: define('REFERENCE', 'https://www.pahoo.org/e-soul/webtech/php06/php06-37-01.shtm');
0020: define('TITLE', '国立国会図書館サーチ');
0021: 
0022: //リファラチェック+リリースフラグの設定
0023: if (isset($_SERVER['HTTP_HOST']) && ($_SERVER['HTTP_HOST'] == 'localhost')) {
0024:     define('FLAG_RELEASE', FALSE);
0025:     define('REFER_ON', '');
0026:     ini_set('display_errors', 1);
0027:     ini_set('error_reporting', E_ALL);
0028: else {
0029:     //リリース・フラグ(公開時にはTRUEにすること)
0030:     define('FLAG_RELEASE', TRUE);
0031:     //リファラ・チェック(直リン防止用;空文字ならチェックしない)
0032:     define('REFER_ON', 'www.pahoo.org');
0033: }
0034: 
0035: //入力バリデーション
0036: define('QUERY_MIN',  2);     //検索文字列の最短
0037: define('QUERY_MAX', 40);     //検索文字列の最長
0038: 
0039: //表示幅(ピクセル)
0040: define('WIDTH', 600);
0041: 
0042: //TRUE:書名読みがなを表示する/FALSE:表示しない
0043: define('RUBY', TRUE);
0044: 
0045: //国立国会図書館サーチAPI(変更不可)
0046: define('NDL_URL', 'https://iss.ndl.go.jp/api/opensearch');

いくつかのパラメータを定数に定義している。変更不可としている以外の定数は自由に設定できる。
定数 RUBY は、書名読みがな(応答データの dcndl:titleTranscription 要素の内容)を ruby タグを使って表示するか否かのフラグである。

解説:リクエストURL取得

0286: /**
0287:  * 国立国会図書館サーチAPI のURLを取得する
0288:  * @param string $query   タイトル(UTF-8;部分一致)
0289:  *                         またはISBN(10桁または13桁;完全一致または前方一致)
0290:  *                         【省略不可】
0291:  * @param string $creater 作成者(UTF-8;部分一致)
0292:  * @param string $from    開始出版年月日(YYYY-MM-DD)
0293:  * @param string $until   終了出版年月日(YYYY-MM-DD)
0294:  * @param int    $cnt     出力レコード上限値(省略時=50)
0295:  * @param int    $mediatype 資料種別(省略時=2:本)
0296:  * @return string WebAPI URL
0297: */
0298: function getURL_searchNDL($query$creater='', $from='', $until='', $cnt=50, $mediatype='1') {
0299:     $isbn = '';
0300:     if (preg_match('/^[0-9|\-]+$/', $query) == 1) {
0301:         $title = '';
0302:         $isbn = 'isbn=' . preg_replace('/\-/', '', $query);
0303:     }
0304:     if ($isbn == '') {
0305:         $title = 'title=' . urlencode($query);
0306:     }
0307: 
0308:     $creater = ($creater != '') ? '&creater=' . urlencode($creater) : '';
0309:     $from    = ($from != '')    ? '&from=' . $from : '';
0310:     $until   = ($until != '')   ? '&until=' . $until : '';
0311:     $cnt     = ($cnt > 0)       ? '&cnt=' . $cnt : '';
0312:     $mediatype = ($mediatype != '') ? '&mediatype=' . $mediatype : '';
0313: 
0314:     return NDL_URL . '?' . $title . $isbn . $creater . $from . $until . $cnt . $mediatype;
0315: }

ユーザー関数 getURL_searchNDL は、タイトル、作成者、開始出版年月日、終了出版年月日、出力レコード上限値、資料種別からリクエスト URL を返す。
タイトルには、書名と ISBN のいずれかを指定可能だ。ユーザー関数内で、数値とハイフンならば ISBN として認識する。
また、タイトル以外は省略可能にしてある。

解説:国立国会図書館検索

0317: /**
0318:  * 国立国会図書館サーチAPIを呼び出し結果を配列に格納する
0319:  * @param array  $items   書籍情報格納用
0320:  * @param string $errmsg  エラーメッセージ格納用
0321:  * @param string $query   タイトル(UTF-8;部分一致)
0322:  *                         またはISBN(10桁または13桁;完全一致または前方一致)
0323:  *                         【省略不可】
0324:  * @param string $creater 作成者(UTF-8;部分一致)
0325:  * @param string $from    開始出版年月日(YYYY-MM-DD)
0326:  * @param string $until   終了出版年月日(YYYY-MM-DD)
0327:  * @param int    $cnt     出力レコード上限値(省略時=50)
0328:  * @param int    $mediatype 資料種別(省略時=2:本)
0329:  * @return int 検索結果の件数
0330: */
0331: function searchNDL(&$items, &$errmsg$query$creater='', $from='', $until='', $cnt=50, $mediatype='1') {
0332:     //名前空間
0333:     define('NS_DCMITYPE', 'http://purl.org/dc/dcmitype/');
0334:     define('NS_RDFS', 'http://www.w3.org/2000/01/rdf-schema#');
0335:     define('NS_XSI', 'http://www.w3.org/2001/XMLSchema-instance');
0336:     define('NS_OPENSEARCH', 'http://a9.com/-/spec/opensearchrss/1.0/');
0337:     define('NS_DC', 'http://purl.org/dc/elements/1.1/');
0338:     define('NS_DCNDL', 'http://ndl.go.jp/dcndl/terms/');
0339:     define('NS_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
0340:     define('NS_RCTERMS', 'http://purl.org/dc/terms/');
0341: 
0342:     $errmsg = '';
0343:     $url = getURL_searchNDL($query$creater$from$until$cnt$mediatype);
0344: 
0345: //PHP4用; DOM XML利用
0346:     if (isphp5over() == FALSE) {
0347:         if (($dom = read_xml($url)) == NULL) {
0348:             $errmsg = '国立国会図書館サーチAPIの接続に失敗しました.';
0349:             return (-1);
0350:         }
0351:         $rss = $dom->get_elements_by_tagname('rss');
0352:         $channel = $rss[0]->get_elements_by_tagname('channel');
0353:         $arr = $channel[0]->get_elements_by_tagname('item');
0354:         //レスポンス・チェック
0355:         $count = count($arr);
0356:         if ($count <= 0) {
0357:             $errmsg = '検索結果がありません.';
0358:             return (-1);
0359:         }
0360:         $cnt = 0;
0361:         foreach ($arr as $item) {
0362:             $isbn = '';
0363:             $node = $item->get_elements_by_tagname('identifier');
0364:             foreach ($node as $val) {
0365:                 if (preg_match('/ISBN/iu', (string)$val->get_attribute('type')) == 1)    $isbn = (string)$val->get_content();
0366:             }
0367:             if ($isbn == '')   continue;
0368:             $node = $item->get_elements_by_tagname('title');
0369:             $items[$isbn]['title'] = ($node == NULL) ? '' : (string)$node[0]->get_content();
0370:             $node = $item->get_elements_by_tagname('creator');
0371:             $items[$isbn]['author'] = ($node == NULL) ? '' : (string)$node[0]->get_content();
0372:             $node = $item->get_elements_by_tagname('publisher');
0373:             $items[$isbn]['publisher'] = ($node == NULL) ? '' : (string)$node[0]->get_content();
0374:             $items[$isbn]['NDC'] = '';
0375:             $node = $item->get_elements_by_tagname('subject');
0376:             foreach ($node as $val) {
0377:                 if (preg_match('/NDC/iu', (string)$val->get_attribute('type')) == 1)    $items[$isbn]['NDC'] = (string)$val->get_content();
0378:             }
0379:             $node = $item->get_elements_by_tagname('link');
0380:             $items[$isbn]['url'] = ($node == NULL) ? '' : (string)$node[0]->get_content();
0381:             $node = $item->get_elements_by_tagname('pubDate');
0382:             $items[$isbn]['pubDate'] = ($node == NULL) ? '' : (string)$node[0]->get_content();
0383:             $node = $item->get_elements_by_tagname('volume');
0384:             if ($node != NULL) {
0385:                 $items[$isbn]['title'] = $items[$isbn]['title'] . '' . (string)$node[0]->get_content() . '';
0386:             }
0387:             $node = $item->get_elements_by_tagname('titleTranscription');
0388:             if ($node != NULL) {
0389:                 $str = (string)$node[0]->get_content();
0390:                 $str = preg_replace('/[  ]/ui', '', $str);
0391:                 $str = mb_convert_kana($str, 'c');
0392:             } else {
0393:                 $str = '';
0394:             }
0395:             $items[$isbn]['yomi'] = $str;
0396:             $cnt++;
0397:         }
0398: 
0399: //PHP5用; SimpleXML利用
0400:     } else {
0401:         $xml = @simplexml_load_file($url);
0402:         if ($xml == FALSE) {
0403:             $errmsg = '国立国会図書館サーチAPIの接続に失敗しました.';
0404:             return FALSE;
0405:         }
0406:         //レスポンス・チェック
0407:         $count = @count($xml->channel->item);
0408:         if ($count <= 0) {
0409:             $errmsg = '検索結果がありません.';
0410:             return (-1);
0411:         }
0412:         $cnt = 0;
0413:         foreach ($xml->channel->item as $item) {
0414:             //ISBN,書名,著者,出版社,NDC番号,URL,出版日
0415:             $node = $item->children(NS_DC);
0416:             $isbn = '';
0417:             foreach ($node->identifier as $id) {
0418:                 if (preg_match('/ISBN/iu', (string)$id->attributes(NS_XSI)) == 1) $isbn = (string)$id;
0419:             }
0420:             if ($isbn == '')   continue;
0421:             $items[$isbn]['title']     = (string)$node->title;
0422:             $items[$isbn]['author']    = (string)$node->creator;
0423:             $items[$isbn]['publisher'] = (string)$node->publisher;
0424:             $items[$isbn]['NDC'] = '';
0425:             foreach ($node->subject as $id) {
0426:                 if (preg_match('/NDC/iu', (string)$id->attributes(NS_XSI)) == 1) $items[$isbn]['NDC'] = (string)$id;
0427:             }
0428:             $items[$isbn]['url'] = (string)$item->link;
0429:             $items[$isbn]['pubDate'] = (string)$item->pubDate;
0430:             //巻数,書名読みがな
0431:             $node = $item->children(NS_DCNDL);
0432:             if ($node->volume != '') {
0433:                 $items[$isbn]['title'] = $items[$isbn]['title'] . '' . (string)$node->volume . '';
0434:             }
0435:             $str = (string)$node->titleTranscription;
0436:             $str = preg_replace('/[  ]/ui', '', $str);      //空白除去
0437:             $str = mb_convert_kana($str, 'c');       //カタカナ→ひらがな変換
0438:             $items[$isbn]['yomi'] = $str;
0439:             $cnt++;
0440:         }
0441:     }
0442: 
0443:     return $cnt;
0444: }

ユーザー関数 searchNDL は国立国会図書館サーチ API 呼び出し、検索結果を配列 $items に格納し、検索結果の件数を返す。
サンプル・プログラムでは、引数 $query にタイトルまたは ISBN を渡すことで検索を行う。$creater 以降の引数はデフォルト値のままにしてあるが、ぜひ、これらの引数を利用したプログラムを作ってみてほしい。

検索結果の XML 構造は RSS 2.0 に似ており、PHP5(SimpleXML)では名前空間に注意が必要だ。名前空間については「PHP でコロンを含む XML要素名を扱う方法」を参照のこと。ここでは、各々の名前空間を定数で定義している。

検索結果の ISBN から ASIN を求め Amazon へのリンクを張る部分は、「PHP で ISBN コードを ASIN コードに変換する」のサンプル・プログラムを流用している。

エラーが発生した場合、引数 $errmsg にエラーメッセージを格納する。エラーがなければ空文字を代入する。
これら以外の部分は、いままで紹介したプログラムと同じである。

質疑応答

【質問】

「PHP で国立国会図書館を検索」のページ大変参考になります。使用させていただきたいと思っています。
ところで、本のタイトルの読みは XML では <dcnl:titleTranscription> とあるのですが、上記の PHP でフリガナの取得はできないのでしょうか。どのようにすれば可能なのでしょうか?教えていただけませんか。
本のサイズ<extent>は何とか取得することができたのですが。
<dc;title>などと <dcnl:titleTranscription> などとの記述の違いが判りません。
教えていただけるとありがたいのですが。


【回答】

お気づきのように、WebAPI の応答にある <dcnl:titleTranscription> に書名の読み仮名(全角カタカナ)が入っています。
読みがなを含めて取得・表示するようプログラムを改良しました。お試しください。


【質問】

ルビ入りのプログラムを作成くださりありがとうございます。参考にさせていただきます。
今後ともよろしくお願いいたします。


【回答】

どういたしまして😀
ご活用ください。

参考サイト

(この項おわり)
header