見出し画像

GASを使って書籍の情報管理を行う。

GAS(Google Apps Script)を使って、書籍の裏面にあるバーコードを読み取り、書籍情報を取得。スプレッドシートにその書籍情報を出力する書籍情報管理システムを作ってみました。

目的は、あくまでも家庭にある書籍の整理のためなので、
今回は書籍の裏面についている2つのバーコードのうち、
上のISBNコード(書籍固有の番号)をだけを読み取ります。

その情報をGoogle Books APIs(2024年8月25日現在無料で使用できます)に送り、書籍情報を取得します。
書籍情報は書籍名、著者、出版社、出版日、書籍についての説明文を取得します。

最後に、スプレッドシートに出力し、
書籍情報をスプレッドシート上で管理します。

学校のICT活用としては、
学校図書館の書籍情報を整理しておき、
『各クラスから学校図書館の授業に関係する書籍を探す』
などが考えられます。
(本が多いので、読み取るのが大変だけど、)


書籍JANコードについて

書籍の裏面には2つのパーコード(2つで書籍JANコード)がありますが、
上がISBNコードを表し、下がCコードを表しています。

ISBNコードとは、国際標準図書番号(International Standard Book Number)のことで、世界共通で使われている書籍を識別するために付けられた固有の番号のことです。

また、Cコードとは、書籍の分類を表す日本独自のコードで、販売対象、発行形態、書籍の内容を表しています。


それでは、早速コードを紹介します。作り方は、次のnoteを参照。

コード.gs

function doGet(e) {
  return HtmlService.createHtmlOutputFromFile('index')
  .setTitle("ISBNコードの読み取り");
}

function writeToSheetAndFetchData(barcode) {
  var sheet = SpreadsheetApp.openById('--スプレッドシートのID--').getActiveSheet();
  var bookData = fetchBookData(barcode);
  sheet.appendRow([barcode, bookData.title, bookData.authors, bookData.publisher, bookData.publishedDate, bookData.description, new Date()]);
  return bookData; // 取得した書籍データを返す
}

function fetchBookData(barcode) {
  var url = 'https://www.googleapis.com/books/v1/volumes?q=isbn:' + barcode + '&country=JP';
  var response = UrlFetchApp.fetch(url);
  var data = JSON.parse(response.getContentText());
  
  if (data.totalItems > 0) {
    var book = data.items[0].volumeInfo;
    return {
      barcode: barcode,
      title: book.title || "N/A",
      authors: (book.authors && book.authors.join(', ')) || "N/A",
      publisher: book.publisher || "N/A",
      publishedDate: book.publishedDate || "N/A",
      description: book.description || "N/A"
    };
  } else {
    return {
      barcode: barcode,
      title: "N/A",
      authors: "N/A",
      publisher: "N/A",
      publishedDate: "N/A",
      description: "N/A"
    };
  }
}

※7行目の openById('--スプレッドシートのID--')は、
書籍情報を出力したいスプレッドシートを開き、
スプレッドシートのURL中の
https://docs.google.com/spreadsheets/d/ここの部分/edit?gid=0#gid=0
openById('ここの部分')として、書き直して下さい。


index.html

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/quagga@0.12.1/dist/quagga.min.js"></script>
    <style>
      #scanner-container {
        position: relative;
        width: 100%;
        max-width: 640px;
        margin: 5pt auto;
      }
      video {
        width: 100%;
        muted: true;
        autoplay: true;
        playsinline: true;
      }
      canvas.drawingBuffer {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        pointer-events: none; /* canvas上でのクリックを無効にする */
      }
    </style>
  </head>
  <body>
    <div id="scanner-container"></div>
    <button id="rescan-btn" style="display:none;">ISBNコードを続けて読み取る</button>
    <div id="message"></div>
    <div id="book-info">
      <p><strong>ISBN:</strong> <span id="isbn"></span></p>
      <p><strong>タイトル:</strong> <span id="title"></span></p>
      <p><strong>著者:</strong> <span id="authors"></span></p>
      <p><strong>出版社:</strong> <span id="publisher"></span></p>
      <p><strong>出版日:</strong> <span id="publishedDate"></span></p>
      <p><strong>説明:</strong> <span id="description"></span></p>
    </div>
    <script>
      let scanCounts = {};
      let scanAttempts = 0;
      const maxScans = 7;

      function startScanner() {
        scanCounts = {};
        scanAttempts = 0;
        document.getElementById("message").innerText = "";

        Quagga.init({
          inputStream: {
            name: "Live",
            type: "LiveStream",
            target: document.querySelector('#scanner-container'),
          },
          decoder: {
            readers: ["ean_reader"]
          },
        }, function (err) {
          if (err) {
            console.log(err);
            return;
          }
          Quagga.start();
        });
      }

      Quagga.onDetected(function (result) {
        var code = result.codeResult.code;
        if (code.startsWith("978") || code.startsWith("979")) {
          scanCounts[code] = (scanCounts[code] || 0) + 1;
          scanAttempts++;

          if (scanAttempts >= maxScans) {
            Quagga.stop();
            let mostFrequentCode = Object.keys(scanCounts).reduce((a, b) => scanCounts[a] > scanCounts[b] ? a : b);
            google.script.run.withSuccessHandler(displayBookInfo).writeToSheetAndFetchData(mostFrequentCode);
            document.getElementById("message").innerText = "Barcode: " + mostFrequentCode + " recorded.";
            document.getElementById("rescan-btn").style.display = "block";
          } else {
            document.getElementById("message").innerText = "Scan " + scanAttempts + " of " + maxScans;
          }
        } else {
          document.getElementById("message").innerText = "Invalid barcode. Please scan again.";
        }
      });

      function displayBookInfo(bookData) {
        document.getElementById("isbn").innerText = bookData.barcode;
        document.getElementById("title").innerText = bookData.title;
        document.getElementById("authors").innerText = bookData.authors;
        document.getElementById("publisher").innerText = bookData.publisher;
        document.getElementById("publishedDate").innerText = bookData.publishedDate;
        document.getElementById("description").innerText = bookData.description;
      }

      document.getElementById("rescan-btn").addEventListener("click", function() {
        document.getElementById("rescan-btn").style.display = "none";
        startScanner();
      });

      // 初期化
      startScanner();
    </script>
  </body>
</html>

とりあえず、これで完成です。

ブラウザで開いた画面

Windows PCにてバーコードを読み取ることを想定していますが、スマホやChromebook等で使用する場合には、もしかしたら、index.html内の<style> #scanner-containerのサイズ設定を変更すると良いかもしれません。

また、書籍情報はGoogle Books APIsが持っている情報しか取得できませんので、書籍名、著者、出版社、出版日、書籍についての説明文のうち、必ずしも全ての情報が取得できるわけではありませんので、あしからず。

この記事が気に入ったらサポートをしてみませんか?