amazonparser 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +3 -0
- data/Rakefile +13 -0
- data/amazonparser.gemspec +18 -0
- data/lib/amazonparser.rb +162 -0
- data/test/amazonparser_test.rb +66 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6a2ad50f84dd3ca4032d984afdc279d6118e8a2e
|
4
|
+
data.tar.gz: 8ba4fcc35500d566c8fa6fd0f6b4a4a7ec359cdf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2255da99a8b6fb3cf5011da44435a99af7262d4aa630169f03a2d140542be0f3072343782a39a0fd5274fb084c19fa98995548783f888852e06ac79febeab68a
|
7
|
+
data.tar.gz: 5c94103d69e021a0db11684a3204722170ded95544b3c3995615b65d54da8a77d7b2a7c283a3a57e565805492452c790d0c019a34ca9a4c2f90914af5f20fadf
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
|
3
|
+
Rake::TestTask.new do |test|
|
4
|
+
test.libs << 'test'
|
5
|
+
test.test_files = FileList['test/*_test.rb']
|
6
|
+
end
|
7
|
+
|
8
|
+
task default: :test
|
9
|
+
|
10
|
+
desc "Open an irb session preloaded with this library"
|
11
|
+
task :console do
|
12
|
+
sh "irb -rubygems -I lib -r amazonparser.rb"
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = 'amazonparser'
|
3
|
+
gem.version = '0.0.1'
|
4
|
+
gem.summary = 'Amazon item lookup parser'
|
5
|
+
gem.description = 'Amazon item lookup parser powered by Vacuum'
|
6
|
+
gem.authors = ['Matias Fernandez']
|
7
|
+
gem.email = 'matiasfmolinari@gmail.com'
|
8
|
+
gem.homepage = 'https://github.com/MatiasFMolinari/amazonparser'
|
9
|
+
gem.license = 'MIT'
|
10
|
+
gem.files = `git ls-files`.split("\n")
|
11
|
+
gem.test_files = `git ls-files -- test/*`.split("\n")
|
12
|
+
|
13
|
+
gem.add_runtime_dependency 'plissken', '>= 1.2.0', '< 2.0'
|
14
|
+
gem.add_runtime_dependency 'recursive-open-struct', '>= 1.0.5', '< 2.0'
|
15
|
+
|
16
|
+
gem.add_development_dependency 'vacuum', '>= 1.5.0', '< 2.0'
|
17
|
+
gem.add_development_dependency 'minitest', '>= 5.10.3', '< 6.0'
|
18
|
+
end
|
data/lib/amazonparser.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'recursive-open-struct'
|
2
|
+
require 'plissken'
|
3
|
+
|
4
|
+
module AmazonParser
|
5
|
+
class << self
|
6
|
+
def parse(product_hash:)
|
7
|
+
# 1. convert hash keys to snakecase
|
8
|
+
product_hash = product_hash.to_snake_keys
|
9
|
+
|
10
|
+
# 2. convert hash to open struct
|
11
|
+
product = RecursiveOpenStruct.new(product_hash, recurse_over_arrays: true)
|
12
|
+
|
13
|
+
# 3. setup basic scopes
|
14
|
+
item = product.item_lookup_response.items.item
|
15
|
+
item_attributes = item.item_attributes
|
16
|
+
images = item.image_sets.image_set
|
17
|
+
categories = item.browse_nodes
|
18
|
+
main_category = item.browse_nodes.browse_node
|
19
|
+
offer_summary = item.offer_summary
|
20
|
+
offers = item.offers
|
21
|
+
promotions = item.offers.offer.promotions
|
22
|
+
|
23
|
+
# 4. copy attributes into root struct
|
24
|
+
|
25
|
+
# a. main response groups
|
26
|
+
product.item = item
|
27
|
+
product.item_attributes = item_attributes
|
28
|
+
product.images = images
|
29
|
+
product.categories = categories
|
30
|
+
product.main_category = main_category
|
31
|
+
product.offer_summary = offer_summary
|
32
|
+
product.offers = offers
|
33
|
+
product.promotions = promotions
|
34
|
+
|
35
|
+
# b. item
|
36
|
+
product.asin = item.asin
|
37
|
+
product.parent_asin = item.parent_asin
|
38
|
+
product.sales_rank = item.sales_rank
|
39
|
+
|
40
|
+
# c. category
|
41
|
+
product.category = main_category.is_a?(Array) ? main_category[0].name : main_category.name
|
42
|
+
|
43
|
+
# d. item attributes
|
44
|
+
product.actor = item_attributes.actor
|
45
|
+
product.artist = item_attributes.artist
|
46
|
+
product.aspect_ratio = item_attributes.aspect_ratio
|
47
|
+
product.audience_rating = item_attributes.audience_rating
|
48
|
+
product.audio_format = item_attributes.audio_format
|
49
|
+
product.author = item_attributes.author
|
50
|
+
product.brand = item_attributes.brand
|
51
|
+
product.catalog_number_list = item_attributes.catalog_number_list
|
52
|
+
product.clothing_size = item_attributes.clothing_size
|
53
|
+
product.creator = item_attributes.creator
|
54
|
+
product.department = item_attributes.department
|
55
|
+
product.director = item_attributes.director
|
56
|
+
product.ean = item_attributes.ean
|
57
|
+
product.ean_list = item_attributes.ean_list
|
58
|
+
product.edition = item_attributes.edition
|
59
|
+
product.eisbn = item_attributes.eisbn
|
60
|
+
product.esrb_age_rating = item_attributes.esrb_age_rating
|
61
|
+
product.feature = item_attributes.feature
|
62
|
+
product.format = item_attributes.format
|
63
|
+
product.genre = item_attributes.genre
|
64
|
+
product.hardware_platform = item_attributes.hardware_platform
|
65
|
+
product.hazardous_material_type = item_attributes.hazardous_material_type
|
66
|
+
product.is_adult_product = to_bool item_attributes.is_adult_product
|
67
|
+
product.is_autographed = to_bool item_attributes.is_autographed
|
68
|
+
product.isbn = item_attributes.isbn
|
69
|
+
product.is_memorabilia = to_bool item_attributes.is_memorabilia
|
70
|
+
product.issues_per_year = item_attributes.issues_per_year
|
71
|
+
product.label = item_attributes.label
|
72
|
+
product.legal_disclaimer = item_attributes.legal_disclaimer
|
73
|
+
product.list_price = item_attributes.list_price.amount&.to_i
|
74
|
+
product.manufacturer = item_attributes.manufacturer
|
75
|
+
product.max_use_age = item_attributes.manufacturer_maximum_age
|
76
|
+
product.min_use_age = item_attributes.manufacturer_minimum_age
|
77
|
+
product.manufacturer_warranty = item_attributes.manufacturer_parts_warranty_description
|
78
|
+
product.material_type = item_attributes.material_type
|
79
|
+
product.media_type = item_attributes.media_type
|
80
|
+
product.meta_type = item_attributes.metal_type
|
81
|
+
product.model = item_attributes.model
|
82
|
+
product.mpn = item_attributes.mpn
|
83
|
+
product.number_of_discs = item_attributes.number_of_discs&.to_i
|
84
|
+
product.number_of_issues = item_attributes.number_of_issues&.to_i
|
85
|
+
product.number_of_items = item_attributes.number_of_items&.to_i
|
86
|
+
product.number_of_pages = item_attributes.number_of_pages&.to_i
|
87
|
+
product.number_of_tracks = item_attributes.number_of_tracks&.to_i
|
88
|
+
product.operating_system = item_attributes.operating_system
|
89
|
+
product.package_quantity = item_attributes.package_quantity&.to_i
|
90
|
+
product.part_number = item_attributes.part_number
|
91
|
+
product.platform = item_attributes.platform
|
92
|
+
product.group = item_attributes.product_group
|
93
|
+
product.product_type_name = item_attributes.product_type_name
|
94
|
+
product.publication_date = item_attributes.publication_date
|
95
|
+
product.publisher = item_attributes.publisher
|
96
|
+
product.region_code = item_attributes.region_code
|
97
|
+
product.release_date = item_attributes.release_date
|
98
|
+
product.running_time = item_attributes.running_time
|
99
|
+
product.seikodo_product_code = item_attributes.seikodo_product_code
|
100
|
+
product.size = item_attributes.size
|
101
|
+
product.sku = item_attributes.sku
|
102
|
+
product.studio = item_attributes.studio
|
103
|
+
product.subscription_length = item_attributes.subscription_length
|
104
|
+
product.title = item_attributes.title
|
105
|
+
product.trade_in_value = item_attributes.trade_in_value
|
106
|
+
product.upc = item_attributes.upc
|
107
|
+
product.upc_list = item_attributes.upc_list
|
108
|
+
product.warranty = item_attributes.warranty
|
109
|
+
product.weee_tax_value = item_attributes.weee_tax_value
|
110
|
+
|
111
|
+
# e. package size
|
112
|
+
product.package_height = item_attributes.package_dimensions.height.__content__&.to_i
|
113
|
+
product.package_height_units = item_attributes.package_dimensions.height.units
|
114
|
+
product.package_width = item_attributes.package_dimensions.width.__content__&.to_i
|
115
|
+
product.package_width_units = item_attributes.package_dimensions.width.units
|
116
|
+
product.package_length = item_attributes.package_dimensions.length.__content__&.to_i
|
117
|
+
product.package_length_units = item_attributes.package_dimensions.length.units
|
118
|
+
|
119
|
+
# f. offers
|
120
|
+
product.offers_count = offers.total_offers&.to_i
|
121
|
+
product.price = offers.offer.dig(:offer_listing, :price, :amount)&.to_i
|
122
|
+
product.sale_price = offers.offer.dig(:offer_listing, :sale_price, :amount)&.to_i
|
123
|
+
product.discount = offers.offer.dig(:offer_listing, :amount_saved, :amount)&.to_i
|
124
|
+
product.percent_discount = offers.offer.offer_listing.percentage_saved&.to_i
|
125
|
+
product.has_super_saver_shipping = to_bool offers.offer.offer_listing.is_eligible_for_super_saver_shipping
|
126
|
+
product.has_prime = to_bool offers.offer.offer_listing.is_eligible_for_prime
|
127
|
+
product.has_prime_streaming = to_bool offers.offer.offer_listing.is_eligible_for_prime_free_digital_video
|
128
|
+
product.can_be_traded_in = to_bool offers.offer.offer_listing.is_eligible_for_trade_in
|
129
|
+
product.availability = offers.offer.offer_listing.availability
|
130
|
+
product.availability_type = offers.offer.offer_listing.availability_attributes.availability_type
|
131
|
+
product.min_hours_until_available = offers.offer.offer_listing.availability_attributes.minimum_hours&.to_i
|
132
|
+
product.max_hours_until_available = offers.offer.offer_listing.availability_attributes.maximum_hours&.to_i
|
133
|
+
|
134
|
+
# g. offer summary
|
135
|
+
product.lowest_new_price = offer_summary.dig(:lowest_new_price, :amount)&.to_i
|
136
|
+
product.lowest_used_price = offer_summary.dig(:lowest_used_price, :amount)&.to_i
|
137
|
+
product.lowest_collectibe_price = offer_summary.dig(:lowest_collectibe_price, :amount)&.to_i
|
138
|
+
product.lowest_refurbished_price = offer_summary.dig(:lowest_refurbished_price, :amount)&.to_i
|
139
|
+
product.new_count = offer_summary.total_new&.to_i
|
140
|
+
product.used_count = offer_summary.total_used&.to_i
|
141
|
+
product.collectible_count = offer_summary.total_collectible&.to_i
|
142
|
+
product.refurbished_count = offer_summary.total_refurbished&.to_i
|
143
|
+
|
144
|
+
# h. first promo
|
145
|
+
product.promo_category = promotions&.promotion&.summary&.category
|
146
|
+
product.promo_requirement = promotions&.promotion&.summary&.eligibility_requirement_description
|
147
|
+
product.promo_benefit = promotions&.promotion&.summary&.benefit_description
|
148
|
+
product.promo_terms = promotions&.promotion&.summary&.terms_and_conditions
|
149
|
+
|
150
|
+
product
|
151
|
+
end
|
152
|
+
|
153
|
+
private
|
154
|
+
|
155
|
+
def to_bool(string)
|
156
|
+
return nil if string.nil?
|
157
|
+
return true if string == true || string == "1"
|
158
|
+
return false if string == false || string == "0"
|
159
|
+
raise ArgumentError.new("invalid value for Boolean: '#{string}'")
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'minitest/autorun'
|
2
|
+
require 'minitest/pride'
|
3
|
+
require 'amazonparser'
|
4
|
+
require 'vacuum'
|
5
|
+
|
6
|
+
class AmazonParserTest < Minitest::Test
|
7
|
+
def test_request
|
8
|
+
# 1. init vacuum
|
9
|
+
request = Vacuum.new('US', true)
|
10
|
+
request.configure(
|
11
|
+
aws_access_key_id: ENV['AWS_ACCESS_KEY_ID'],
|
12
|
+
aws_secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'],
|
13
|
+
associate_tag: 'makeuppicker-20',
|
14
|
+
version: nil
|
15
|
+
)
|
16
|
+
|
17
|
+
# 2. setup request
|
18
|
+
query = {
|
19
|
+
'ItemId' => 'B000V3MGFS',
|
20
|
+
'ResponseGroup' => 'BrowseNodes, Images, ItemAttributes, OfferFull, PromotionSummary, SalesRank'
|
21
|
+
}
|
22
|
+
|
23
|
+
# 3. request item
|
24
|
+
response = request.item_lookup(query: query, persistent: true)
|
25
|
+
response.parser = nil
|
26
|
+
|
27
|
+
# 4. convert xml response to hash
|
28
|
+
product_hash = response.parse
|
29
|
+
|
30
|
+
# 5. parse product
|
31
|
+
product = AmazonParser.parse(product_hash: product_hash)
|
32
|
+
|
33
|
+
# display output while transforming into tests
|
34
|
+
puts "asin: " + product.asin.inspect
|
35
|
+
puts "title: " + product.title.inspect
|
36
|
+
puts "category: " + product.category.inspect
|
37
|
+
puts "brand: " + product.brand.inspect
|
38
|
+
|
39
|
+
puts "list_price: " + product.list_price.inspect
|
40
|
+
puts "price: " + product.price.inspect
|
41
|
+
puts "sale_price: " + product.sale_price.inspect
|
42
|
+
puts "discount: " + product.discount.inspect
|
43
|
+
puts "lowest_new_price: " + product.lowest_new_price.inspect
|
44
|
+
puts "lowest_used_price: " + product.lowest_used_price.inspect
|
45
|
+
puts "new_count: " + product.new_count.inspect
|
46
|
+
puts "used_count: " + product.used_count.inspect
|
47
|
+
puts "percent_discount: " + product.percent_discount.inspect
|
48
|
+
puts "availability_message: " + product.availability_message.inspect
|
49
|
+
puts "availability_type: " + product.availability_type.inspect
|
50
|
+
puts "min_hours_until_available: " + product.min_hours_until_available.inspect
|
51
|
+
puts "max_hours_until_available: " + product.max_hours_until_available.inspect
|
52
|
+
puts "has_super_saver_shipping: " + product.has_super_saver_shipping.inspect
|
53
|
+
puts "has_prime: " + product.has_prime.inspect
|
54
|
+
|
55
|
+
puts "color: " + product.color.inspect
|
56
|
+
puts "size: " + product.size.inspect
|
57
|
+
puts "package_quantity: " + product.package_quantity.inspect
|
58
|
+
puts "part_number: " + product.part_number.inspect
|
59
|
+
puts "group: " + product.group.inspect
|
60
|
+
puts "manufacturer: " + product.manufacturer.inspect
|
61
|
+
puts "release_date: " + product.release_date.inspect
|
62
|
+
puts "number_of_items: " + product.number_of_items.inspect
|
63
|
+
puts "publisher: " + product.publisher.inspect
|
64
|
+
puts "product_type_name: " + product.type.inspect
|
65
|
+
end
|
66
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: amazonparser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Matias Fernandez
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-07-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: plissken
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.2.0
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '2.0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 1.2.0
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: recursive-open-struct
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 1.0.5
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '2.0'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 1.0.5
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '2.0'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: vacuum
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.5.0
|
60
|
+
- - "<"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '2.0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.5.0
|
70
|
+
- - "<"
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '2.0'
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: minitest
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - ">="
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: 5.10.3
|
80
|
+
- - "<"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '6.0'
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 5.10.3
|
90
|
+
- - "<"
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: '6.0'
|
93
|
+
description: Amazon item lookup parser powered by Vacuum
|
94
|
+
email: matiasfmolinari@gmail.com
|
95
|
+
executables: []
|
96
|
+
extensions: []
|
97
|
+
extra_rdoc_files: []
|
98
|
+
files:
|
99
|
+
- README.md
|
100
|
+
- Rakefile
|
101
|
+
- amazonparser.gemspec
|
102
|
+
- lib/amazonparser.rb
|
103
|
+
- test/amazonparser_test.rb
|
104
|
+
homepage: https://github.com/MatiasFMolinari/amazonparser
|
105
|
+
licenses:
|
106
|
+
- MIT
|
107
|
+
metadata: {}
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
requirements:
|
119
|
+
- - ">="
|
120
|
+
- !ruby/object:Gem::Version
|
121
|
+
version: '0'
|
122
|
+
requirements: []
|
123
|
+
rubyforge_project:
|
124
|
+
rubygems_version: 2.6.11
|
125
|
+
signing_key:
|
126
|
+
specification_version: 4
|
127
|
+
summary: Amazon item lookup parser
|
128
|
+
test_files:
|
129
|
+
- test/amazonparser_test.rb
|