ElectronでNFCを使った書籍貸出管理を作ってみる - 書籍検索編

前回のElectronでNFCを使った書籍の貸し出し・返却機能を持ったアプリケーションを作成しました。しかし、このアプリケーションはまだ新規に書籍を登録したり廃棄したりする機能が備わっていません。MySQLへ手動で登録するというのもスマートじゃない。

そこで今回は、新しく購入してきた書籍のISBNコードを読み取って、国会図書館および楽天ブックスAPIの2つを持って、書籍情報を取得。データベースへ登録する機能を搭載したいと思います。基本的にはこのエントリーの移植であり、REST APIを叩いて得たデータをInsert Intoで入れるまでを行います。

今回の検索画面の検索結果テーブルのデザインは、こちらのサイトのCSSをお借りしました。

図:ISBNで検索して情報を取得->DB登録する流れ

今回使用するモジュールやサービス

使用するサービス

カードリーダーとドライバー

Node.jsモジュール

  • keytarモジュール – OS標準のパスワード管理システムを利用して、安全にパスワード等のやり取りをする
  • electron-store – 各種設定情報を格納する為のモジュール
  • Promise-MySQLモジュール – Promiseが使えるMySQLへアクセスする為のモジュール
  • jQueryモジュール – ElectronでjQueryを使えるようにする為のモジュール
  • electron-rebuild – nfc-pcscモジュールをリビルドするために使用します。
  • nfc-pcsc – Node.jsでPC/SC規格準拠のカードリーダーを読み書きする為のモジュール
  • request - HTTP通信を行うために必要なモジュール。今回の主役であり、REST APIを叩くために利用する。
  • xml2json - 面倒なXMLデータをJSON形式に変換するモジュール。

HTML側で利用するライブラリ

requestモジュールについて

モジュールの追加

今回は前回の続きであるので、主役であるrequestモジュールを追加します。また、社内で利用する事から「プロキシー」を経由する事を想定し、利用する場合には事前に通過するプロキシーサーバのアドレスとポート番号が必要になります。

モジュールの追加自体は非常に簡単。特別なことをせずともインストールするだけで利用する事が可能です。

※2019年4月15日 - requestモジュールが今後のアップデートをしないメンテナンスモード(修正のみ)へと移行されるようです。別のモジュールへ移行を促すか?非推奨にするかをIssueにて議論されているようです(すぐに使えなくなるとか、消えてなくなるという事ではない)。代替モジュールについての議論はこちらでなされているようです。

また、同期的に処理が必要だという方は、requestをPromise化したモジュールもあります。その場合は、

で、導入する事が可能です。

通常のアクセスとプロキシー経由のアクセス

特にプロキシーサーバを経由する事がない場合には以下のようなコードで通信をすることが可能です。

しかし、プロキシー経由でなければ外に出られない場合には、モジュールの読み込み後にProxy設定を追加し、その設定で通信を行う必要があります。

  • request.defaultsにプロキシーのアドレスとポートを指定する
  • proxy.getにて通信を行う。

図:きちんとアクセスできた場合

ヘッダーとオプション設定について

HTTPリクエストではこれまでもGoogle Apps ScriptVBAでも紹介してきたように「オプション設定」と「リクエストヘッダー情報」が付き物です。Node.js上のrequestモジュールでもそれは同じ。

ヘッダーについては以下のような記述を行います。ヘッダー指定も基本マニュアルに記載がありますが、省かれている雑なマニュアルもあるので注意が必要です。

特に「REST APIを叩く」場合には、OAuth2.0認証を利用し、access tokenを持って通信を行う事が非常に多いです。その場合のヘッダー情報が「Authorization」であり、Bearerに続けて、Access Tokenの値を繋げて渡します。但しこのAccess Tokenを取得する為のルーチンや、tokenが時間切れかどうかチェックするコード、token時間切れ時にRefresh Tokenを使って再度Access Tokenを取得するなどのコードもまた必要になる事が多いです。

さらにオプション設定では以下のような記述を行います。その際にoptionsにheadersを加えることをお忘れなく。

エンドポイントURLとは、その操作(例えばドライブでファイル操作をするといった事例)の時に使用するURLで、マニュアルに記載が必ずあります。Google Drive API v2の事例で言えば、https://www.googleapis.com/drive/v2がエンドポイントURLとなります。機能別に複数わけられているケースもあれば、1つのエンドポイントでオプション指定で分けていることもあります。

methodは通常はPOSTGETのどちらかですが、例えばBox APIなどの場合には、PUTPATCHDELETEといったメソッドもあります。基本どれも使いて側からしたらメソッド名が変わるくらいで同じですが、これについても相手側サーバのマニュアルに使うべきメソッドの指定があります。

検索するメインルーチン

国会図書館APIの検索と結果

モジュールの追加

今時のウェブサービスの場合、基本的に送信も受信もデータについては「JSON形式」でやり取りが可能なので、JavaScriptの場合非常に簡単に複雑な構造のデータであっても取り扱いが可能です。しかし、前時代のウェブサービスの場合、JSON形式ではなくXML形式でしか対応していないケースが多く、このXMLは構造が非常に複雑で取り扱いも非常に面倒な形式です。

そこで、XMLでパースするのではなくJSONに変換して楽々取得するためのモジュールを追加しておきます。インストール時にnode-gypによるリビルドが発生しますので、きちんとnode-gypが動いている環境である必要があります。

また、このモジュールはそのままではelectronで利用できないので、electron-rebuildにてネイティブ環境用にリビルドする必要があります。

  1. プロジェクトフォルダに入る
  2. electron-rebuild -w xml2jsonを実行する
  3. リビルドが完了したら成功

変換するためのコード

まずは取り込む為のコードです。国会図書館サーチAPIで夜回り猫を探索するとこんな感じで返ってくる。

  • parser変数にxml2jsonモジュールを読み込みます。
  • APIを叩いた結果返ってきたXMLデータをparser.toJson(body)という形で変換しjson変数に格納しています。この時点ですでにJSON化されています。

XMLがどのようにJSONに変換されるか

夜回り猫という面白い本があるのですが、これを国会図書館で検索してみました。まずは普通にXMLで返ってきた値を見てみます。

いわゆる名前空間などが設定されていて、一見すると簡単に取れそうに見えますが、ものすごく面倒臭いです。これをxml2jsonを経由させた場合の値は以下のようになります。

  • rssから始まり、各エレメントが見事にJSON構造になっています。
  • 各エレメントの文字列をそのままJSONとして指定すれば取れるので、めちゃくちゃ楽です。
  • キー名にコロンを含んだものがあるので、この場合には、例えばdc:publisherの値を取りたい場合には、json.rss.channel.item["dc:publisher"]といった形で指定すればJSONから値を取得可能です。XMLだとここがひどく面倒

楽天ブックスAPIで検索した結果

楽天ブックスAPIはJSON形式で返ってくるので非常に楽です。リクエストの方式もシンプルなので、それほど難儀せずにコードを組み立てることが可能です。

楽天ブックスAPI側の準備

楽天ブックス書籍検索APIは、事前にアプリケーションIDの取得が必要です。ISBN検索で引っ張るようにしました。試しに使用したクエリはこちら

APIの取得手順は以下の通り。楽天IDが必要です。今回はいつものようなOAuth2認証を使わないので、APIキーのみでオッケーです。

  1. 新規アプリ登録画面へ行く
  2. アプリ名、アプリのURL(http://127.0.0.1でOK)を入力して、規約に同意して新規アプリを作成をクリック
  3. アプリのデベロッパーIDが表示されますので、この値を控えておきます。プログラムの中で使用します。
  4. コードの中の変数にアプリのデベロッパーIDを記入する

図:アプリIDがそれになります。ほかの項目は不要です。

データを取得する為のコード

ISBNで検索した結果

データを登録するコード

すでに登録済みの本かどうか、ISBNコードでチェックを掛けてから、フォームデータをもとにMySQLへ登録します。今回は必要な個所だけコードを記載しています。

関連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)