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

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

(2019 年 5 月 2 日)総合目録ネットワークシステムの URL を https 対応に変更。

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

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

サンプル・プログラム

このプログラムは国立国会図書館の総合目録ネットワークシステムを呼び出している。

NDCコード

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

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

解説:初期値

0020: //利用間隔(秒;相手システムに負荷をかけないために間隔を開ける)
0021: define('INTERVAL', 10);
0022: 
0023: //NDCの第3次区分表(第9版)を外部ファイル名
0024: define('FNAME_NDC9', './NDC9.csv');

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

解説:変換処理

0193: /**
0194:  * NDC番号を取り出す
0195:  * @param string $isbn ISBN番号
0196:  * @return NDC番号/FALSE=取得失敗
0197: */
0198: function isbn2ndc($isbn) {
0199:     //総合目録ネットワークシステムへ問い合わせ
0200:     $url = "https://iss.ndl.go.jp/books?rft.isbn={$isbn}";
0201:     if (($fp = fopen($url, 'r')) == FALSE)  return FALSE;
0202:     $link = '';
0203:     while (! feof($fp)) {
0204:         $res = trim(fgets($fp));
0205:         if (preg_match("/<div class=\"item_summarywrapper\">/iu", $res) > 0) {
0206:             while (! feof($fp)) {
0207:                 $res = trim(fgets($fp));
0208:                 if (preg_match("/<a href=\"(https?\:\/\/iss\.ndl\.go\.jp\/books\/[a-zA-Z0-9\-]+)\">/iu", $res$arr) > 0) {
0209:                     $link = $arr[1];
0210:                     break;
0211:                 }
0212:             }
0213:         }
0214:     }
0215:     fclose($fp);
0216: 
0217:     //NDC取得シーケンス
0218:     if (($fp = fopen($link, 'r')) == FALSE)     return FALSE;
0219:     $ndc = FALSE;
0220:     while (! feof($fp)) {
0221:         $res = trim(fgets($fp));
0222:         if (preg_match("/<th scope=\"row\">NDC/iu", $res) > 0) {
0223:             while (! feof($fp)) {
0224:                 $res = trim(fgets($fp));
0225:                 if (preg_match("/<td>([0-9\.]+).+<\/td>/iu", $res$arr) > 0) {
0226:                     $ndc = $arr[1];
0227:                     break;
0228:                 }
0229:             }
0230:         }
0231:     }
0232:     fclose($fp);
0233: 
0234:     return $ndc;
0235: }

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

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

解説:分類名の取得

0237: /**
0238:  * NDC番号から分類名を取り出す
0239:  * @param string $ndc NDC番号
0240:  * @return 分類名/FALSE=取得失敗
0241: */
0242: function ndc2class($ndc) {
0243:     $n2 = substr($ndc, 0, 2) . '0';       //NDCの上2桁+'0'
0244:     $n3 = substr($ndc, 0, 3);            //NDCの上3桁
0245:     if (preg_match('/^[0-9]{3}$/', $n3) != 1) return FALSE;
0246: 
0247:     $res = FALSE;
0248:     if (($fp = fopen(FNAME_NDC9, 'r')) == FALSE)    return FALSE;
0249:     while (! feof($fp)) {
0250:         $arr = fgetcsv($fp, 1000, "\t");
0251:         if ($arr[0] == $n2) {
0252:             $res = $arr[1] . ' - ';
0253:         } else if ($arr[0] == $n3) {
0254:             $res .= $arr[1];
0255:             break;
0256:         }
0257:     }
0258:     return $res;
0259: }

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 !」とエラーが返されますが、解決手段はごさいますでしょうか?
お手数をお掛けしますが、どうぞよろしくお願いいたします。


【回答】

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

参考サイト

(この項おわり)
header