ISBNの13桁化(ISBN(国際標準図書番号)規格改定等について お知らせ)に伴って、既存のデータベースの10桁を変換するために、作ったものです。
- 10桁、13桁ISBNのチェックデジットの計算
- 10桁ISBNと13桁JANの相互変換
- チェックデジットなしのコードをチェックデジットを付けた10桁、13桁ISBNに変換
入力値は最低9桁あれば、10桁、13桁のISBNに変換できるようにしています。2段目JANコード(C分類、価格)の意味も表示できます。
追記
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)