読者です 読者をやめる 読者になる 読者になる

oneshotlife-pythonのブログ

Pythonを好んで使っているプログラマです。Pythonこそが最強のプログラミング言語だと思っています。Pythonは使いやすいです。Pythonは書きやすいです。Pythonは読みやすいです。Pythonはパワフルです。Pythonは一貫性があります。Pythonが好きです。

Pythonで楽天ウェブサービスを使って書籍情報を取得する ~ リファクタリングしてみた #Python

WebAPI

はじめに

前回好評だったエントリPythonで楽天ウェブサービスを使って書籍情報を取得する #Python - oneshotlife-pythonのブログですが、Pythonの知識の浅い数年前に書いたコードだったため、つっこみどころ満載でした。よってリファクタリングしてみました。リファクタ
リングって流行ってるみたいですね。リファクタリング関連の書籍もたくさん出ています。中には、Rubyなどに言語を絞った書籍もあるようです。残念ながら、Pythonに絞ったリファクタリング本は未だ無いようです。

サンプルコード(リファクタリング前)

#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import urllib
import urllib2
import json

def Rakuten_BooksAuthorSearch(author,hits,sort):
    developerId = 'DEV_ID'
    affiliateId = 'AFF_ID'
    uri = 'https://app.rakuten.co.jp/services/api/BooksBook/Search/20130522?'+\
    'applicationId='   +developerId+\
    '&affiliateId='    +affiliateId+\
    '&author='          +author+\
    '&hits='            +hits+\
    '&sort='            +sort
    
    res = json.load(urllib2.urlopen(uri))
    print json.dumps(res, sort_keys = True, indent = 4)
    
    items = res["Items"]
    for item in items:
        print item["Item"]["title"]       
    print """<!-- Rakuten Web Services Attribution Snippet FROM HERE -->
<a href="http://webservice.rakuten.co.jp/" target="_blank">Supported by 楽天ウェブサービス</a>
<!-- Rakuten Web Services Attribution Snippet TO HERE -->"""

Rakuten_BooksAuthorSearch(urllib.quote("芥川龍之介"),"5","sales")

リファクタリングポイント

メソッド

def Rakuten_BooksAuthorSearch(author,hits,sort):

下でいろいろ考察しているが、結局は、

search_rakutenbooks_by_author

にしようかと思う。

語順

まず、語順が良くないかな。

SearchRakutenBooksByAuthor

とかのほうが良かった。
また、キャメルケースとかスネークケースとかってあるよね。

単語の区切り

RakutenBooksは、まぁRakutenbooksでいいのかな。。。ひとつの単語と捉える。

パスカルケース/アッパーキャメルケース
SearchRakutenbooksByAuthor
キャメルケース/ローワーキャメルケース
searchRakutenbooksByAuthor
スネークケース
search_rakutenbooks_by_author

ライブラリ

import urllib
import urllib2

ここはいかにも不細工ですね。urllibとurllib2って、API仕様がいまいちで、機能も中途半端なんです。二つもインポートしているんですが、未だとrequestsを使ったほうが断然良いです。
Requests: 人間のためのHTTP — requests-docs-ja 1.0.4 documentation

クエリの組立方

uri = 'https://app.rakuten.co.jp/services/api/BooksBook/Search/20130522?'+\
    'applicationId='   +developerId+\
    '&affiliateId='    +affiliateId+\
    '&author='          +author+\
    '&hits='            +hits+\
    '&sort='            +sort

ここは、迷うことなく辞書を使うべきです。。。PerlとかRubyとかだと、ハッシュ(連想配列)っていうのを使うんでしょうけど、Pythonにも似たような機能があるんです。辞書って呼びます。まぁ、呼び方はどうでもいいですけど。。。

参考書籍

入門 Python 3

メイン処理の書き方

Rakuten_BooksAuthorSearch(urllib.quote("芥川龍之介"),"5","sales")

いきなりメインの処理を書いちゃってますけど、外部ファイルとしてインポートした場合にだけ処理を走らせるようにしたほうが良さそう。ワンファイルで書きたいのなら別だけど。。。

通例以下のように書いたif文の中にメイン処理を書くようです。

if __name__ == "__main__":

print処理

items = res["Items"]
    for item in items:
        print item["Item"]["title"]       
    print """<!-- Rakuten Web Services Attribution Snippet FROM HERE -->
<a href="http://webservice.rakuten.co.jp/" target="_blank">Supported by 楽天ウェブサービス</a>
<!-- Rakuten Web Services Attribution Snippet TO HERE -->"""

ここは、メソッド内に書かずに、外出しします。

戻値

戻値が無いけれども、取得したデータをjoson形式で返却しちゃいましょうか?

サンプルコード(リファクタリング後)

#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
import requests
import json

def search_rakutenbooks(base_uri,query):
    res = requests.get(base_uri,params=query)
    return res.json()

if __name__ == "__main__":
    base_uri = 'https://app.rakuten.co.jp/services/api/BooksBook/Search/20130522'
    query = {}
    #共通パラメーター
    query['applicationId'] = 'DEV_ID' #自分のデベロッパーIDを設定して下さい
    query['affiliateId']   = 'AFF_ID' #自分のデベロッパーIDを設定して下さい
    #query['format'] = ''
    #query['callback'] = ''
    #query['elements'] = ''
    #query['formatVersion'] = ''
    #固有パラメーター
    #query['title'] = ''
    query['author'] = u'芥川龍之介'
    #query['publisherName'] = ’’
    #query['isbn'] = ’’
    query['hits'] = 1
    #query['page'] = ’’
    #query['availability'] = ’’
    #query['outOfStockFlag'] = ’’
    #query['chirayomiFlag'] = ’’
    query['sort'] = 'sales'
    #query['limitedFlag'] = ''
    #query['carrier'] = ''
    #query['genreInformationFlag'] = ''

    res = search_rakutenbooks(base_uri,query)
    print json.dumps(res, sort_keys = True, indent = 4)
    for item in res["Items"]:
        for key,val in item["Item"].iteritems():
            print "|",key,"|",val,"|"
    print u"""<!-- Rakuten Web Services Attribution Snippet FROM HERE -->
<a href="http://webservice.rakuten.co.jp/" target="_blank">Supported by 楽天ウェブサービス</a>
<!-- Rakuten Web Services Attribution Snippet TO HERE -->"""

コメント

search_rakutenbooks_by_author内の処理がスカスカになっちゃったwwwwwwwwwwwwwwwwwwwwwwww
ただ単純に、getして、json形式に変換して返却しているだけwwwwwwwwwwwwwwwwwwwwwwwww
まぁ、requestsがそれだけ優秀だという証しでもある。

実行結果

JSON形式そのまんま

{
    "GenreInformation": [], 
    "Items": [
        {
            "Item": {
                "affiliateUrl": "http://hb.afl.rakuten.co.jp/hgc/g00q0723.hqkjfc3b.g00q0723.hqkjg1ee/?pc=http%3A%2F%2Fbooks.rakuten.co.jp%2Frb%2F11256033%2F&m=http%3A%2F%2Fm.rakuten.co.jp%2Frms%2Fmsv%2FItem%3Fn%3D11256033%26surl%3Dbook", 
                "author": "\u82a5\u5ddd\u9f8d\u4e4b\u4ecb/\u6709\u5ddd\u6d69", 
                "authorKana": "\u30a2\u30af\u30bf\u30ac\u30ef,\u30ea\u30e5\u30a6\u30ce\u30b9\u30b1/\u30a2\u30ea\u30ab\u30ef,\u30d2\u30ed", 
                "availability": "1", 
                "booksGenreId": "001008022007/001008022008", 
                "chirayomiUrl": "", 
                "contents": "", 
                "discountPrice": 0, 
                "discountRate": 0, 
                "isbn": "9784043944682", 
                "itemCaption": "\u5b66\u6821\u306b\u306f\u4e0d\u601d\u8b70\u306a\u8a71\u304c\u3064\u307e\u3063\u3066\u3044\u307e\u3059\u3002\u6559\u5ba4\u306e\u7a93\u304b\u3089\u6c7a\u307e\u3063\u305f\u6642\u9593\u306b\u3060\u3051\u898b\u3048\u308b\u5973\u5b50\u9ad8\u6821\u751f\u3001\u5927\u4eba\u305f\u3061\u306e\u6d88\u3048\u305f\u4e16\u754c\u3092\u751f\u304d\u308b\u5c0f\u5b66\u751f\u305f\u3061\u3001\u98a8\u8239\u5c11\u5e74\u3068\u306e\u4ea4\u6d41\u30fc\u3002\u3044\u3064\u3082\u306e\u65e5\u5e38\u304c\u3050\u306b\u3083\u308a\u3068\u66f2\u304c\u3063\u3066\u898b\u3048\u308b\u3001\u305d\u3093\u306a\u4e0d\u601d\u8b70\u306a\u8aad\u66f8\u4f53\u9a13\u304c\u5f85\u3063\u3066\u3044\u307e\u3059\u3002\u53e4\u4eca\u6771\u897f\u4eba\u6c17\u4f5c\u5bb6\u305f\u3061\u306e\u66f8\u7c4d\u521d\u53ce\u9332\u4f5c\u3084\u4e0d\u673d\u306e\u540d\u4f5c\u3092\u96c6\u3081\u305f\u3001\u77ed\u7de8\u5c0f\u8aac\u30a2\u30f3\u30bd\u30ed\u30b8\u30fc\u7b2c\uff14\u5f3e\u3002", 
                "itemPrice": 555, 
                "itemUrl": "http://books.rakuten.co.jp/rb/11256033/", 
                "largeImageUrl": "http://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4682/9784043944682.jpg?_ex=200x200", 
                "limitedFlag": 0, 
                "listPrice": 0, 
                "mediumImageUrl": "http://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4682/9784043944682.jpg?_ex=120x120", 
                "postageFlag": 0, 
                "publisherName": "\u89d2\u5ddd\u66f8\u5e97", 
                "reviewAverage": "4.33", 
                "reviewCount": 3, 
                "salesDate": "2011\u5e7408\u6708", 
                "seriesName": "\u89d2\u5ddd\u6587\u5eab", 
                "seriesNameKana": "\u30ab\u30c9\u30ab\u30ef \u30d6\u30f3\u30b3", 
                "size": "\u6587\u5eab", 
                "smallImageUrl": "http://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4682/9784043944682.jpg?_ex=64x64", 
                "subTitle": "", 
                "subTitleKana": "", 
                "title": "\u4e0d\u601d\u8b70\u306e\u6249\uff08\u5348\u5f8c\u306e\u6559\u5ba4\uff09", 
                "titleKana": "\u30d5\u30b7\u30ae \u30ce \u30c8\u30d3\u30e9"
            }
        }
    ], 
    "carrier": 0, 
    "count": 143, 
    "first": 1, 
    "hits": 1, 
    "last": 1, 
    "page": 1, 
    "pageCount": 100
}

出力したデータを加工してテーブルにしてみた

discountPrice 0
publisherName 角川書店
chirayomiUrl
reviewCount 3
mediumImageUrl http://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4682/9784043944682.jpg?_ex=120x120
isbn 9784043944682
affiliateUrl http://hb.afl.rakuten.co.jp/hgc/g00q0723.hqkjfc3b.g00q0723.hqkjg1ee/?pc=http%3A%2F%2Fbooks.rakuten.co.jp%2Frb%2F11256033%2F&m=http%3A%2F%2Fm.rakuten.co.jp%2Frms%2Fmsv%2FItem%3Fn%3D11256033%26surl%3Dbook
availability 1
contents
size 文庫
seriesNameKana カドカワ ブンコ
subTitle
title 不思議の扉(午後の教室)
seriesName 角川文庫
discountRate 0
titleKana フシギ ノ トビラ
largeImageUrl http://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4682/9784043944682.jpg?_ex=200x200
authorKana アクタガワ,リュウノスケ/アリカワ,ヒロ
booksGenreId 001008022007/001008022008
smallImageUrl http://thumbnail.image.rakuten.co.jp/@0_mall/book/cabinet/4682/9784043944682.jpg?_ex=64x64
itemPrice 555
postageFlag 0
itemCaption 学校には不思議な話がつまっています。教室の窓から決まった時間にだけ見える女子高校生、大人たちの消えた世界を生きる小学生たち、風船少年との交流ー。いつもの日常がぐにゃりと曲がって見える、そんな不思議な読書体験が待っています。古今東西人気作家たちの書籍初収録作や不朽の名作を集めた、短編小説アンソロジー第4弾。
limitedFlag 0
author 芥川龍之介/有川浩
salesDate 2011年08月
itemUrl http://books.rakuten.co.jp/rb/11256033/
subTitleKana
reviewAverage 4.33
listPrice 0

Supported by 楽天ウェブサービス

お薦め書籍

入門 Python 3

入門 Python 3

Effective Python ―Pythonプログラムを改良する59項目

Effective Python ―Pythonプログラムを改良する59項目

初めてのPython 第3版

初めてのPython 第3版

みんなのPython 第3版

みんなのPython 第3版