Last active
March 17, 2021 05:45
-
-
Save rniwase/28e65f185e779fffa01cd10053792573 to your computer and use it in GitHub Desktop.
テキストファイルからISBNチェックディジット検証・NDLから所蔵データ取得
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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