【Python3】Google Books APIを使ってみる

はじめに

アルバイトの片山です。

前回、卒業制作で使った、Python3での並行処理?をやってみましたが、
今回は、同じく卒業制作の一部で使ったものをやっていきたいと思います。

相変わらず拙いコード・記事なのはご容赦ください。

Google Books APIからISBNコードによってその本の情報を持ってくるのをやります。

Google Books APIを使う

参考にしたのはこちらのページです。
参考ページではjQueryを使っていますが、Pythonでもやることは大して変わりません。

環境はいつも通り、Python3(3.5.2)を使っていきます。ちなみにGoogleのAPIを使いますが、登録等は必要ないので簡単にできると思います。

簡単なサンプル

とりあえずISBNコードを入力すると、その書籍の情報がJSON形式でやってくるので、そいつをPrintする簡単なものを作ってみました。

影の声: pip install requestsなどしてライブラリをインストールしておきましょう。

# -*- coding: utf-8 -*-
import requests

url = 'https://www.googleapis.com/books/v1/volumes?q=isbn:'

def main(isbn):
    req_url = url + isbn
    response = requests.get(req_url)
    return response.text

if __name__ == "__main__":
    while True:
        isbn_input = input("input ISBN >>>")
        print(main(isbn_input))

たとえば森絵都さんの「カラフル」のISBNを入力してみます。

$ python3 google_api.py                                                                                     2.3.1
input ISBN >>>9784167741013
{
 "kind": "books#volumes",
 "totalItems": 1,
 "items": [
  {
   "kind": "books#volume",
   "id": "xMMeNwAACAAJ",
   "etag": "M8bNz6/uLH4",
   "selfLink": "https://www.googleapis.com/books/v1/volumes/xMMeNwAACAAJ",
   "volumeInfo": {
    "title": "カラフル",
    "authors": [
     "森絵都"
    ],
    "publishedDate": "2007-09",
    "description": "生前の罪により、輪廻のサイクルから外されたぼくの魂。だが天使業界の抽選にあたり、再挑戦のチャンスを得た。自殺を図った少年、真の体にホームステイし、自分の罪を思い出さなければならないのだ。真として過ごすうち、ぼくは人の欠点や美点が見えてくるようになるのだが...。不朽の名作ついに登場。",
    "industryIdentifiers": [
     {
      "type": "ISBN_10",
      "identifier": "4167741016"
     },
     {
      "type": "ISBN_13",
      "identifier": "9784167741013"
     }
    ],
    "readingModes": {
     "text": false,
     "image": false
    },
    "pageCount": 259,
    "printType": "BOOK",
    "categories": [
     "Fantasy fiction"
    ],
    "averageRating": 3.5,
    "ratingsCount": 27,
    "maturityRating": "NOT_MATURE",
    "allowAnonLogging": false,
    "contentVersion": "preview-1.0.0",
    "imageLinks": {
     "smallThumbnail": "http://books.google.com/books/content?id=xMMeNwAACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api",
     "thumbnail": "http://books.google.com/books/content?id=xMMeNwAACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api"
    },
    "language": "ja",
    "previewLink": "http://books.google.co.jp/books?id=xMMeNwAACAAJ&dq=isbn:9784167741013&hl=&cd=1&source=gbs_api",
    "infoLink": "http://books.google.co.jp/books?id=xMMeNwAACAAJ&dq=isbn:9784167741013&hl=&source=gbs_api",
    "canonicalVolumeLink": "https://books.google.com/books/about/%E3%82%AB%E3%83%A9%E3%83%95%E3%83%AB.html?hl=&id=xMMeNwAACAAJ"
   },
   "saleInfo": {
    "country": "JP",
    "saleability": "NOT_FOR_SALE",
    "isEbook": false
   },
   "accessInfo": {
    "country": "JP",
    "viewability": "NO_PAGES",
    "embeddable": false,
    "publicDomain": false,
    "textToSpeechPermission": "ALLOWED",
    "epub": {
     "isAvailable": false
    },
    "pdf": {
     "isAvailable": false
    },
    "webReaderLink": "http://play.google.com/books/reader?id=xMMeNwAACAAJ&hl=&printsec=frontcover&source=gbs_api",
    "accessViewStatus": "NONE",
    "quoteSharingAllowed": false
   },
   "searchInfo": {
    "textSnippet": "生前の罪により、輪廻のサイクルから外されたぼくの魂。だが天使業界の抽選にあたり、再挑戦のチャンスを得た。自殺を図った少年、真の体にホームステイし、自分の罪を思い ..."
   }
  }
 ]
}

こんな感じで書籍情報が得られます。

書籍情報がみつからない時も結構あるのですが、その時は、

{
 "kind": "books#volumes",
 "totalItems": 0
}

こんな感じになります。

ちょっと応用したサンプル

卒業制作で提出した、ほぼそのままのコードを貼り付けただけですが、JSONまわりが全然わからなくて苦労しつつ作ったものなので、いつか誰かに需要あるかなとおもって貼り付けておきます……

内容としては、

  • ローカルの./isbn_datasにISBNと書籍の情報がすでにあれば、そいつからtitledescriptionをreturnする
  • ローカルになければGoogle Books APIからJSONを取得して./isbn_datasに保存、descriptiontitleをreturnする

という感じです。要は、一度読み込んだものについてはローカルから使えるようにして、なければAPIから引っ張ってこようという感じです。

やってることは大したことないのですが、作ってた当時は「ほんまJSONとやらわけわからん……」ってなりつつ試行錯誤してました。
ファイルを扱うのもやったことなかったし……

影の声: 実行前にmkdir .isbn_dataとしておく必要があります。

# -*- coding: utf-8 -*-
import sys
import requests
import json

url = 'https://www.googleapis.com/books/v1/volumes?q=isbn:'

def main(isbn):
    isbn_path = "./isbn_data/" + isbn + ".json"
    buf01 = ''
    buf02 = ''
    try:
        with open(isbn_path, 'r') as f:
            data = json.load(f)
            try:
                buf01 += data['items'][0]['volumeInfo']['title'] 
                buf02 += data['items'][0]['volumeInfo']['description'] 
            except:
                print('None')
    except:
        req_url = url + isbn
        response = requests.get(req_url)
        with open(isbn_path, 'w') as f:
            json.dump(response.json(), f)
        with open(isbn_path, 'r') as f:
            data = json.load(f)
            try:
                buf01 += data['items'][0]['volumeInfo']['title'] 
                buf02 += data['items'][0]['volumeInfo']['description'] 
            except:
                print('None')
    return buf01, buf02

if __name__ == "__main__":
    while True:
        sys.stdout.write('input isbn >>>')       
        isbn_input = input()
        print(main(isbn_input))

おわりに

いつもながら「こんなの誰に需要あるんだよ」っていう感じのことをやってきましたが、どこかの誰かの助けになればと思います。

関連記事

Python3: 並行処理?非同期処理?をやってみる

ベテランRubyistがPythonコードを5倍速くした話(翻訳)

デザインも頼めるシステム開発会社をお探しならBPS株式会社までどうぞ 開発エンジニア積極採用中です! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

Yuki.K

1995年生まれ。慶應SFCを2018年3月に卒業予定(予定) 夢も希望もなくキャンパスを彷徨っていたところ、夢と希望いっぱいのBPS村に引きずり込まれてしまった大学生アルバイト。 雑用担当

Yuki.Kの書いた記事

週刊Railsウォッチ

インフラ

ActiveSupport探訪シリーズ