ISBNの13桁化(ISBN(国際標準図書番号)規格改定等について お知らせ)に伴って、既存のデータベースの10桁を変換するために、作ったものです。
- 10桁、13桁ISBNのチェックデジットの計算
- 10桁ISBNと13桁JANの相互変換
- チェックデジットなしのコードをチェックデジットを付けた10桁、13桁ISBNに変換
入力値は最低9桁あれば、10桁、13桁のISBNに変換できるようにしています。2段目JANコード(C分類、価格)の意味も表示できます。
追記
- 単に10桁を13桁にするだけなら、「モジュラス10ウエイト3とisbn10to13」をどうぞ。
- プログラムじゃなくて、とにかく今すぐ10桁13桁相互変換をしたいばあいは、「ISBN10桁13桁相互変換CGI」をどうぞ。
isbnlib.py
※最新版はGist:227568をどうぞ。
#!/usr/bin/env python # -*- coding: utf-8 -*- """ISBN(国際標準図書番号)規格改定 http://www.isbn-center.jp/whatsnew/kikaku.html ISBNコードをいろいろするライブラリ。isbnlib.py """ import os,sys #13桁ISBNの接頭文字 ISBN13_PREFIX = ('978','979') #書籍JANの接頭文字(ISBNと同様) JAN_PREFIX_1ST = ISBN13_PREFIX #書籍JAN2段目の接頭文字 JAN_PREFIX_2ND = ('192','191') #2005年12月現在、10桁に対して付加する接頭文字 ISBN13=ISBN13_PREFIX[0] def cd10(code): """10桁ISBNのチェックデジットを計算して返す。 http://www.kikuchi.biz-web.jp/barcodefile/ISBN.html """ s = str(code)[:9] w = 10 a = 0 for i in range(len(s)): a = a + (int(s[i]) * w) w -= 1 d = 11 - (a % 11) if d == 10: d = "X" if d == 11: d = "0" return d def cd13(code): """13桁ISBNのチェックデジットを計算して返す。 http://www.isbn-center.jp/whatsnew/kikaku.html """ s = str(code)[:12] a = b = 0 for i in range(0,len(s),2): a = a + int(s[i]) for i in range(1,len(s),2): b = b + int(s[i]) d = (a + (b*3)) % 10 if d>0: d = 10 - d return d def cdjan(s): return cd13(s) class ISBN(object): """10桁と13桁のISBNを相互変換するクラス """ def __init__(self, anyisbn): """クラスの初期化 9桁(チェックデジットなし)、10桁、13桁(JAN)のいずれの形式でも 受け入れる。逆にそれ以外は受け入れない。 """ self.raw = None anyisbn = anyisbn.strip().upper().replace('ISBN','').replace('-','') if len(anyisbn) in (9,10): self.raw = anyisbn[:9] elif len(anyisbn)==13: self.raw = anyisbn[3:12] else: raise ValueError,"ISBN [%s] length error. should be 9 or 10 or 13" % anyisbn def isbn10(self): return "%s%s" % (self.raw,self.old_checkdegit()) def oldstyle(self): return self.isbn10() def old_checkdegit(self): return cd10(self.raw) def isbn13(self): return "%s%s%s" % (ISBN13,self.raw,self.new_checkdegit()) def newstyle(self): return self.isbn13() def new_checkdegit(self): return cd13(ISBN13+self.raw) class CCode(object): """Cコード(バーコードの2段目に含まれている)の内容を保持しているクラス。 """ _target = (u"一般",u"教養",u"実用",u"専門","None",u"婦人",u"学参I (小・中学生対象)",u"学参II(高校生対象)",u"児童 (中学生以下対象)",u"雑誌扱い") _style = (u"単行本",u"文庫",u"新書",u"全集・双書",u"ムック・その他",u"事・辞典",u"図鑑",u"絵本",u"磁性媒体など",u"コミック") _ndc = (u"総記",u"百科事典",u"年鑑","None",u"情報科学","None","None","None","None","None", u"哲学",u"心理(学)",u"倫理(学)","None",u"宗教",u"仏教",u"キリスト教","None","None","None", u"歴史・総記",u"日本歴史",u"外国歴史",u"伝記","None",u"地理",u"旅行","None","None","None", u"社会科学総記",u"政治(含む国防軍事)",u"法律",u"経済・財政・統計",u"経営","None",u"社会",u"教育","None",u"民族風習", u"自然科学総記",u"数学",u"物理学",u"化学",u"天文・地学",u"生物学","None",u"医学・薬学","None","None", u"工学工業総記",u"土木",u"建築",u"機械",u"電気",u"電子・通信",u"海事",u"採鉱・冶金",u"その他工業","None", u"産業総記",u"農林業",u"水産業",u"商業","None",u"交通通信業","None","None","None","None", u"芸術総記",u"絵画・彫刻",u"写真・工芸",u"音楽・舞踏",u"演劇・映画",u"体育・スポーツ",u"諸芸・娯楽",u"家事","None",u"コミック・劇画" u"語学総記",u"日本語",u"英米語","None",u"ドイツ語",u"フランス語","None",u"外国語","None","None", u"文学総記",u"日本文学総記",u"日本文学詩歌",u"日本文学小説","None",u"日本文学・評論・随筆その他","None",u"外国文学小説",u"外国文学その他","None") def __init__(self,ccode=None): self.raw = ccode if self.raw: self.target = int(ccode[0:1]) self.targetv = self._target[self.target] self.style = int(ccode[1:2]) self.stylev = self._style[self.style] self.ndc = int(ccode[2:4]) self.ndcv = self._ndc[self.ndc] def __str__(self): return self.raw class BookJAN(ISBN): """2段目バーコードのデータをCコードと価格に分類するクラス。 Cコードの細かい内容はCCodeクラスが管理する。 """ def __init__(self, input): if len(input)==13: if input[:3] in JAN_PREFIX_1ST: super(BookJAN,self).__init__(input) self.ccode = None self.price = None elif input[:3] in JAN_PREFIX_2ND: self.raw = input self.ccode = CCode(self.raw[3:7]) self.price = int(self.raw[7:12]) else: raise Exception,"[%s] does not valid Book JAN code" % input else: raise Exception,"[%s] does not valid Book JAN code" % input def test(encoding='euc-jp'): """テストルーチン""" tests = ('494999908','4798108545', '4-7741-2228-9','ISBN4-7741-2228-9','isbn4774122289', 'ISBN450123456','12345678901','9784398470270','9784817180148') print "="*20 print " ISBN" print "="*20 for c in tests[0:4]: isbn = ISBN(c) print "Raw ",isbn.raw,"[<-",c,"]" print "Old ",isbn.oldstyle() print "New ",isbn.newstyle() print "" print "="*20 print " Book JAN" print "="*20 tests = ('9784398470270','9784817180148') for c in tests[0:4]: jan = BookJAN(c) print "RAW ",jan.raw print "New ",jan.newstyle() print "" print "="*20 print " Book JAN CCode" print "="*20 tests = ('1910193003605','1923055038004') for c in tests[0:4]: jan = BookJAN(c) print "RAW ",jan.raw if jan.ccode: print "C-CODE ",jan.ccode print "C-CODE.Target ",jan.ccode.target,' :',jan.ccode.targetv.encode(encoding) print "C-CODE.Style ",jan.ccode.style,' :',jan.ccode.stylev.encode(encoding) print "C-CODE.NDC ",jan.ccode.ndc,':',jan.ccode.ndcv.encode(encoding) print "PRICE ",jan.price print "" idx = 0 cc = 0 for c in CCode()._ndc: print idx, if c: print c.encode(encoding) cc += 1 else: print c idx += 1 print cc,'/',len(CCode()._ndc) if __name__=='__main__': encoding = "euc-jp" if sys.platform == 'win32': encoding="cp932" test(encoding)