書籍情報の探索先として国立国会図書館とGoogleBooks
authorOHASHI, Norikazu <katz@neko-mori.sakura.ne.jp>
Mon, 6 May 2019 02:58:46 +0000 (11:58 +0900)
committerOHASHI, Norikazu <katz@neko-mori.sakura.ne.jp>
Mon, 6 May 2019 02:58:46 +0000 (11:58 +0900)
sinatra/app/models/books_db.rb

index 00ea5d2..c74758b 100644 (file)
@@ -6,6 +6,7 @@ require 'active_record'
 require 'mysql2'
 require 'httpclient'
 require 'json'
+require "rexml/document"
 require 'digest/sha2'
 
 # DB設定ファイルの読み込み
@@ -76,6 +77,12 @@ class BookManager
   # openBDから取得
   SEARCH_ON_OPENBD = 2
 
+  # Google Books から取得
+  SEARCH_ON_GBS = 3
+  
+  # 国立国会図書館 から取得
+  SEARCH_ON_NDL = 3
+
   # ISBNの文字列から "-" を削除
   # @param [String] isbn 処理対象のISBN
   # @return [String] 変換後のISBN
@@ -128,27 +135,50 @@ class BookManager
     return book_hash
   end
 
+  # 書影のURLを国立図書館のAPIより取得する。
+  # @param [String] isbn 対象のISBN
+  # @return [String] 取得したURI
+  def self.getCover(isbn)
+    cover_uri = "https://iss.ndl.go.jp/thumbnail/#{isbn}"
+    client = HTTPClient.new
+    res = client.get(cover_uri)
+
+    if (res.status == 200)
+      return cover_uri
+    else
+      return nil
+    end
+  end
+  
+  # 著者種別から各関係者ハッシュのキーを取得
+  # @param [String] job 著者種別
+  # @return [Symbol] ハッシュキー
+  def self.getParsonKey(job)
+    case job
+    when "著", "著者", "作者", "作" then
+      key = :author
+    when "イラスト", "画", "作画" then
+      key = :illustrator
+    when "翻訳", "訳" then
+      key = :translator
+    when "原著", "原" then
+      key = :original_author
+    when "監修", "監" then
+      key = :supervisor
+    else
+      key = :author
+    end
+    return key
+  end
+  
   # openBDの著者情報から各関係者ハッシュを作成
   # @param [String] parsons 著者情報
   # @return [Hash] 関係者ハッシュ
-  def self.getParsons(parsons)
+  def self.getParsonsFromOpenBD(parsons)
     parsons_hash = {}
     parsons.split(" ").each do |item|
-      name, jobs = item.split("/")
-      case jobs
-      when "著", "著者", "作者", "作" then
-        key = :author
-      when "イラスト", "画", "作画" then
-        key = :illustrator
-      when "翻訳", "訳" then
-        key = :translator
-      when "原著", "原" then
-        key = :original_author
-      when "監修", "監" then
-        key = :supervisor
-      else
-        key = :author
-      end
+      name, job = item.split("/")
+      key = getParsonKey(job)
       if ( parsons_hash[key] == nil || parsons_hash[key] = "")
         parsons_hash[key] = name
       else
@@ -176,7 +206,7 @@ class BookManager
       return nil
     end
     book = books[0]["summary"]
-    parsons = getParsons(book["author"])
+    parsons = getParsonsFromOpenBD(book["author"])
     book_hash = {
       search_type: SEARCH_ON_OPENBD,
       isbn: book["isbn"],
@@ -187,10 +217,105 @@ class BookManager
       original_author: parsons[:original_author],
       translator: parsons[:translator],
       supervisor: parsons[:supervisor],
-      illustrator: book[:illustrator],
+      illustrator: parsons[:illustrator],
       publisher: book["publisher"],
       pubdate: book["pubdate"],
-      cover_uri: book["cover"]
+      cover_uri: (book["cover"] != nil) && (book["cover"] != "") ? book["cover"] : getCover(isbn)
+    }
+    return book_hash
+  end
+  
+  # 国立国会図書館の著者情報から各関係者ハッシュを作成
+  # @param [String] parsons 著者情報
+  # @return [Hash] 関係者ハッシュ
+  def self.getParsonsFromNDL(parsons)
+    parsons_hash = {}
+    parsons.each do |item|
+      splitData = item.split(" ")
+      name = splitData[0...splitData.size-1].join(" ")
+      job = splitData[splitData.size-1]
+      key = getParsonKey(job)
+      if ( parsons_hash[key] == nil || parsons_hash[key] = "")
+        parsons_hash[key] = name
+      else
+        parsons_hash[key] += ", " + name
+      end
+    end
+    return parsons_hash
+  end
+  
+  # ISBNからopenBDを検索してハッシュで返却
+  # @param [String] isbn 
+  # @return [Hash] 書籍情報
+  def self.getHashOfNDL(isbn)
+    client = HTTPClient.new
+    res = client.get("http://iss.ndl.go.jp/api/sru",
+                     {'operation' => 'searchRetrieve',
+                      'query' => "isbn=#{isbn}",
+                      'recordSchema' => 'dcndl'})
+    library_param = REXML::Document.new(res.body)
+    book_num = library_param.elements['//searchRetrieveResponse/numberOfRecords'].text.to_i
+    if (book_num < 1)
+      return nil
+    end
+    element_str = library_param.elements["//searchRetrieveResponse/records/record[#{book_num}]/recordData"].text
+    book_xml = REXML::Document.new(element_str)
+    book = book_xml.elements['//rdf:RDF/dcndl:BibResource/']
+    creators = []
+    book.elements.each('dc:creator') do |item|
+      creators << item.text
+    end
+    parsons = getParsonsFromNDL(creators)
+    book_hash = {
+      search_type: SEARCH_ON_OPENBD,
+      isbn: isbn,
+      title: book.elements['dcterms:title'] != nil ? book.elements['dcterms:title'].text : nil,
+      volume: book.elements['dcndl:volume/rdf:Description/rdf:value'] != nil ? book.elements['dcndl:volume/rdf:Description/rdf:value'].text.gsub(/[^\d]/, "").to_i : nil,
+      series: book.elements['dcndl:seriesTitle/rdf:Description/rdf:value'] != nil ? book.elements['dcndl:seriesTitle/rdf:Description/rdf:value'].text : nil,
+      author: parsons[:author],
+      original_author: parsons[:original_author],
+      translator: parsons[:translator],
+      supervisor: parsons[:supervisor],
+      illustrator: parsons[:illustrator],
+      publisher: book.elements['dcterms:publisher/foaf:Agent/foaf:name'] != nil ? book.elements['dcterms:publisher/foaf:Agent/foaf:name'].text : nil,
+      pubdate: book.elements['dcterms:date'] != nil ? book.elements['dcterms:date'].text.gsub(".","-") : nil,
+      cover_uri: getCover(isbn)
+    }
+    return book_hash
+  end
+
+  # ISBNからGoogleBooksを検索してハッシュで返却
+  # @param [String] isbn 
+  # @return [Hash] 書籍情報
+  def self.getHashOfGBS(isbn)
+    client = HTTPClient.new
+    res = client.get("https://www.googleapis.com/books/v1/volumes", q: "isbn:#{isbn}")
+    books = JSON.parse(res.body)
+
+    if (books["totalItems"] > 1)
+      raise FailedGetInstance
+    end
+    if (books["totalItems"] < 1)
+      return nil
+    end
+    if (books["items"] == nil || books["items"][0] == nil)
+      return nil
+    end
+    book = books["items"][0]["volumeInfo"]
+    book_hash = {
+      search_type: SEARCH_ON_GBS,
+      isbn: isbn,
+      title: book["title"],
+      volume: book["volume"],
+      series: nil,
+      author: book["authors"].join(", "),
+      original_author: nil,
+      translator: nil,
+      supervisor: nil,
+      illustrator:nil,
+      publisher: book["publisher"],
+      pubdate: book["publishedDate"],
+      cover_uri: (book["imageLinks"] != nil) ? book["imageLinks"]["thumbnail"] : getCover(isbn)
     }
     return book_hash
   end
@@ -219,8 +344,10 @@ class BookManager
   end
   
   private_class_method :toIsbn, :deleteBookOfCollection,
-                       :getHashOfBooks, :getParsons, :getHashOfOpenBD,
-                       :createBookHash
+                       :getHashOfBooks, :getParsonKey, :getCover,
+                       :getParsonsFromOpenBD, :getHashOfOpenBD,
+                       :getParsonsFromNDL, :getHashOfNDL,
+                       :getHashOfGBS, :createBookHash
 
   # 書影情報登録
   # @param [String] isbn 画像を登録するISBN
@@ -297,6 +424,12 @@ class BookManager
     if (book_info == nil)
       book_info = getHashOfOpenBD(isbn)
     end
+    if (book_info == nil)
+      book_info = getHashOfNDL(isbn)
+    end
+    if (book_info == nil)
+      book_info = getHashOfGBS(isbn)
+    end
     if (book_info == nil)
       book_info = {isbn: isbn}
     end