47fe6df9ae4568940889056b274debcf1e094b5b
[mspang/pyceo.git] / ceo / pymazon.py
1 #!/usr/bin/python
2
3 from xml.dom import minidom, Node
4 import urllib
5 import time
6
7 class PyMazonError(Exception):
8         """Holds information about an error that occured during a pymazon request"""
9         def __init__(self, messages):
10                 self.__message = '\n'.join(messages)
11
12         def __get_message(self):
13                 return self.__message
14
15         def __str__(self):
16                 return repr(self.__message)
17
18         message = property(fget=__get_message)
19
20
21 class PyMazonBook:
22         """Stores information about a book retrieved via PyMazon."""
23         def __init__(self, title, authors, publisher, year, isbn10, isbn13, edition):
24                 self.__title = title
25                 self.__authors = authors
26                 self.__publisher = publisher
27                 self.__year = year 
28                 self.__isbn10 = isbn10
29                 self.__isbn13 = isbn13
30                 self.__edition = edition
31
32         def __str__(self):
33                 return 'Title:     ' + self.title + '\n' + \
34                        'Author(s): ' + ', '.join(self.authors) + '\n' \
35                                  'Publisher: ' + self.publisher + '\n' + \
36                                  'Year:      ' + self.year + '\n' + \
37                                  'ISBN-10:   ' + self.isbn10 + '\n' + \
38                                  'ISBN-13:   ' + self.isbn13 + '\n' + \
39                                  'Edition:   ' + self.edition
40
41         def __get_title(self):
42                 return self.__title
43
44         def __get_authors(self):
45                 return self.__authors
46         
47         def __get_publisher(self):
48                 return self.__publisher
49
50         def __get_year(self):
51                 return self.__year
52
53         def __get_isbn10(self):
54                 return self.__isbn10
55
56         def __get_isbn13(self):
57                 return self.__isbn13
58
59         def __get_edition(self):
60                 return self.__edition
61
62         title = property(fget=__get_title)
63         authors = property(fget=__get_authors)
64         publisher = property(fget=__get_publisher)
65         year = property(fget=__get_year)
66         isbn10 = property(fget=__get_isbn10)
67         isbn13 = property(fget=__get_isbn13)
68         edition = property(fget=__get_edition)
69
70
71 class PyMazon:
72         """A method of looking up book information on Amazon."""
73         def __init__(self, accesskey):
74                 self.__key = accesskey
75                 self.__last_query_time = 0
76
77         def __form_request(self, isbn):
78                 return 'http://webservices.amazon.com/onca/xml?' + \
79                        'Service=AWSECommerceService' + \
80                                  '&Version=2008-08-19' + \
81                        '&AWSAccessKeyId=' + self.__key + \
82                                  '&Operation=ItemLookup' + \
83                                  '&ResponseGroup=ItemAttributes' + \
84                                  '&IdType=ISBN' + \
85                                  '&SearchIndex=Books' + \
86                                  '&ItemId=' + isbn
87
88         def __elements_text(self, element, name):
89                 result = []
90                 matching = element.getElementsByTagName(name)
91                 for match in matching:
92                         if len(match.childNodes) != 1:
93                                 continue
94                         child = match.firstChild
95                         if child.nodeType != Node.TEXT_NODE:
96                                 continue
97                         result.append(child.nodeValue.strip())
98                 return result
99
100         def __format_errors(self, errors):
101                 error_list = []
102                 for error in errors:
103                         error_list.extend(self.__elements_text(error, 'Message'))
104                 return error_list
105
106         def __extract_single(self, element, name):
107                 matches = self.__elements_text(element, name)
108                 if len(matches) == 0:
109                         return ''
110                 return matches[0]
111
112         def lookup(self, isbn):
113                 file = urllib.urlretrieve(self.__form_request(isbn))[0]
114                 xmldoc = minidom.parse(file)
115
116                 cur_time = time.time()
117                 while cur_time - self.__last_query_time < 1.0:
118                         sleep(cur_time - self.__last_query_time)
119                         cur_time = time.time()
120                 self.__last_query_time = cur_time
121
122                 errors = xmldoc.getElementsByTagName('Errors')
123                 if len(errors) != 0:
124                         raise PyMazonError, self.__format_errors(errors)
125
126                 title = self.__extract_single(xmldoc, 'Title')
127                 authors = self.__elements_text(xmldoc, 'Author')
128                 publisher = self.__extract_single(xmldoc, 'Publisher')
129                 year = self.__extract_single(xmldoc, 'PublicationDate')[0:4]
130                 isbn10 = self.__extract_single(xmldoc, 'ISBN')
131                 isbn13 = self.__extract_single(xmldoc, 'EAN')
132                 edition = self.__extract_single(xmldoc, 'Edition')
133
134                 return PyMazonBook(title, authors, publisher, year, isbn10, isbn13, edition)