argius note

プログラミング関連

iPhoneでバーコードリーダーでISBNを読み取ってサーバーに送る

iPhoneで書籍のバーコードを読み取ってサーバーに送るにはどうしたら良いのかな、と思って調べた結果です。

はじめに

書籍の記録をするのに、ISBNを手打ちでやっていたのですが、これってiPhoneとバーコードでできるよね?と思いながらもずっと放ったらかしていたので、この度は復活したことだし良い機会だからということでやってみました。

バーコードを読んでISBNを取得する部分は、便利なアプリやサンプルコードがすぐに見つかったので、それ自体は苦労せずに実現できました。

あとは、サーバーに送る部分ですが、ただ送るだけでは面白くありませんので、今回は、Pythonの標準機能だけでCGIスクリプトを書いて、サーバーサイドでWebサービスを使って書籍情報を取得する、というサンプルを作ってみました。

参考にしたサイト

環境

サーバーサイド処理を書く言語は、Pythonに限らず特定の言語である必要性は皆無ですが、WebAPIのレスポンスがXMLなので、XMLを処理しやすい言語が良いでしょう。

仕様

一次元バーコードを読み取る

参考サイトの『たった26行で~』の記事によれば、一次元バーコードを読み取るには、pic2shop というアプリを使えば良いみたいです。

コールバックURLを指定すると、その後ろに?r={ISBN13コード}というクエリーパラメーターを付加してURLにリダイレクトしてくれます。
一点、注意が必要で、pic2shopのリダイレクト先は、デフォルトブラウザーSafari 1になってしまいます。つまり、例えChromeでページを開いて実行しても、結果はSafariで開いてしまうのです。これは仕方ないことですね。 ちなみに、このアプリを呼び出す方式については、キーワード「カスタムURLスキーム」で検索すると知ることができます。これはもちろん、pic2shop以外にも利用されている仕組みです。

サーバーサイド処理

ここは何でも良いのですが、スクリプト言語の中でも使い慣れているPythonで書いてみました。
今回は、標準機能だけを使ったCGIスクリプトを実装しました。

サーバー側でWebサービスを呼び出す

書籍情報を取得するには、AWSを使うのが最も詳細に情報が得られるかも知れませんが、今回はサンプルなので、誰でも使える国立国会図書館サーチのWebAPIを利用しました。
このWebAPIの仕様については、前述の参考サイトに書かれています。

URLのパラメーターにISBNを指定すれば、結果をXMLで返してくれます。
プロトコルは、OpenSearchを選択しました。

具体例は、後述のコード例をご覧ください。

実装

コード例

かなり雑なコードですが、今回はその辺はあまり重要でないので顧みません。

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import cgi

fields = cgi.FieldStorage()
isbn13 = fields.getfirst("r", "")
bookinfo = ""
if isbn13:
    import urllib.request
    url = "http://iss.ndl.go.jp/api/sru?operation=searchRetrieve&query=isbn=" + isbn13
    with urllib.request.urlopen(url) as res:
        xml = res.read()
        import xml.etree.ElementTree as ET
        root = ET.fromstring(xml)
        if len(root[4]) > 0:
            dc = ET.fromstring(root[4][0][2].text)
            ns = {"dc": "http://purl.org/dc/elements/1.1/"}
            # タイトル, 著者, 出版社
            title = dc.find("dc:title", ns).text
            author = dc.find("dc:creator", ns).text
            publisher = dc.find("dc:publisher", ns).text
            bookinfo = title + ", " + author + ", " + publisher
        else:
            bookinfo = "見つかりませんでした"

html = """
<!DOCTYPE html>
<html lang="ja">
<style>
h1 { font-size: 320%%; }
p { font-size: 300%%; }
input { font-size: 360%%; }
</style>
<body>

<script>
function scanBarcode() {
    var callbackUri = encodeURIComponent(location.origin + location.pathname + "?r=EAN")
    document.location = "pic2shop://scan?callback=" + callbackUri
}
</script>

<h1>書籍バーコード読み取り&検索</h1>

<p>書籍情報: %s</p>

<input type="button" value="バーコード読み取り" onclick="scanBarcode();" />

<p>Python デバッグ情報 FieldStorage: %s</p>
</body>
</html>"""
print("Content-type: text/html\n\n", html % (bookinfo, str(fields)))

実行結果

f:id:argius:20170403132243p:plain

うまく連携できているようです。


おわりに

大したことしてないはずが、思ったより時間がかかってしまいました。
でも、これで書籍のバーコードを使ったWebアプリが作れそうです。

もちろん、書籍だけでなくバーコードなら何にでも使えますので、バーコードの管理が必要ならば試してみて下さい。

(おわり)


  1. 正規の方法でなければSafari以外にすることもできますが、もちろんここではお薦めしません。