PHPでISBNコードからNDCコードを求める

(1/1)
私は乱読派だが、いちいち本を買っていると置く場所が無くなるし、家計に厳しい。このため、ほとんどの本は図書館から借りて読んでいる(気に入った本は買う)。いちおう、読んだ本の記録は残しているのだが、これをどう分類するか考えた末に、図書館と同じ分類法(NDC;日本十進分類法)を利用することに決めた。
図書館で借りた本は背表紙にNDCコードが貼ってあるからいいのだが、買った本は調べないとわからない。
そこで、前回紹介したISBNコードからNDCコードを求めることはできないか考え、つくったのが今回紹介するプログラムである。

(2020年5月4日)PHP8対応,リファラチェック追加

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

PHPでISBNコードからNDCコードを求める

サンプル・プログラム

このプログラムは国立国会図書館の総合目録ネットワークシステムを呼び出している。
圧縮ファイルの内容
isbn2ndc.phpサンプル・プログラム本体。
isbn2ndc.cfg前回利用時間を保持するファイル。
NDC9.csvNDCの第3次区分表(第9版)ファイル

NDCコード

NDC(Nippon Decimal Classification)は日本十進分類法とも呼ばれ、図書館で書籍を分類するために使われている10進数3桁の数字である。

書籍の出版時にはISBNコードは付与されるが、NDCコードは付与されない。あくまで図書館側が分類して付与するコードである。また、ISBNコードとNDCコードの正しい対応表(データベース)というものも存在しない。
そこで今回は、国立国会図書館の総合目録ネットワークシステムを呼び出し、ISBNコードからNDCコードを求める

解説:初期値

0034: //短縮URL(デフォルト)
0035: define('DEF_ISBN', '9784798135472');
0036: 
0037: //利用間隔(秒;相手システムに負荷をかけないために間隔を開ける)
0038: define('INTERVAL', 10);
0039: 
0040: //NDCの第3次区分表(第9版)を外部ファイル名
0041: define('FNAME_NDC9', './NDC9.csv');
0042: 
0043: //表示幅(ピクセル)
0044: define('WIDTH', 550);

総合目録ネットワークシステムに負荷をかけないため、INTERVAL で定義した間隔より短い間隔でプログラムが実行されないようにしている。

解説:変換処理

0209: /**
0210:  * NDC番号を取り出す
0211:  * @param   string $isbn ISBN番号
0212:  * @return  NDC番号/FALSE=取得失敗
0213: */
0214: function isbn2ndc($isbn) {
0215:     //総合目録ネットワークシステムへ問い合わせ
0216:     $url = "https://iss.ndl.go.jp/books?rft.isbn={$isbn}";
0217:     if (($fp = fopen($url, 'r')) == FALSEreturn FALSE;
0218:     $link = '';
0219:     while (! feof($fp)) {
0220:         $res = trim(fgets($fp));
0221:         if (preg_match("/<div class=\"item_summarywrapper\">/iu", $res) > 0) {
0222:             while (! feof($fp)) {
0223:                 $res = trim(fgets($fp));
0224:                 if (preg_match("/<a href=\"(https?\:\/\/iss\.ndl\.go\.jp\/books\/[a-zA-Z0-9\-]+)\">/iu", $res$arr) > 0) {
0225:                     $link = $arr[1];
0226:                     break;
0227:                 }
0228:             }
0229:         }
0230:     }
0231:     fclose($fp);
0232: 
0233:     //NDC取得シーケンス
0234:     if (($fp = fopen($link, 'r')) == FALSE)        return FALSE;
0235:     $ndc = FALSE;
0236:     while (! feof($fp)) {
0237:         $res = trim(fgets($fp));
0238:         if (preg_match("/<th scope=\"row\">NDC/iu", $res) > 0) {
0239:             while (! feof($fp)) {
0240:                 $res = trim(fgets($fp));
0241:                 if (preg_match("/<td>([0-9\.]+).+<\/td>/iu", $res$arr) > 0) {
0242:                     $ndc = $arr[1];
0243:                     break;
0244:                 }
0245:             }
0246:         }
0247:     }
0248:     fclose($fp);
0249: 
0250:     return $ndc;
0251: }

ISBN番号からNDC番号への変換は、総合目録ネットワークシステムの検索結果をスクレイピングしているだけである。

総合目録ネットワークシステムのアウトプットは変更になるかもしれないので、この部分は適宜変更してほしい。

解説:分類名の取得

0253: /**
0254:  * NDC番号から分類名を取り出す
0255:  * @param   string $ndc NDC番号
0256:  * @return  分類名/FALSE=取得失敗
0257: */
0258: function ndc2class($ndc) {
0259:     $n2 = substr($ndc, 0, 2) . '0';      //NDCの上2桁+'0'
0260:     $n3 = substr($ndc, 0, 3);            //NDCの上3桁
0261:     if (preg_match('/^[0-9]{3}$/', $n3) != 1)    return FALSE;
0262: 
0263:     $res = FALSE;
0264:     if (($fp = fopen(FNAME_NDC9, 'r')) == FALSE)   return FALSE;
0265:     while (! feof($fp)) {
0266:         $arr = fgetcsv($fp, 1000, "\t");
0267:         if ($arr[0] == $n2) {
0268:             $res = $arr[1] . ' - ';
0269:         } else if ($arr[0] == $n3) {
0270:             $res .= $arr[1];
0271:             break;
0272:         }
0273:     }
0274:     return $res;
0275: }

NDCコードという数字だけでは分類名が分かりにくいので、NDCの第3次区分表(第9版)を外部ファイル "NDC9.csv" に持たせ、求めたNDCから引くようにした。

おまけの話

分類したかった書籍約900冊のうち、ISBNがあるのに総合目録ネットワークシステムの検索に引っかからなかった書籍が2冊あった。また、検索にはかかるが、NDCコードが登録されていないものが4冊あった。そもそもISBNコードがない自費出版のような書籍が1冊あった。

このプログラムは、入力されたISBNコードのチェック(アルゴリズムは「PHPでISBNコードをASINコードに変換する」で用いたものと同じ)や、NDCが検出できなかった時にエラーを返すようにしてある。

国立国会図書館には、少なくとも日本国内で出版された全ての書籍がデータベース化されていると信じていたのだが、100%完璧ではないのだということを知らされた。分類作業の苦労が偲ばれる。

質疑応答

【質問】

お疲れ様です。
「isbn2ndc」のサンプルプログラムを実行すると「Sory, system error occured !」とエラーが返されますが、解決手段はごさいますでしょうか?
お手数をお掛けしますが、どうぞよろしくお願いいたします。


【回答】

サーバのタイムゾーン設定によるエラーでした。
プログラムを修正しましたのでお試しください。



【質問】 ゆきむら様

こんばんは、初めまして。
素敵なプログラムをありがとうございます。
PHPプログラムを実行を押すと「Sory, system error occured !」とエラーが出ます。
お忙しい中大変恐縮ですが、お返事頂けますと幸いです。
よろしくお願いいたします。


【回答】

現在、プログラムは正常に動作しています。
冒頭で紹介したとおり、国立国会図書館の総合目録ネットワークシステムを利用しています。相手システムに負荷をかけないよう、一度検索すると、10秒間は検索できないようになっています。また、頻繁に検索を行うと「Sory, system error occured !」と表示する可能性があります。

参考サイト

(この項おわり)
header