completelynovel-amazon-product-advertising-api 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/EXAMPLE.rdoc +81 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +94 -0
- data/amazon-product-advertising-api.gemspec +36 -0
- data/lib/amazon_product_advertising_api.rb +8 -0
- data/lib/amazon_product_advertising_api/base.rb +12 -0
- data/lib/amazon_product_advertising_api/operations/base.rb +131 -0
- data/lib/amazon_product_advertising_api/operations/browse_node.rb +65 -0
- data/lib/amazon_product_advertising_api/operations/item.rb +133 -0
- data/lib/amazon_product_advertising_api/support.rb +55 -0
- metadata +84 -0
data/EXAMPLE.rdoc
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'amazon_product_advertising_api'
|
3
|
+
# Setup your API key - in an initializer or something like that
|
4
|
+
AmazonProductAdvertisingApi::Base.api_key = "<insert api key here>"
|
5
|
+
|
6
|
+
# Setup Associates IDs for whichever regions you're selling to
|
7
|
+
AmazonProductAdvertisingApi::Base.associate_ids.uk = "<insert UK Associate ID here>"
|
8
|
+
AmazonProductAdvertisingApi::Base.associate_ids.us = "<insert US Associate ID here>"
|
9
|
+
|
10
|
+
lookup = AmazonProductAdvertisingApi::Operations::Item::ItemLookup.new("0201485419")
|
11
|
+
lookup.run
|
12
|
+
|
13
|
+
# Returned XML, tidied
|
14
|
+
# <?xml version="1.0"?>
|
15
|
+
# <ItemLookupResponse xmlns="http://webservices.amazon.com/AWSECommerceService/2005-10-05">
|
16
|
+
# <OperationRequest>
|
17
|
+
# <RequestId>d6c19392-7710-4b05-ad9c-1637755170d8</RequestId>
|
18
|
+
# <Arguments>
|
19
|
+
# <Argument Name="Operation" Value="ItemLookup"/>
|
20
|
+
# <Argument Name="Service" Value="AWSECommerceService"/>
|
21
|
+
# <Argument Name="ItemId" Value="0201485419"/>
|
22
|
+
# <Argument Name="AWSAccessKeyId" Value="<your api key>"/>
|
23
|
+
# </Arguments>
|
24
|
+
# <RequestProcessingTime>0.0376290000000000</RequestProcessingTime>
|
25
|
+
# </OperationRequest>
|
26
|
+
# <Items>
|
27
|
+
# <Request>
|
28
|
+
# <IsValid>True</IsValid>
|
29
|
+
# <ItemLookupRequest>
|
30
|
+
# <Condition>New</Condition>
|
31
|
+
# <DeliveryMethod>Ship</DeliveryMethod>
|
32
|
+
# <IdType>ASIN</IdType>
|
33
|
+
# <MerchantId>Amazon</MerchantId>
|
34
|
+
# <OfferPage>1</OfferPage>
|
35
|
+
# <ItemId>0201485419</ItemId>
|
36
|
+
# <ResponseGroup>Small</ResponseGroup>
|
37
|
+
# <ReviewPage>1</ReviewPage>
|
38
|
+
# </ItemLookupRequest>
|
39
|
+
# </Request>
|
40
|
+
# <Item>
|
41
|
+
# <ASIN>0201485419</ASIN>
|
42
|
+
# <DetailPageURL>http://www.amazon.co.uk/Art-Computer-Programming-Information-Processing/dp/0201485419%3FSubscriptionId%3D<your api key>%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0201485419</DetailPageURL>
|
43
|
+
# <ItemAttributes>git
|
44
|
+
# <Author>Donald E. Knuth</Author>
|
45
|
+
# <Manufacturer>Addison Wesley</Manufacturer>
|
46
|
+
# <ProductGroup>Book</ProductGroup>
|
47
|
+
# <Title>The Art of Computer Programming: v. 1-3: Vol 1-3 (Series in Computer Science & Information Processing)</Title>
|
48
|
+
# </ItemAttributes>
|
49
|
+
# </Item>
|
50
|
+
# </Items>
|
51
|
+
# </ItemLookupResponse>
|
52
|
+
|
53
|
+
lookup.response.items.size
|
54
|
+
=> 1
|
55
|
+
|
56
|
+
lookup.response.items.first
|
57
|
+
=> #<AmazonProductAdvertisingApi::Item:0x139154c @detail_page_url="http://www.amazon.co.uk/Art-Computer-Programming-Information-Processing/dp/0201485419%3FSubscriptionId%3D<your api key>%26tag%3Dws%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0201485419", @item_attributes=#<AmazonProductAdvertisingApi::Container:0x1391448 @manufacturer="Addison Wesley", @product_group="Book", @title="The Art of Computer Programming: v. 1-3: Vol 1-3 (Series in Computer Science & Information Processing)", @author="Donald E. Knuth">, @asin="0201485419">
|
58
|
+
|
59
|
+
lookup.response.items.first.asin
|
60
|
+
=> "0201485419"
|
61
|
+
|
62
|
+
# ItemAttributes is a container element, doesn't return a string
|
63
|
+
lookup.response.items.first.item_attributes
|
64
|
+
=> #<AmazonProductAdvertisingApi::Container:0x1391448 @manufacturer="Addison Wesley", @product_group="Book", @title="The Art of Computer Programming: v. 1-3: Vol 1-3 (Series in Computer Science & Information Processing)", @author="Donald E. Knuth">
|
65
|
+
|
66
|
+
lookup.response.items.first.item_attributes.title
|
67
|
+
=> "The Art of Computer Programming: v. 1-3: Vol 1-3 (Series in Computer Science & Information Processing)"
|
68
|
+
|
69
|
+
lookup.response.items.first.item_attributes.author
|
70
|
+
=> "Donald E. Knuth"
|
71
|
+
|
72
|
+
# If you need to debug, you can access all the xml data easily
|
73
|
+
lookup.raw_data
|
74
|
+
=> <XML string, straight from the request body>
|
75
|
+
|
76
|
+
lookup.hpricot_data
|
77
|
+
=> <the xml data, having been fed into Hpricot>
|
78
|
+
|
79
|
+
# And also the request uri
|
80
|
+
irb(main):022:0> lookup.request_uri
|
81
|
+
=> #<URI::HTTP:0x1c7021c URL:http://ecs.amazonaws.co.uk/onca/xml?Service=AWSECommerceService&Operation=ItemLookup&ItemId=0201485419&AWSAccessKeyId=%3Cinsert%20api%20key%20here%3E>
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 Jon Gilbraith, CompletelyNovel Ltd
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
= amazon-product-advertising-api
|
2
|
+
|
3
|
+
== Introduction
|
4
|
+
A nice rubyish interface to the Amazon Product Advertising API, formerly
|
5
|
+
known as the Associates Web Service and before that the Amazon E-Commerce
|
6
|
+
Service.
|
7
|
+
|
8
|
+
The basic design philosophy is the 'Principle of least surprise', so it's:
|
9
|
+
- a dsl that should feel familiar to ruby folk.
|
10
|
+
- structured generally like the API.
|
11
|
+
|
12
|
+
== Prerequisites
|
13
|
+
It's assumed you're reasonably familiar with Ruby as a language, and the
|
14
|
+
typical coding patterns and styles employed by the community.
|
15
|
+
|
16
|
+
It's also assumed that you're familiar with the API. If not go RTFM for a bit,
|
17
|
+
it's all pretty straight forward.
|
18
|
+
|
19
|
+
== Overview
|
20
|
+
As mentioned before, the idea behind this is to model the API so that once
|
21
|
+
you're familiar with this library and the API, you'll find this an easy way to
|
22
|
+
navigate around it. You should then be able to just refer to the lists of
|
23
|
+
Operations, Response Groups and Response Elements in the appendices for all
|
24
|
+
you need to know.
|
25
|
+
|
26
|
+
You initiate requests by instantiating classes representing api Operations and
|
27
|
+
named the same way, i.e. ItemSearch, ItemLookup, etc. The request parameters
|
28
|
+
are represented by attributes on those objects and can be manipulated as you
|
29
|
+
wish. If a parameter is required it'll be required or defaulted on
|
30
|
+
initialization, but everywhere else we defer to the defaults provided by the
|
31
|
+
api.
|
32
|
+
|
33
|
+
Once setup, you call 'run' on the operation which will send the request and
|
34
|
+
return a response object (and after that also available as operation.response).
|
35
|
+
|
36
|
+
The response has a bit less structure than the request operations. There is no
|
37
|
+
representation for Response Groups as beyond one level deep there is no clear
|
38
|
+
pattern for how returned XML is structured (at least not without going down the
|
39
|
+
route trying to define custom handling for each of them). So, instead we group
|
40
|
+
the Operations into broad groups which return the same collections of data.
|
41
|
+
ItemSearch, ItemLookup and SimilarityLookup all return a Items container
|
42
|
+
element with one or more Item tag in it, etc.
|
43
|
+
|
44
|
+
Everything beyond one level deep is done with a recursive sweep instantiating
|
45
|
+
Element objects as we go.
|
46
|
+
|
47
|
+
== Things to know
|
48
|
+
- Amazon uses a lot of Camel case in their XML, but to suit Ruby / Rails
|
49
|
+
conventions attributes, etc are converted to underscore style.
|
50
|
+
- One gotcha - Response Elements can either be a simple value or a container
|
51
|
+
with more elements inside. We recognise this situation by simply comparing
|
52
|
+
the parent and child names (plural parent, singular child) though that isn't
|
53
|
+
always the pattern so we also look for multiple children of the same name.
|
54
|
+
|
55
|
+
That means that some situations might creep through and not work as expected.
|
56
|
+
If the parent and child don't follow the same naming convention and there is
|
57
|
+
also only one child element you'd find the child would be defined as
|
58
|
+
parent.child rather than parent.children.first.
|
59
|
+
|
60
|
+
This is a bug and will have to be addressed (probably by making a list of
|
61
|
+
container elements to check against).
|
62
|
+
|
63
|
+
== Having problems?
|
64
|
+
After running the request uri, returned raw xml and hpricot data will be
|
65
|
+
available in operation.raw_data and operation.hpricot_data which should tell
|
66
|
+
you all you need to know about the response.
|
67
|
+
|
68
|
+
== Test coverage
|
69
|
+
There aren't any tests at the moment but I'll try to add some.
|
70
|
+
|
71
|
+
For the most part there isn't really all that much to test though as it's all
|
72
|
+
largely just making http requests, however the XML parsing is quite convoluted
|
73
|
+
so some tests would be good there to make sure the parsing is following the
|
74
|
+
intended rules.
|
75
|
+
|
76
|
+
|
77
|
+
= TODO
|
78
|
+
- Implement the rest of the Operations (Cart*, Customer*, Help, List*, Seller*,
|
79
|
+
Tag*, Transaction* and Vehicle*).
|
80
|
+
- Clean handling of routine errors such as rate limiting, etc.
|
81
|
+
- Implement HMAC before the authentication requirement kicks in in August 2009.
|
82
|
+
- Implement batch and multiple operation requests, abstracted away from the
|
83
|
+
user within the dsl.
|
84
|
+
- Some sort of internal caching mechanism.
|
85
|
+
- Ability to bind to different IP addresses, in order to circumvent API rate
|
86
|
+
limiting.
|
87
|
+
|
88
|
+
|
89
|
+
= Credits
|
90
|
+
Created by Jon Gilbraith, jon@completelynovel.com, while working with
|
91
|
+
CompletelyNovel.
|
92
|
+
|
93
|
+
Contents of support.rb are basically taken and adapted from Rails'
|
94
|
+
ActiveSupport.
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{amazon-product-advertising-api}
|
5
|
+
s.version = "0.0.2"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Jon Gilbraith"]
|
9
|
+
s.date = %q{2009-06-11}
|
10
|
+
s.description = %q{A nice rubyish interface to the Amazon Product Advertising API, formerly known as the Associates Web Service and before that the Amazon E-Commerce Service.}
|
11
|
+
s.email = %q{jon@completelynovel.com}
|
12
|
+
s.files = ["EXAMPLE.rdoc", "MIT-LICENSE", "README.rdoc", "amazon-product-advertising-api.gemspec", "lib/amazon_product_advertising_api", "lib/amazon_product_advertising_api/base.rb", "lib/amazon_product_advertising_api/operations", "lib/amazon_product_advertising_api/operations/base.rb", "lib/amazon_product_advertising_api/operations/browse_node.rb", "lib/amazon_product_advertising_api/operations/item.rb", "lib/amazon_product_advertising_api/support.rb", "lib/amazon_product_advertising_api.rb"]
|
13
|
+
s.has_rdoc = false
|
14
|
+
s.homepage = %q{http://github.com/completelynovel/amazon-product-advertising-api}
|
15
|
+
s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{amazon-pa-api}
|
18
|
+
s.rubygems_version = %q{1.3.0}
|
19
|
+
s.summary = %q{A nice rubyish interface to the Amazon Product Advertising API.}
|
20
|
+
|
21
|
+
if s.respond_to? :specification_version then
|
22
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
23
|
+
s.specification_version = 2
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_runtime_dependency(%q<mime-types>, [">= 1.15"])
|
27
|
+
s.add_runtime_dependency(%q<diff-lcs>, [">= 1.1.2"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<mime-types>, [">= 1.15"])
|
30
|
+
s.add_dependency(%q<diff-lcs>, [">= 1.1.2"])
|
31
|
+
end
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<mime-types>, [">= 1.15"])
|
34
|
+
s.add_dependency(%q<diff-lcs>, [">= 1.1.2"])
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'hpricot'
|
3
|
+
|
4
|
+
require 'amazon_product_advertising_api/support'
|
5
|
+
require 'amazon_product_advertising_api/base'
|
6
|
+
require 'amazon_product_advertising_api/operations/base'
|
7
|
+
require 'amazon_product_advertising_api/operations/browse_node'
|
8
|
+
require 'amazon_product_advertising_api/operations/item'
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module AmazonProductAdvertisingApi
|
2
|
+
module Operations
|
3
|
+
module Base
|
4
|
+
|
5
|
+
class Request
|
6
|
+
|
7
|
+
attr_accessor :aws_access_key_id
|
8
|
+
|
9
|
+
attr_accessor :region
|
10
|
+
|
11
|
+
attr_accessor :operation
|
12
|
+
|
13
|
+
attr_accessor :request_uri
|
14
|
+
|
15
|
+
attr_accessor :raw_data
|
16
|
+
|
17
|
+
attr_accessor :hpricot_data
|
18
|
+
|
19
|
+
attr_accessor :response
|
20
|
+
|
21
|
+
SERVICE_URLS = {
|
22
|
+
:us => 'http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService',
|
23
|
+
:uk => 'http://ecs.amazonaws.co.uk/onca/xml?Service=AWSECommerceService',
|
24
|
+
:ca => 'http://ecs.amazonaws.ca/onca/xml?Service=AWSECommerceService',
|
25
|
+
:de => 'http://ecs.amazonaws.de/onca/xml?Service=AWSECommerceService',
|
26
|
+
:jp => 'http://ecs.amazonaws.jp/onca/xml?Service=AWSECommerceService',
|
27
|
+
:fr => 'http://ecs.amazonaws.fr/onca/xml?Service=AWSECommerceService'
|
28
|
+
}
|
29
|
+
|
30
|
+
def initialize
|
31
|
+
self.response = AmazonProductAdvertisingApi::Operations::Base::Element.new
|
32
|
+
end
|
33
|
+
|
34
|
+
def query_amazon(params)
|
35
|
+
request_params = {}
|
36
|
+
request_params["AWSAccessKeyId"] = AmazonProductAdvertisingApi::Base.api_key
|
37
|
+
request_params["Operation"] = self.operation
|
38
|
+
request_params["AssociateTag"] = AmazonProductAdvertisingApi::Base.associate_ids.send(self.region) unless AmazonProductAdvertisingApi::Base.associate_ids.send(self.region).nil?
|
39
|
+
request_params.merge!(params)
|
40
|
+
|
41
|
+
self.request_uri = "#{SERVICE_URLS[self.region]}&#{request_params.collect { |var, val| var.to_s.camelize + "=" + val.to_s }.join("&")}"
|
42
|
+
self.request_uri = URI.parse(URI.escape(self.request_uri))
|
43
|
+
|
44
|
+
result = Net::HTTP::get_response(self.request_uri)
|
45
|
+
raise("Error connecting to Amazon") if !result.kind_of?(Net::HTTPSuccess)
|
46
|
+
|
47
|
+
# Store away the raw data for debugging or if more direct access is required
|
48
|
+
self.raw_data = result.body
|
49
|
+
self.hpricot_data = Hpricot.XML(self.raw_data)
|
50
|
+
|
51
|
+
# Now parse the xml and build out the reponse elements
|
52
|
+
self.parse
|
53
|
+
end
|
54
|
+
|
55
|
+
def parse
|
56
|
+
raise "This should be being overridden by it's subclass to provide custom parsing for the particular operation concerned."
|
57
|
+
end
|
58
|
+
|
59
|
+
def run
|
60
|
+
self.query_amazon(params)
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
# When passed an hpricot element it returns true or false based on whether this item is thought to be inside a Container Element.
|
65
|
+
# It does this in the rather crude way of seeing if the parent's name is the pluralized form of it's own, or it is one of
|
66
|
+
# several with the same name. This isn't 100% fool proof so I think at some point using a definitive list of the container elements
|
67
|
+
# would be a better way to go.
|
68
|
+
#
|
69
|
+
# The pluralisation could also do with something a bit more sophisticated.
|
70
|
+
def parent_a_container?(hpricot_element)
|
71
|
+
hpricot_element.parent.name == hpricot_element.name + "s" || hpricot_element.parent.search("> #{hpricot_element.name}").size > 1
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
class Element
|
77
|
+
|
78
|
+
include Enumerable
|
79
|
+
|
80
|
+
def initialize
|
81
|
+
@contained_elements = []
|
82
|
+
end
|
83
|
+
|
84
|
+
def add_element(name, value = nil)
|
85
|
+
name = name.underscore
|
86
|
+
|
87
|
+
self.instance_eval %{
|
88
|
+
def self.#{name}
|
89
|
+
@#{name}
|
90
|
+
end
|
91
|
+
def self.#{name}=(value)
|
92
|
+
@#{name} ||= value
|
93
|
+
end
|
94
|
+
}
|
95
|
+
|
96
|
+
if !value.nil?
|
97
|
+
value = value.to_s if value.is_a?(Symbol)
|
98
|
+
self.send("#{name}=", value)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Return the element
|
102
|
+
self.instance_eval("self.#{name}")
|
103
|
+
end
|
104
|
+
|
105
|
+
def << element
|
106
|
+
@contained_elements << element
|
107
|
+
end
|
108
|
+
|
109
|
+
def each(&block)
|
110
|
+
@contained_elements.each do |element|
|
111
|
+
yield element
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def [] position
|
116
|
+
@contained_elements[position]
|
117
|
+
end
|
118
|
+
|
119
|
+
def first
|
120
|
+
@contained_elements.first
|
121
|
+
end
|
122
|
+
|
123
|
+
def size
|
124
|
+
@contained_elements.size
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module AmazonProductAdvertisingApi
|
2
|
+
module Operations
|
3
|
+
module BrowseNode
|
4
|
+
|
5
|
+
class BrowseNodeLookup < AmazonProductAdvertisingApi::Operations::Base::Request
|
6
|
+
|
7
|
+
REQUEST_PARAMETERS = :browse_node_id, :response_group
|
8
|
+
|
9
|
+
REQUEST_PARAMETERS.each do |param|
|
10
|
+
self.send(:attr_accessor, param)
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(browse_node_id, region = :uk)
|
14
|
+
super()
|
15
|
+
|
16
|
+
self.browse_node_id = browse_node_id
|
17
|
+
self.operation = "BrowseNodeLookup"
|
18
|
+
self.region = region
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse
|
22
|
+
self.response.add_element("BrowseNodes", AmazonProductAdvertisingApi::Operations::Base::Element.new)
|
23
|
+
|
24
|
+
(self.hpricot_data/'BrowseNodes > BrowseNode').each do |element|
|
25
|
+
new_element = AmazonProductAdvertisingApi::Operations::Base::Element.new
|
26
|
+
self.response.browse_nodes << new_element
|
27
|
+
|
28
|
+
queue = []
|
29
|
+
queue << [new_element, element.containers]
|
30
|
+
|
31
|
+
queue.each do |pair|
|
32
|
+
current_element = pair[0]
|
33
|
+
current_children = pair[1]
|
34
|
+
|
35
|
+
current_children.each do |child|
|
36
|
+
if child.containers.size == 0
|
37
|
+
current_element.add_element(child.name, child.inner_html)
|
38
|
+
else
|
39
|
+
if parent_a_container?(child)
|
40
|
+
new_element = AmazonProductAdvertisingApi::Operations::Base::Element.new
|
41
|
+
current_element << new_element
|
42
|
+
queue << [new_element, child.containers]
|
43
|
+
else
|
44
|
+
new_element = current_element.add_element(child.name, AmazonProductAdvertisingApi::Operations::Base::Element.new)
|
45
|
+
queue << [new_element, child.containers]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def params
|
55
|
+
REQUEST_PARAMETERS.inject({}) do |parameters, parameter|
|
56
|
+
parameters[parameter] = eval("self.#{parameter}") unless eval("self.#{parameter}.nil?")
|
57
|
+
parameters
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module AmazonProductAdvertisingApi
|
2
|
+
module Operations
|
3
|
+
module Item
|
4
|
+
|
5
|
+
module Common
|
6
|
+
|
7
|
+
def parse
|
8
|
+
self.response.add_element("Items", AmazonProductAdvertisingApi::Operations::Base::Element.new)
|
9
|
+
|
10
|
+
(self.hpricot_data/'Items > Item').each do |element|
|
11
|
+
new_element = AmazonProductAdvertisingApi::Operations::Base::Element.new
|
12
|
+
self.response.items << new_element
|
13
|
+
|
14
|
+
queue = []
|
15
|
+
queue << [new_element, element.containers]
|
16
|
+
|
17
|
+
queue.each do |pair|
|
18
|
+
current_element = pair[0]
|
19
|
+
current_children = pair[1]
|
20
|
+
|
21
|
+
current_children.each do |child|
|
22
|
+
if child.containers.size == 0
|
23
|
+
current_element.add_element(child.name, child.inner_html)
|
24
|
+
else
|
25
|
+
if parent_a_container?(child)
|
26
|
+
new_element = AmazonProductAdvertisingApi::Operations::Base::Element.new
|
27
|
+
current_element << new_element
|
28
|
+
queue << [new_element, child.containers]
|
29
|
+
else
|
30
|
+
new_element = current_element.add_element(child.name, AmazonProductAdvertisingApi::Operations::Base::Element.new)
|
31
|
+
queue << [new_element, child.containers]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
class ItemSearch < AmazonProductAdvertisingApi::Operations::Base::Request
|
42
|
+
|
43
|
+
include Common
|
44
|
+
|
45
|
+
REQUEST_PARAMETERS = :actor, :artist, :audience_rating, :author, :availability, :brand, :browse_node, :city,
|
46
|
+
:composer, :condition, :conductor, :director, :item_page, :keywords, :manufacturer, :maximum_price,
|
47
|
+
:merchant_id, :minimum_price, :neighborhood, :orchestra, :postal_code, :power, :publisher, :related_items_page,
|
48
|
+
:relationship_type, :review_sort, :search_index, :sort, :tag_page, :tags_per_page, :tag_sort, :text_stream, :title,
|
49
|
+
:variation_page, :response_group
|
50
|
+
|
51
|
+
REQUEST_PARAMETERS.each do |param|
|
52
|
+
self.send(:attr_accessor, param)
|
53
|
+
end
|
54
|
+
|
55
|
+
def initialize(keywords, search_index = "Books", region = :uk)
|
56
|
+
super()
|
57
|
+
|
58
|
+
self.keywords = keywords
|
59
|
+
self.search_index = search_index
|
60
|
+
self.operation = "ItemSearch"
|
61
|
+
self.region = region
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def params
|
66
|
+
REQUEST_PARAMETERS.inject({}) do |parameters, parameter|
|
67
|
+
parameters[parameter] = eval("self.#{parameter}") unless eval("self.#{parameter}.nil?")
|
68
|
+
parameters
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
class ItemLookup < AmazonProductAdvertisingApi::Operations::Base::Request
|
75
|
+
|
76
|
+
include Common
|
77
|
+
|
78
|
+
REQUEST_PARAMETERS = :condition, :id_type, :item_id, :merchant_id, :offer_page, :related_items_page, :relationship_type, :review_page,
|
79
|
+
:review_sort, :search_index, :tag_page, :tags_per_page, :tag_sort, :variation_page, :response_group
|
80
|
+
|
81
|
+
REQUEST_PARAMETERS.each do |param|
|
82
|
+
self.send(:attr_accessor, param)
|
83
|
+
end
|
84
|
+
|
85
|
+
def initialize(item_id, region = :uk)
|
86
|
+
super()
|
87
|
+
|
88
|
+
self.item_id = item_id
|
89
|
+
self.operation = "ItemLookup"
|
90
|
+
self.region = region
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
def params
|
95
|
+
REQUEST_PARAMETERS.inject({}) do |parameters, parameter|
|
96
|
+
parameters[parameter] = eval("self.#{parameter}") unless eval("self.#{parameter}.nil?")
|
97
|
+
parameters
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
class SimilarityLookup < AmazonProductAdvertisingApi::Operations::Base::Request
|
104
|
+
|
105
|
+
include Common
|
106
|
+
|
107
|
+
REQUEST_PARAMETERS = :condition, :item_id, :merchant_id, :similarity_type, :response_group
|
108
|
+
|
109
|
+
REQUEST_PARAMETERS.each do |param|
|
110
|
+
self.send(:attr_accessor, param)
|
111
|
+
end
|
112
|
+
|
113
|
+
def initialize(item_id, region = :uk)
|
114
|
+
super()
|
115
|
+
|
116
|
+
self.item_id = item_id
|
117
|
+
self.operation = "SimilarityLookup"
|
118
|
+
self.region = region
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
def params
|
123
|
+
REQUEST_PARAMETERS.inject({}) do |parameters, parameter|
|
124
|
+
parameters[parameter] = eval("self.#{parameter}") unless eval("self.#{parameter}.nil?")
|
125
|
+
parameters
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class Class
|
2
|
+
def cattr_reader(sym)
|
3
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
4
|
+
unless defined? @@#{sym} # unless defined? @@hair_colors
|
5
|
+
@@#{sym} = nil # @@hair_colors = nil
|
6
|
+
end # end
|
7
|
+
#
|
8
|
+
def self.#{sym} # def self.hair_colors
|
9
|
+
@@#{sym} # @@hair_colors
|
10
|
+
end # end
|
11
|
+
#
|
12
|
+
def #{sym} # def hair_colors
|
13
|
+
@@#{sym} # @@hair_colors
|
14
|
+
end # end
|
15
|
+
EOS
|
16
|
+
end
|
17
|
+
|
18
|
+
def cattr_writer(sym)
|
19
|
+
class_eval(<<-EOS, __FILE__, __LINE__)
|
20
|
+
unless defined? @@#{sym} # unless defined? @@hair_colors
|
21
|
+
@@#{sym} = nil # @@hair_colors = nil
|
22
|
+
end # end
|
23
|
+
#
|
24
|
+
def self.#{sym}=(obj) # def self.hair_colors=(obj)
|
25
|
+
@@#{sym} = obj # @@hair_colors = obj
|
26
|
+
end # end
|
27
|
+
EOS
|
28
|
+
end
|
29
|
+
|
30
|
+
def cattr_accessor(sym)
|
31
|
+
cattr_reader(sym)
|
32
|
+
cattr_writer(sym)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
class String
|
38
|
+
|
39
|
+
def camelize(first_letter_in_uppercase = true)
|
40
|
+
if first_letter_in_uppercase
|
41
|
+
self.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
42
|
+
else
|
43
|
+
self.first + camelize(self)[1..-1]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def underscore
|
48
|
+
self.to_s.gsub(/::/, '/').
|
49
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
50
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
51
|
+
tr("-", "_").
|
52
|
+
downcase
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: completelynovel-amazon-product-advertising-api
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Gilbraith
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-11 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: mime-types
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "1.15"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: diff-lcs
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.1.2
|
34
|
+
version:
|
35
|
+
description: A nice rubyish interface to the Amazon Product Advertising API, formerly known as the Associates Web Service and before that the Amazon E-Commerce Service.
|
36
|
+
email: jon@completelynovel.com
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- EXAMPLE.rdoc
|
45
|
+
- MIT-LICENSE
|
46
|
+
- README.rdoc
|
47
|
+
- amazon-product-advertising-api.gemspec
|
48
|
+
- lib/amazon_product_advertising_api
|
49
|
+
- lib/amazon_product_advertising_api/base.rb
|
50
|
+
- lib/amazon_product_advertising_api/operations
|
51
|
+
- lib/amazon_product_advertising_api/operations/base.rb
|
52
|
+
- lib/amazon_product_advertising_api/operations/browse_node.rb
|
53
|
+
- lib/amazon_product_advertising_api/operations/item.rb
|
54
|
+
- lib/amazon_product_advertising_api/support.rb
|
55
|
+
- lib/amazon_product_advertising_api.rb
|
56
|
+
has_rdoc: false
|
57
|
+
homepage: http://github.com/completelynovel/amazon-product-advertising-api
|
58
|
+
post_install_message:
|
59
|
+
rdoc_options:
|
60
|
+
- --inline-source
|
61
|
+
- --charset=UTF-8
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: "0"
|
69
|
+
version:
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: "0"
|
75
|
+
version:
|
76
|
+
requirements: []
|
77
|
+
|
78
|
+
rubyforge_project: amazon-pa-api
|
79
|
+
rubygems_version: 1.2.0
|
80
|
+
signing_key:
|
81
|
+
specification_version: 2
|
82
|
+
summary: A nice rubyish interface to the Amazon Product Advertising API.
|
83
|
+
test_files: []
|
84
|
+
|