PyAWS - A Python wrapper for Amazon Web Service配列なら配列で、存在したり存在しない場合があるプロパティならばそれ用のアクセサを作ってほしい...
PyAWS is a Python wrapper for the latest Amazon Web Service. It is designed to pave the way for Python developers to interactivate AWS. This project is forked from the code base of pyamazon. The Amazone E-Commerce Services is supported.
http://pyaws.sourceforge.net/
Djangoテンプレートで配列かどうかを判断してループで回してってのはつらいです。
あと、Django Template Engineの最新版でないと
{% for key, value in values %}
こういう書き方が出来ないので、結局明示的な名前の付いたdictに作り変える必要があった。まぁこれはpyawsのせいではないけれど。aws.py
#!-*- coding:utf-8 -*-
import os
import cgi
import wsgiref.handlers
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.api import urlfetch
import logging
import yaml
from pyaws import ecs
def to_dict_array(array):
ret = []
for item in array:
ret.append({'key': item.keys()[0], 'value':item.values()[0] })
return ret
class MainPage(webapp.RequestHandler):
config = yaml.safe_load(open(os.path.join(os.path.dirname(__file__), 'aws.yaml'), 'r'))
def get(self):
kind = self.request.get('kind')
keyword = self.request.get('keyword')
template_values = {}
template_values = {
'asoid' : self.config['asoid'],
'kinds' : to_dict_array(self.config['kinds']),
'kind' : kind,
'keyword' : keyword,
'books' : [],
}
if keyword:
asoid = self.config['asoid']
devkey = self.config['devkey']
kinds = self.config['kinds']
ecs.setLicenseKey(devkey)
ecs.setLocale(self.config['locale'])
books = ecs.ItemSearch(keyword, SearchIndex=kind, ResponseGroup='Medium,Offers')
count = 0
max = 5
for book in books:
if 'Author' in book.__dict__ and not isinstance(book.Author, list):
book.Author = [book.Author]
if 'Offer' in book.Offers.__dict__:
if isinstance(book.Offers.Offer, list):
book.Availability = book.Offers.Offer[0].OfferListing.Availability
elif 'Availability' in book.Offers.Offer.OfferListing.__dict__:
book.Availability = book.Offers.Offer.OfferListing.Availability
template_values['books'].append(book)
count += 1
if count > max: break
path = os.path.join(os.path.dirname(__file__), 'aws.html')
self.response.out.write(template.render(path, template_values))
def main():
application = webapp.WSGIApplication([('/pyaws/', MainPage)], debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == '__main__':
main()
aws.html
<html>
<head>
<title>AWS商品検索</title>
<style tyle="text/css"><!--
body {
font-family: 'メイリオ', 'Osaka'
}
#content {
margin-left: 50px;
}
#error {
color: red;
}
.awsxom {
background: #eeeeee;
padding: 0.5em;
}
--></style>
</head>
<body>
<h1>AWS商品検索</h1><img src="http://b.hatena.ne.jp/entry/image/http://mattn.appspot.com/pyaws/" title="はてなブックマーク" />
<div id="content">
<p align="right"><a href="/">目次</a></p>
<form method="get">
<label for="kind">種類</label>
<select id="kind" name="kind" value="{{ kind }}">
{% for item in kinds %}<option value="{{ item.key }}"{% ifequal item.key kind %} selected="selected"{% endifequal %}>{{ item.value }}</option>
{% endfor %}
</select>
<label for="keyword">キーワード</label><input id="keyword" name="keyword" type="text" value="{{ keyword|escape }}" />
<input type="submit" />
</form>
<hr />
{% for book in books %}
<div class="awsxom">
<a href="http://www.amazon.co.jp/exec/obidos/ASIN/{{ book.ASIN }}/ref=nosim/{{ asoid }}">
<img src="{{ book.SmallImage.URL }}" align="left" hspace="5" border="0" alt="{{ book.Title }}" class="image" />
<strong>{{ book.Title }}</strong></a><br />
{{ book.Author|join:", " }}<br />
{{ book.Manufacturer}} / {{ book.ListPrice.FormattedPrice }} ({% if book.PublicationDate %}{{ book.PublicationDate }}{% else %}{{ book.ReleaseDate }}{% endif %})<br />
<br />
発送可能時間:{{ book.Availability }}<br />
<br clear="all" />
</div><br />
{% endfor %}
</div>
</body>
</html>
あと、設定用のyamlaws.yaml
asoid : xxxxxxxxx
devkey : 1XXXXXXXXXXXXXXXXXXX
locale: jp
kinds:
- Blended: Blended すべての商品
- Books: 本
- Classical: クラシック音楽
- DVD: DVD
- Electronics: エレクトロニクス
- ForeignBooks: 洋書
- Hobbies: ホビー
- Kitchen: ホーム&キッチン
- Music: 音楽
- MusicTracks: 曲名
- Software: ソフトウェア
- SportingGoods: スポーツ
- Toys: おもちゃ
- VHS: VHSビデオ
- Video: DVD&ビデオ
- VideoGames: ゲーム
- HealthPersonalCare: ヘルス&ビューティー
これ、AuthorとかAvailabilityなんかのアクセサが最初から決まった型で扱えればコードは2/3くらいになりそう。いっそBeautifulSoupとかで作った方が作り手側としては納得が行くのかも。
動いてる物は以下
AWS商品検索追記
パッチを付けるのを忘れてました。
pyaws.diff
--- pyaws/ecs.py.orig Mon Apr 09 07:38:57 2007
+++ pyaws/ecs.py Wed May 07 18:12:21 2008
@@ -19,7 +19,8 @@
import os, urllib, string, inspect
-from xml.dom import minidom
+from google.appengine.api import urlfetch
+import pxdom
__author__ = "Kun Xi < kunxi@kunxi.org >"
__version__ = "0.2.0"
@@ -164,10 +165,7 @@
"""Send the query url and return the DOM
Exception is raised if there is errors"""
- u = urllib.FancyURLopener(HTTP_PROXY)
- usock = u.open(url)
- dom = minidom.parse(usock)
- usock.close()
+ dom = pxdom.parseString(urlfetch.fetch(url).content)
errors = dom.getElementsByTagName('Error')
if errors:
@@ -282,7 +280,7 @@
if(plugins == None):
plugins = {}
- childElements = [e for e in element.childNodes if isinstance(e, minidom.Element)]
+ childElements = [e for e in element.childNodes if isinstance(e, pxdom.Element)]
if childElements:
for child in childElements:
@@ -291,7 +289,7 @@
if type(getattr(rc, key)) <> type([]):
setattr(rc, key, [getattr(rc, key)])
setattr(rc, key, getattr(rc, key) + [unmarshal(child, plugins)])
- elif isinstance(child, minidom.Element):
+ elif isinstance(child, pxdom.Element):
if plugins.has_key('isPivoted') and plugins['isPivoted'](child.tagName):
unmarshal(child, plugins, rc)
elif plugins.has_key('isBypassed') and plugins['isBypassed'](child.tagName):
@@ -303,7 +301,7 @@
else:
setattr(rc, key, unmarshal(child, plugins))
else:
- rc = "".join([e.data for e in element.childNodes if isinstance(e, minidom.Text)])
+ rc = "".join([e.data for e in element.childNodes if isinstance(e, pxdom.Text)])
return rc
pxdomはDOM Level 3をpythonで実装しているすばらしいライブラリです。ココから取得して下さい。