compare_supermarkets 0.1.12 → 0.3.1
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.
- checksums.yaml +4 -4
- data/config/environment.rb +1 -0
- data/lib/compare_supermarkets/cli.rb +12 -5
- data/lib/compare_supermarkets/product.rb +24 -31
- data/lib/compare_supermarkets/scraper.rb +59 -32
- data/lib/compare_supermarkets/supermarket.rb +59 -0
- data/lib/compare_supermarkets/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bbf654fdd40a10a41089214f44231f0e8c5cd8656d2aab638cbb6f7de7d2a23
|
4
|
+
data.tar.gz: cacc2dcf4343553a0114ef6b9aa9bad3b298e130913f7dcf5345189504da681d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a7b08c8f7f9b5ab53b2d491303db0b52e09bf2bfb3721671c064f4f8a2fda2a262b15695b074a22fe7d18982ad68152f6df7ff1f9949a1ff4d662ecc7587f5d3
|
7
|
+
data.tar.gz: 8a7fe54602b4f222d8b67d0de4928c8101d90834fb1df7ddadf03847e459816dbe93620a78998ed7fbda20975643a0b5896ebd939bed9c95f1181e27bb953964
|
data/config/environment.rb
CHANGED
@@ -9,5 +9,6 @@ require_relative '../lib/compare_supermarkets/scraper'
|
|
9
9
|
require_relative '../lib/compare_supermarkets/product'
|
10
10
|
require_relative '../lib/compare_supermarkets/cli'
|
11
11
|
require_relative '../lib/compare_supermarkets/version'
|
12
|
+
require_relative '../lib/compare_supermarkets/supermarket'
|
12
13
|
|
13
14
|
Watir.default_timeout = 0
|
@@ -5,7 +5,7 @@ class CompareSupermarkets::CLI
|
|
5
5
|
puts ""
|
6
6
|
puts "Type q at any time to exit."
|
7
7
|
puts ""
|
8
|
-
puts "Would you like to compare prices between Coles and
|
8
|
+
puts "Would you like to compare prices between Coles, Woolworths and IGA? (Y/N)"
|
9
9
|
input = gets.strip.downcase
|
10
10
|
puts ""
|
11
11
|
if input == "y"
|
@@ -42,7 +42,7 @@ class CompareSupermarkets::CLI
|
|
42
42
|
self.search_supermarkets(input)
|
43
43
|
puts ""
|
44
44
|
puts ""
|
45
|
-
if CompareSupermarkets::Product.count >
|
45
|
+
if CompareSupermarkets::Product.count > 20
|
46
46
|
puts ""
|
47
47
|
puts "Ooo, jeez, seems like we have a lot of results."
|
48
48
|
puts "We have #{CompareSupermarkets::Product.count} results for you."
|
@@ -52,8 +52,8 @@ class CompareSupermarkets::CLI
|
|
52
52
|
change_search_term
|
53
53
|
elsif CompareSupermarkets::Product.count == 0
|
54
54
|
puts ""
|
55
|
-
puts "Ohhh man! Doesn't seem like
|
56
|
-
puts "that product."
|
55
|
+
puts "Ohhh man! Doesn't seem like any of these supermarkets"
|
56
|
+
puts "carry that product."
|
57
57
|
puts ""
|
58
58
|
change_search_term
|
59
59
|
else
|
@@ -111,6 +111,8 @@ class CompareSupermarkets::CLI
|
|
111
111
|
puts ""
|
112
112
|
puts "5 - Only Woolworths items"
|
113
113
|
puts ""
|
114
|
+
puts "6 - Only IGA items"
|
115
|
+
puts ""
|
114
116
|
input = gets.strip
|
115
117
|
puts ""
|
116
118
|
choice(input)
|
@@ -135,6 +137,10 @@ class CompareSupermarkets::CLI
|
|
135
137
|
how_to_sort ? direction = "asc" : direction = "desc"
|
136
138
|
choice = CompareSupermarkets::Product.woolworths_sorted_by_price
|
137
139
|
print_items(choice, direction)
|
140
|
+
elsif input == "6"
|
141
|
+
how_to_sort ? direction = "asc" : direction = "desc"
|
142
|
+
choice = CompareSupermarkets::Product.iga_sorted_by_price
|
143
|
+
print_items(choice, direction)
|
138
144
|
elsif input == ""
|
139
145
|
invalid_input
|
140
146
|
how_to_display
|
@@ -200,6 +206,7 @@ class CompareSupermarkets::CLI
|
|
200
206
|
how_to_display
|
201
207
|
elsif input == "2"
|
202
208
|
CompareSupermarkets::Product.clear_all
|
209
|
+
CompareSupermarkets::Supermarket.clear_all
|
203
210
|
start
|
204
211
|
elsif input == ""
|
205
212
|
invalid_input
|
@@ -263,7 +270,7 @@ class CompareSupermarkets::CLI
|
|
263
270
|
def print_items(choice, direction)
|
264
271
|
direction == "asc" ? choice = choice : choice = choice.reverse
|
265
272
|
choice.each do |item|
|
266
|
-
p "Supermarket: #{item.supermarket}"
|
273
|
+
p "Supermarket: #{item.supermarket.name}"
|
267
274
|
p "Item name: #{item.name}"
|
268
275
|
p "Item price: $#{item.dollar_value}.#{item.cent_value}"
|
269
276
|
p "Item unit size: #{item.unit_size}"
|
@@ -1,10 +1,7 @@
|
|
1
1
|
class CompareSupermarkets::Product
|
2
|
-
|
3
|
-
attr_reader :supermarket, :name, :price, :unit_size, :url, :dollar_value, :cent_value
|
2
|
+
attr_accessor :supermarket, :name, :price, :unit_size, :url, :dollar_value, :cent_value
|
4
3
|
|
5
4
|
@@all = []
|
6
|
-
@@coles_all = []
|
7
|
-
@@woolworths_all = []
|
8
5
|
|
9
6
|
def initialize (supermarket = nil, name = nil, price=nil, unit_size = nil, url = nil, dollar_value=nil, cent_value=nil)
|
10
7
|
@supermarket = supermarket
|
@@ -13,45 +10,31 @@ class CompareSupermarkets::Product
|
|
13
10
|
@unit_size = unit_size
|
14
11
|
@dollar_value = dollar_value
|
15
12
|
@cent_value = cent_value
|
16
|
-
@url = @supermarket == "Coles"
|
13
|
+
@url = if @supermarket.name == "Coles"
|
14
|
+
"https://shop.coles.com.au#{url}"
|
15
|
+
elsif @supermarket.name == "Woolworths"
|
16
|
+
"https://www.woolworths.com.au#{url}"
|
17
|
+
else
|
18
|
+
url
|
19
|
+
end
|
17
20
|
@@all << self
|
18
|
-
if @supermarket == "Coles"
|
19
|
-
@@coles_all << self
|
20
|
-
else
|
21
|
-
@@woolworths_all << self
|
22
|
-
end
|
23
21
|
end
|
24
22
|
|
25
23
|
def self.all
|
26
|
-
|
24
|
+
@@all
|
27
25
|
end
|
28
26
|
|
29
27
|
def self.count
|
30
28
|
@@all.count
|
31
29
|
end
|
32
30
|
|
33
|
-
def
|
34
|
-
|
35
|
-
product.css(".product-name").text,
|
36
|
-
product.css(".package-price").text.delete_prefix('$').gsub('per', '/'),
|
37
|
-
product.css(".package-size.accessibility-inline").text,
|
38
|
-
product.css(".product-image-link").attribute('href'),
|
39
|
-
product.css(".dollar-value").text,
|
40
|
-
product.css(".cent-value").text.delete_prefix('.'))
|
31
|
+
def supermarket_name
|
32
|
+
self.supermarket ? self.supermarket.name : nil
|
41
33
|
end
|
42
34
|
|
43
|
-
def self.woolworths_new_from_search(product)
|
44
|
-
product_to_compare = self.new("Woolworths",
|
45
|
-
product.css(".shelfProductTile-descriptionLink").text,
|
46
|
-
product.css(".shelfProductTile-cupPrice.ng-star-inserted").text.delete_prefix(' $').chomp(" "),
|
47
|
-
product.css(".shelfProductTile-descriptionLink").text.split(" ").last,
|
48
|
-
product.css(".shelfProductTile-descriptionLink").attribute('href').value,
|
49
|
-
product.css(".price-dollars").text,
|
50
|
-
product.css(".price-cents").text)
|
51
|
-
end
|
52
35
|
|
53
36
|
def self.all_items_sorted_by_price
|
54
|
-
sorted =
|
37
|
+
sorted = self.all.sort_by! do |s|
|
55
38
|
price_to_sort = s.dollar_value + '.' + s.cent_value
|
56
39
|
price_to_sort.to_f
|
57
40
|
end
|
@@ -62,14 +45,24 @@ class CompareSupermarkets::Product
|
|
62
45
|
end
|
63
46
|
|
64
47
|
def self.coles_sorted_by_price
|
65
|
-
|
48
|
+
coles_items = self.all.select{|product| product.supermarket_name == "Coles"}
|
49
|
+
coles_items.sort_by! do |s|
|
66
50
|
price_to_sort = s.dollar_value + '.' + s.cent_value
|
67
51
|
price_to_sort.to_f
|
68
52
|
end
|
69
53
|
end
|
70
54
|
|
71
55
|
def self.woolworths_sorted_by_price
|
72
|
-
|
56
|
+
woolworths_items = self.all.select{|product| product.supermarket_name == "Woolworths"}
|
57
|
+
woolworths_items.sort_by! do |s|
|
58
|
+
price_to_sort = s.dollar_value + '.' + s.cent_value
|
59
|
+
price_to_sort.to_f
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.iga_sorted_by_price
|
64
|
+
iga_items = self.all.select{|product| product.supermarket_name == "IGA"}
|
65
|
+
iga_items.sort_by! do |s|
|
73
66
|
price_to_sort = s.dollar_value + '.' + s.cent_value
|
74
67
|
price_to_sort.to_f
|
75
68
|
end
|
@@ -7,53 +7,80 @@ class CompareSupermarkets::Scraper
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.search_supermarkets(search_term)
|
10
|
-
|
11
|
-
|
10
|
+
supermarkets = ["Coles", "Woolworths", "IGA"]
|
11
|
+
supermarkets.each do |supermarket|
|
12
|
+
search_for(supermarket, search_term)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.search_for(supermarket, search_term)
|
17
|
+
open_browser(supermarket, search_term)
|
12
18
|
end
|
13
19
|
|
14
|
-
def self.
|
20
|
+
def self.open_browser(supermarket, search_term)
|
15
21
|
browser = Watir::Browser.new :chrome
|
16
|
-
|
22
|
+
if supermarket.downcase == "coles"
|
23
|
+
search = "https://shop.coles.com.au/a/national/everything/search/#{search_term}"
|
24
|
+
class_name = "products"
|
25
|
+
elsif supermarket.downcase == "woolworths"
|
26
|
+
search = "https://www.woolworths.com.au/shop/search/products?searchTerm=#{search_term}"
|
27
|
+
class_name = "layoutWrapper"
|
28
|
+
else
|
29
|
+
search = "https://new.igashop.com.au/sm/pickup/rsid/53363/results?q=#{search_term}"
|
30
|
+
class_name = ["Listing-sc-1vfhaq2", "iQljRa"]
|
31
|
+
end
|
32
|
+
browser.goto(search)
|
33
|
+
self.handle_waiting(browser, supermarket, class_name, search_term)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.handle_waiting(browser, supermarket, class_name, search_term)
|
17
37
|
begin
|
18
|
-
|
38
|
+
js_doc = browser.element(class: class_name).wait_until(&:present?)
|
19
39
|
rescue
|
20
|
-
puts "
|
40
|
+
puts "#{supermarket} does not have any #{search_term}"
|
21
41
|
puts ""
|
22
|
-
puts "Let's check Woolworths"
|
23
42
|
puts ""
|
43
|
+
if supermarket.downcase != "iga"
|
44
|
+
puts "Let's check the next one"
|
45
|
+
end
|
24
46
|
puts ""
|
25
47
|
else
|
26
|
-
|
27
|
-
|
28
|
-
all_coles_products.each do |product|
|
29
|
-
if product.css(".product-name").text != ""
|
30
|
-
CompareSupermarkets::Product.coles_new_from_search(product)
|
31
|
-
end
|
32
|
-
end
|
48
|
+
products = Nokogiri::HTML(js_doc.inner_html)
|
49
|
+
self.add_supermarket_products(supermarket, products, search_term)
|
33
50
|
ensure
|
34
51
|
browser.close
|
35
52
|
end
|
36
53
|
end
|
37
54
|
|
38
|
-
def self.
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
rescue
|
44
|
-
puts "Woolworths does not have this product"
|
45
|
-
else
|
46
|
-
woolworths_products = Nokogiri::HTML(woolworths_js_doc.inner_html)
|
47
|
-
woolworths_all_products = woolworths_products.css(".shelfProductTile-content")
|
48
|
-
woolworths_all_products.each do |product|
|
49
|
-
if product.css(".shelfProductTile-descriptionLink").text != ""
|
50
|
-
if product.css(".unavailableSection.width-full.ng-star-inserted").empty?
|
51
|
-
CompareSupermarkets::Product.woolworths_new_from_search(product)
|
52
|
-
end
|
53
|
-
end
|
55
|
+
def self.add_supermarket_products(supermarket, products, search_term)
|
56
|
+
new_supermarket = CompareSupermarkets::Supermarket.new(supermarket)
|
57
|
+
self.which_supermarket(supermarket, products).each do |product|
|
58
|
+
if check?(supermarket, product, search_term)
|
59
|
+
new_supermarket.add_product(product)
|
54
60
|
end
|
55
|
-
|
56
|
-
|
61
|
+
end
|
62
|
+
if new_supermarket.products.count == 0
|
63
|
+
puts "#{supermarket} do not have any #{search_term}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.check?(supermarket, product, search_term)
|
68
|
+
if supermarket.downcase == "coles"
|
69
|
+
check = product.css(".product-name").text != ""
|
70
|
+
elsif supermarket.downcase == "woolworths"
|
71
|
+
check = product.css(".shelfProductTile-descriptionLink").text != ""
|
72
|
+
else
|
73
|
+
check = product.css(".sc-hKFyIo.bdDYJz").text.downcase[search_term]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.which_supermarket(supermarket, products)
|
78
|
+
if supermarket.downcase == "coles"
|
79
|
+
all_products = products.css(".product")
|
80
|
+
elsif supermarket.downcase == "woolworths"
|
81
|
+
all_products = products.css(".shelfProductTile-content")
|
82
|
+
else
|
83
|
+
all_products = products.css(".ColListing-sc-lcurnl.kYBrWq")
|
57
84
|
end
|
58
85
|
end
|
59
86
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
class CompareSupermarkets::Supermarket
|
2
|
+
attr_accessor :name
|
3
|
+
|
4
|
+
@@all = []
|
5
|
+
|
6
|
+
def initialize(name=nil)
|
7
|
+
@name = name
|
8
|
+
@@all << self
|
9
|
+
@products = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.all
|
13
|
+
@@all
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_product(product)
|
17
|
+
if self.name == "Coles"
|
18
|
+
new_product = CompareSupermarkets::Product.new(self,
|
19
|
+
product.css(".product-name").text,
|
20
|
+
product.css(".package-price").text.delete_prefix('$').gsub('per', '/'),
|
21
|
+
product.css(".package-size.accessibility-inline").text.chomp(' '),
|
22
|
+
product.css(".product-image-link").attribute('href'),
|
23
|
+
product.css(".dollar-value").text,
|
24
|
+
product.css(".cent-value").text.delete_prefix('.'))
|
25
|
+
elsif self.name == "Woolworths"
|
26
|
+
new_product = CompareSupermarkets::Product.new(self,
|
27
|
+
product.css(".shelfProductTile-descriptionLink").text,
|
28
|
+
product.css(".shelfProductTile-cupPrice.ng-star-inserted").text.delete_prefix(' $').chomp(" "),
|
29
|
+
product.css(".shelfProductTile-descriptionLink").text.split(" ").last,
|
30
|
+
product.css(".shelfProductTile-descriptionLink").attribute('href').value,
|
31
|
+
product.css(".price-dollars").text,
|
32
|
+
product.css(".price-cents").text)
|
33
|
+
else
|
34
|
+
price_css = if product.css(".ProductCardPrice-sc-zgh1l1.hwVjs").text.delete_prefix("$").split(".").first
|
35
|
+
".ProductCardPrice-sc-zgh1l1.hwVjs"
|
36
|
+
else
|
37
|
+
".ProductCardPrice-sc-zgh1l1.jYaBFk"
|
38
|
+
end
|
39
|
+
new_product = CompareSupermarkets::Product.new(self,
|
40
|
+
product.css(".sc-hKFyIo.bdDYJz").text.split(', ').first,
|
41
|
+
product.css(".ProductCardPriceInfo-sc-1o21dmb.iDDqhD").text.delete_prefix("$").gsub("/", " / "),
|
42
|
+
product.css(".sc-hKFyIo.bdDYJz").text.split(', ').last,
|
43
|
+
product.css(".ProductCardHiddenLink-sc-y1ynto.hGUSDV").attribute('href').value,
|
44
|
+
product.css(price_css).text.delete_prefix("$").split(".").first,
|
45
|
+
product.css(price_css).text.split(".").last.chomp(" avg/ea")
|
46
|
+
)
|
47
|
+
end
|
48
|
+
@products << new_product
|
49
|
+
end
|
50
|
+
|
51
|
+
def products
|
52
|
+
CompareSupermarkets::Product.all.select{|product| product.supermarket == self}
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.clear_all
|
56
|
+
@@all.clear
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: compare_supermarkets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Berger Howes
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-09-
|
11
|
+
date: 2021-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -108,8 +108,8 @@ dependencies:
|
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: 3.142.7
|
111
|
-
description: Will search Woolworths and
|
112
|
-
input search parameter **Google Chrome Required**
|
111
|
+
description: Will search Woolworths, Coles and IGA online stores for prices based
|
112
|
+
on an input search parameter **Google Chrome Required**
|
113
113
|
email:
|
114
114
|
- happymelonbox@gmail.com
|
115
115
|
executables:
|
@@ -125,6 +125,7 @@ files:
|
|
125
125
|
- lib/compare_supermarkets/cli.rb
|
126
126
|
- lib/compare_supermarkets/product.rb
|
127
127
|
- lib/compare_supermarkets/scraper.rb
|
128
|
+
- lib/compare_supermarkets/supermarket.rb
|
128
129
|
- lib/compare_supermarkets/version.rb
|
129
130
|
homepage: http://rubygems.org/gems/compare_supermarkets
|
130
131
|
licenses:
|