AI

BeautifulSoupの挙動が謎(GAE上でPythonでAmazonAPIを使う)

GAEでPythonとDjangoでAmazonAPI使ったWEBアプリを作成中。
AmazonAPIはPyzonを使っていて、返ってきたxmlはBeautifulSoupを使って読んでいる。
が、BeautifulSoupがよく分からず、どんなコードならいいのか全然わからない。
あれはうまくいったのに、これはうまくいかないなんて全然分からなかったので、あれとこれをメモっておく。

うまくいったコード

from pyzon import Pyzon
from BeautifulSoup import BeautifulStoneSoup
import re
access_key_id = ****
secret_access_key = ****
associate_tag = ****
#本を検索する
def book_search(bookname):
pyzon = Pyzon(access_key_id, secret_access_key, associate_tag)
xml = pyzon.ItemSearch(search_index='Books', Keywords=bookname,ResponseGroup='Small,Images')
soup = BeautifulStoneSoup(xml)
#asin,smallimage,title,author,manufacturerのリスト作る
bookinfo_list = [[item.asin.contents[0],item.smallimage,item.title.contents[0],item.author,item.manufacturer.contents[0]] for item in soup.findAll('item')]
#smallimage,authorはNONEの可能性あり、チェックしてNONEの対応して、余計なものを省く
idx = 0
for bookinfo in bookinfo_list:
if not bookinfo[1] == 'NONE':
p = re.compile('^(?P.+?)')
m = p.match(str(bookinfo[1]))
if m: bookinfo_list[idx][1] = m.group('url')
if not bookinfo[3] == 'NONE':
p = re.compile('^(?P.+?)')
m = p.match(str(bookinfo[3]))
if m: bookinfo_list[idx][3] = m.group('author')
idx += 1
return bookinfo_list

うまくいかなかったコード

from pyzon import Pyzon
from BeautifulSoup import BeautifulStoneSoup
access_key_id = ****
secret_access_key = ****
associate_tag = ****
#1冊の本の情報を取り出す(IdTypeはASIN)※amazonAPIのitemLookup
def book_lookup(asin):
pyzon = Pyzon(access_key_id, secret_access_key, associate_tag)
xml = pyzon.ItemLookup(item_id=str(asin),ResponseGroup='Small,Images')
soup = BeautifulStoneSoup(xml)
#asin,smallimage,mediumimage,largeimage,title,author,manufacturerのリスト作る
asin = soup.asin.contents[0]
title = soup.title.contents[0]
manufacturer = soup.manufacturer.contents[0]
#imageとauthorはNONEの可能性があるので、チェックした後、値を格納。
smallimage_url = ''
mediumimage_url = ''
largeimage_url = ''
author = ''
if not soup.smallimage == 'NONE': smallimage_url = soup.smallimage.url.contents[0]
if not soup.mediumimage == 'NONE': mediumimage_url = soup.mediumimage.url.contents[0]
if not soup.largeimage == 'NONE': largeimage_url = soup.largeimage.url.contents[0]
if not soup.author == 'NONE': author = soup.author.contents[0]
return [int(asin),str(smallimage_url),str(mediumimage_url),str(largeimage_url),title,author,manufacturer]

うまくいかなかった方は、soup.smallimageとか、soup.authorとかの値が無いときに、最後の数行のif分のところで、無い値の部分がエラーになる。

AmazonAPIがJSONで返してくれたらどんだけ楽なことか。PythonでXMLをJSONに直すのも簡単ではなさそうなので、XMLをBeautifulSoup読む方法で粘ろう。
ちなみに、うまくいかなかったコードの修正版がこれ。

from pyzon import Pyzon
from BeautifulSoup import BeautifulStoneSoup
import re
access_key_id = ****
secret_access_key = ****
associate_tag = ****
#1冊の本の情報を取り出す(IdTypeはASIN)※amazonAPIのitemLookup
def book_lookup(asin):
pyzon = Pyzon(access_key_id, secret_access_key, associate_tag)
xml = pyzon.ItemLookup(item_id=str(asin),ResponseGroup='Small,Images')
soup = BeautifulStoneSoup(xml)
#asin,smallimage,mediumimage,largeimage,title,author,manufacturerのリスト作る
bookinfo_list = [[item.asin.contents[0],item.smallimage,item.mediumimage,item.largeimage,item.title.contents[0],item.author,item.manufacturer.contents[0]] for item in soup.findAll('item')]
#imageとauthorはNONEの可能性があるので、チェックした後、値を格納。
idx = 0
for bookinfo in bookinfo_list:
if not bookinfo[1] == 'NONE':
p = re.compile('^(?P.+?)')
m = p.match(str(bookinfo[1]))
if m: bookinfo_list[idx][1] = m.group('url')
if not bookinfo[2] == 'NONE':
p = re.compile('^(?P.+?)')
m = p.match(str(bookinfo[2]))
if m: bookinfo_list[idx][2] = m.group('url')
if not bookinfo[3] == 'NONE':
p = re.compile('^(?P.+?)')
m = p.match(str(bookinfo[3]))
if m: bookinfo_list[idx][3] = m.group('url')
if not bookinfo[5] == 'NONE':
p = re.compile('^(?P.+?)')
m = p.match(str(bookinfo[5]))
if m: bookinfo_list[idx][5] = unicode(m.group('author'),'utf-8')
idx += 1
return bookinfo_list[0]