Skip to content

Instantly share code, notes, and snippets.

@rniwase
Last active March 17, 2021 05:45
Show Gist options
  • Save rniwase/28e65f185e779fffa01cd10053792573 to your computer and use it in GitHub Desktop.
Save rniwase/28e65f185e779fffa01cd10053792573 to your computer and use it in GitHub Desktop.
テキストファイルからISBNチェックディジット検証・NDLから所蔵データ取得
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ISBNコードが羅列されたテキストファイル<isbn_code.txt>から所蔵データを取得して,
# カンマ区切りのテキストファイル<rec_data.txt>を出力します.
# --- プログラムの利用について ---
# このプログラムは国立国会図書館サーチ(NDL Search)APIを利用します.
# サーバへの過負荷を避けるために,本プログラムの継続的な利用は避けてください.
# NDL Search APIの利用については次のURLを参照してください.
# http://iss.ndl.go.jp/information/api/riyou/
# <isbn_code.txt>のデータ記述例
'''
9784873117386
9784873117393
978-4-87311-778-2
978-4-87311-753-9
4-900900-64-8
4-87311-196-X
ISBN978-4-87311-276-3
'''
import urllib.request
import xml.etree.ElementTree as ET
import csv
url = 'http://iss.ndl.go.jp/api/sru?operation=searchRetrieve&query=isbn=' # NDL SRU API
rec_ns = '{http://purl.org/dc/elements/1.1/}'
def checkDigitISBN(isbn):
isbn_rfm = isbn
for r in ['ISBN', ' ', '-', '\r', '\n', '\t']: # 無視する文字列
isbn_rfm = isbn_rfm.replace(r, '')
try:
if len(isbn_rfm) < 10:
raise ValueError('ISBNコードは10桁または13桁です')
if isbn_rfm[:-1].isdigit() and (isbn_rfm[-1] == 'X' or isbn_rfm[-1].isdigit()) == False:
raise ValueError('ISBNコードに不正な文字が含まれています')
isbn_num = list(map(int, isbn_rfm[:-1]))
isbn_cd = int(isbn_rfm[-1].replace('X', '10'))
if len(isbn_rfm) == 13: # 13桁 ISBNコード
tmp = sum(isbn_num[0:12:2]) + 3 * sum(isbn_num[1:12:2])
tmp = int(str(tmp)[-1])
check_digit = 10 - tmp
if check_digit == 10:
check_digit = 0
elif len(isbn_rfm) == 10: # 10桁 ISBNコード
tmp = sum(
[x * y for (x, y) in zip(list(range(10, 1, -1)), isbn_num)])
check_digit = 11 - tmp % 11
else:
raise ValueError('ISBNコードは10桁または13桁です')
if check_digit != isbn_cd:
raise ValueError('ISBNコードのチェックディジットが不正です')
else:
return isbn_rfm
except ValueError as e:
print(str(e) + ': {0}'.format(isbn))
return None
def getRecordTree(isbn):
with urllib.request.urlopen(url + isbn) as response:
sru_data = response.read()
sru_root = ET.fromstring(sru_data)
if len(sru_root[4]) == 0: # NDLに所蔵データなし
print('NDLに所蔵データがありません')
return []
rec_data = sru_root[4][0][2].text # records/record/recordData
rec_tree = ET.fromstring(rec_data)
return rec_tree
def parseRecordTree(tree, tag):
return tree.find(rec_ns + tag).text
if __name__ == '__main__':
infile = open('isbn_code.txt', 'r')
outfile = open('rec_data.txt', 'w')
writer = csv.writer(outfile, quotechar='\"')
header = ['', 'タイトル', '作者', '出版社', 'ISBNコード', '備考']
writer.writerow(header)
while True:
line = infile.readline()
if line.isspace():
continue
elif line == '':
break
print('inline: ' + line)
r_isbn = checkDigitISBN(line)
if r_isbn != None:
rec_t = getRecordTree(r_isbn)
if rec_t:
print([rd.text for rd in rec_t])
w_d = ['',
parseRecordTree(rec_t, 'title'),
parseRecordTree(rec_t, 'creator'),
parseRecordTree(rec_t, 'publisher'),
r_isbn,
'']
else:
w_d = ['record not found']
else:
w_d = ['error']
writer.writerow(w_d)
infile.close()
outfile.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment