applephile 0.1.1 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e713864e37dd7643ec6cf1044f273ba3e7bf786ba0fcab93fc203e244f1fbc0
4
- data.tar.gz: f80873e73af63d05bbabe2db5f1c1bae9c0cb21858629b666819654d1ebe713c
3
+ metadata.gz: 3618935c4e88ada9eea742356249211938111ec7f71caaa4ed3847bd905256d8
4
+ data.tar.gz: cf806e277f666de2db140762b401663178a7beb9742fea9fdc7b36b50cdaf10b
5
5
  SHA512:
6
- metadata.gz: 395fa8484d87a669cb3e1b91023eed44047d80a61f3e7be38e5cf1dd327af8e62f89a93fd9f155768cfb75a4d21e0af3dac5c455faf1da6757ad9cbf4c463e86
7
- data.tar.gz: 5325dfa6829a069e7875bfbd2abd61c91b46e7a98cf830a888157598408efe16e22a65b62c5aa08f7e4e02b5dccd4bc61a7507b05479bf7f1eb797284831dd6c
6
+ metadata.gz: ae3d3f9b7e1fefb353d6c95035c0fa35ff481566567b076378b1df0bfc53ab6e52ef820feb782df256f34c5e77fbaca0d44d14a96827d6d8c3a05a2d704d18b6
7
+ data.tar.gz: 710e4ec59c56177a6d8f1dfc6c8a7463370a7ec459a604a5d0781cc5c88dde087e24e83e5a76f774e33f42e50afd2d460425e44ca6dfb62e76ace1293da26233
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
  require_relative '../config/environment.rb'
3
3
 
4
- CLI.new.run
4
+ Applephile::CLI.new.run
@@ -1 +1,6 @@
1
- require_relative '../config/environment.rb'
1
+ require_relative '../config/environment.rb'
2
+
3
+ module Applephile
4
+ class Error < StandardError; end
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,24 @@
1
+ module Applephile
2
+ class City
3
+ attr_accessor :name, :state, :city_url
4
+ attr_reader :items
5
+
6
+ @@all = []
7
+
8
+ def initialize(city_attributes)
9
+ city_attributes.each {|key, value| self.send(("#{key}="), value)}
10
+ @items = []
11
+ @@all << self
12
+ end
13
+
14
+ def add_item(item)
15
+ item.city = self
16
+ @items << item
17
+ item
18
+ end
19
+
20
+ def get_apple_prods_by_price(set_price)
21
+ @items.select { |item| item.price.to_i >= set_price.to_i }
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,139 @@
1
+ module Applephile
2
+ class CLI
3
+ INTRO_MESSAGE = "WELCOME TO CRAIGSLIST SCRAPPER!"
4
+
5
+ def run
6
+ @scrape = Applephile::CraigsList.new
7
+ puts INTRO_MESSAGE
8
+ choice = ""
9
+ while choice != "exit"
10
+ choice = display_main_menu
11
+ if choice == "scrape"
12
+ get_menu_input
13
+ create_items_from_array(scrape_apple_prodcuts)
14
+ grab_apple_prodcuts
15
+ end
16
+ end
17
+ end
18
+
19
+
20
+ def display_main_menu
21
+ stars = "************************".colorize(:yellow)
22
+ puts "#{stars} MAIN MENU #{stars}"
23
+ puts "Enter \"scrape\" to scrape.".colorize(:blue)
24
+ puts "Enter \"exit\" to end program.".colorize(:yellow)
25
+ puts "What would you like to do?".colorize(:blue)
26
+ gets.chomp
27
+ end
28
+
29
+ def get_menu_input
30
+ display_states
31
+ puts "Please enter a number for the state you'd like to scrape.".colorize(:green)
32
+ #convert number input from user
33
+ @state_scraped = convert_to_state(gets.chomp)
34
+ display_cities(@state_scraped)
35
+ puts "Please enter a number for the city you'd like to scrape.".colorize(:green)
36
+ @city_scraped = convert_to_city(@state_scraped, gets.chomp)
37
+ puts "You have chosen the state of #{@state_scraped}, and the city of #{@city_scraped.capitalize}."
38
+ end
39
+
40
+ def display_states
41
+ @scrape.get_states_names.each_with_index do |state, index|
42
+ print "#{index + 1}. #{state} ".ljust(28)
43
+ if (index + 1) % 5 == 0
44
+ print "\n"
45
+ end
46
+ end
47
+ print "\n"
48
+ end
49
+
50
+ def display_cities(state)
51
+ @state_cities = @scrape.get_state_cities(state)
52
+ #find max length of city and use it left justify everything else for screen output
53
+ max_length = @state_cities.map(&:length).max
54
+ @state_cities.each_with_index do |city, index|
55
+ print "#{index + 1}. #{city.capitalize.ljust(max_length)} "
56
+ if (index + 1) % 3 == 0
57
+ print "\n"
58
+ end
59
+ end
60
+ print "\n"
61
+ end
62
+
63
+ def convert_to_state(state_number)
64
+ #it takes in a number and returns the corresponding state's name
65
+ @scrape.get_states_names[state_number.to_i - 1]
66
+ end
67
+
68
+ def convert_to_city(state, city_number)
69
+ #it takes in a number and returns the corresponding city's name
70
+ @state_cities[city_number.to_i - 1]
71
+ end
72
+
73
+ def scrape_apple_prodcuts
74
+ @scraped_city_url = @scrape.return_city_link(@state_scraped, @city_scraped)
75
+ @phones = @scrape.scrape_by_city_url(@scraped_city_url)
76
+ end
77
+
78
+ def grab_apple_prodcuts
79
+ puts "Price enter a price higher than 150 to see the list of phones, defualt price is 150.".colorize(:blue)
80
+ display_apple_products_info(@city.get_apple_prods_by_price(gets.chomp))
81
+ end
82
+
83
+ def create_items_from_array(phones_array)
84
+ if phones_array.empty?
85
+ puts "Your search return zero hits, please scrape again"
86
+ get_menu_input
87
+ create_items_from_array(scrape_apple_products())
88
+ else
89
+ @city = Applephile::City.new({:name => @city_scraped, :state => @state_scraped,
90
+ :city_url => @scraped_city_url})
91
+ phones_array.each do |phone_info|
92
+ @city.add_item(Applephile::Item.new(phone_info))
93
+ end
94
+ end
95
+ end
96
+
97
+ def display_apple_products_info(apple_products)
98
+ separator = "-+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+--+-+-+".colorize(:yellow)
99
+ puts "The following phones were found in accordance to your search parameters."
100
+ choice = ""
101
+ while choice != "exit"
102
+ apple_products.each_with_index do |product, index|
103
+ puts "#{index + 1}: #{product.description}"
104
+ puts "Price: $#{product.price}"
105
+ puts "Phone's url: #{product.url}"
106
+ puts "Phone's City: #{product.city.name}"
107
+ puts separator
108
+
109
+ if (index + 1) % 5 == 0
110
+ # puts "Enter number to see link phone on browser.".colorize(:cyan)
111
+ # puts "next for more phones".colorize(:green)
112
+ # puts "Or enter exit to re-scrape.".colorize(:blue)
113
+
114
+ choice = get_choice
115
+ if choice == "next"
116
+ next
117
+ elsif choice == 'exit'
118
+ break
119
+ else
120
+ #make sure screen stays on all present create_items_from_array
121
+ phone_url = apple_products[choice.to_i - 1].url
122
+ system("open", phone_url)
123
+ choice = get_choice
124
+ end
125
+ end
126
+ end
127
+ puts "There are no moh phones to show."
128
+ end
129
+ end
130
+
131
+ def get_choice
132
+ puts "Enter number to see link phone on browser.".colorize(:cyan)
133
+ puts "next for more phones".colorize(:green)
134
+ puts "Or enter exit to re-scrape.".colorize(:blue)
135
+ gets.chomp
136
+ end
137
+
138
+ end
139
+ end
@@ -0,0 +1,106 @@
1
+ require 'nokogiri'
2
+ require 'open-uri'
3
+ require 'pry'
4
+
5
+ module Applephile
6
+ class CraigsList
7
+ attr_accessor :site_url, :doc
8
+
9
+ def initialize()
10
+ @site_url = "https://www.craigslist.org/about/sites"
11
+ @doc = Nokogiri::HTML(open(@site_url))
12
+ end
13
+
14
+ def get_states_names
15
+ #it returns an array of states of the U.S., CLI will use to display them
16
+ doc.css(".colmask").first.css("h4").collect { |st| st.text}
17
+ end
18
+
19
+ def get_state_cities(state_name)
20
+ #it returns an array of cities belonging to a particular state
21
+ #1. find the state first.
22
+ #2. then collect the state's city array, return a flatten array so only cities can be used
23
+ #to be displayed in CLI
24
+ state_cities_array = []
25
+ states_cities_links.each do |states, cities_links|
26
+ if states.to_s == state_name
27
+ #collect only cities
28
+ state_cities_array = cities_links.collect { |city| city.keys }
29
+ break
30
+ end
31
+ end
32
+ state_cities_array.flatten!
33
+
34
+ end
35
+
36
+ def return_city_link(state, city)
37
+ #it returns the link of a particular city
38
+ #1. find state hash
39
+ #2. find the city
40
+ #3. get city's link
41
+ city_url = ""
42
+ states_cities_links.find do |key, value|
43
+ if key.to_s == state
44
+ value.find do |city_hash|
45
+ if city_hash.has_key?(city)
46
+ city_url = city_hash[city]
47
+ end
48
+ end
49
+ end
50
+ end
51
+ city_url
52
+ end
53
+ def scrape_by_city_url(city_url)
54
+ items_array_of_hashes = []
55
+ #1. returns an array of hashes for every link (phone found) for a particular scrape criteria
56
+ #2. build site link with searching criteria phones with pic, new, os
57
+ #3. grab all phones that meet this search criteria.
58
+ #4. traverse the collection, and grab each needed attribute one by one.
59
+ #5. build hash, and save it to array.
60
+ #6. return hash
61
+ city_url = city_url + "search/moa?hasPic=1&condition=10&mobile_os=2"
62
+ city_doc = Nokogiri::HTML(open(city_url))
63
+ grab_all_phones = city_doc.css(".result-info")
64
+ grab_all_phones.each do |phones|
65
+ phone_url = phones.css("a")[0]["href"]
66
+ phone_price = phones.css(".result-price").text.split("$")[1]
67
+ phone_description = phones.css("a").text.split("\n")[0]
68
+ items_array_of_hashes.push({:url => phone_url,
69
+ :price => phone_price,
70
+ :description => phone_description})
71
+ end
72
+ items_array_of_hashes
73
+ end
74
+
75
+
76
+ private
77
+
78
+ def cities_and_links
79
+ #it returns a two dimensional array of cities, with their links as a hash by the state
80
+ # [[{"citya" => linka}, {"cityb" => linkb}, {"cityc" => linkc}], [{"cityz" => linkz}]]
81
+
82
+ two_dimension_city = []
83
+ doc.css(".colmask").first.css("ul").each do |city|
84
+ #collect returns [{"city1" => link1}, {city2 => link2}]
85
+ #collect removes "/" and unnecessary spaces from cities
86
+ two_dimension_city.push(city.css("li a").collect { |city| { city.text.split("/")[0].strip => city["href"] }})
87
+ end
88
+ two_dimension_city
89
+ end
90
+
91
+ def states_cities_links
92
+ #returns a array of hashes with keys equal to states, and values
93
+ #equal to an array of cities and their respective links
94
+ #{ :state1 => [{"city1" => link1}, {city2 => link2}, {city3 => link3}],
95
+ # :state2 => [{}]}
96
+
97
+ states_cities_links_hash = {}
98
+ #proceed by states, make hash, then push into array
99
+ #cities index implicitly starts from the first state
100
+ get_states_names.each_with_index do |state, index|
101
+ states_cities_links_hash[state.to_sym] = cities_and_links[index]
102
+ end
103
+ states_cities_links_hash
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,9 @@
1
+ module Applephile
2
+ class Item
3
+ attr_accessor :city, :price, :description, :url
4
+
5
+ def initialize(item_attributes)
6
+ item_attributes.each {|key, value| self.send(("#{key}="), value)}
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module Applephile
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: applephile
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ramon Chavez
@@ -116,11 +116,11 @@ files:
116
116
  - bin/setup
117
117
  - config/environment.rb
118
118
  - lib/applephile.rb
119
+ - lib/applephile/city.rb
120
+ - lib/applephile/command_line_interface.rb
121
+ - lib/applephile/craigslist.rb
122
+ - lib/applephile/item.rb
119
123
  - lib/applephile/version.rb
120
- - lib/city.rb
121
- - lib/command_line_interface.rb
122
- - lib/craigslist.rb
123
- - lib/item.rb
124
124
  - touch
125
125
  homepage: https://github.com/rachavez1974/applephile
126
126
  licenses:
@@ -1,22 +0,0 @@
1
- class City
2
- attr_accessor :name, :state, :city_url
3
- attr_reader :items
4
-
5
- @@all = []
6
-
7
- def initialize(city_attributes)
8
- city_attributes.each {|key, value| self.send(("#{key}="), value)}
9
- @items = []
10
- @@all << self
11
- end
12
-
13
- def add_item(item)
14
- item.city = self
15
- @items << item
16
- item
17
- end
18
-
19
- def get_apple_prods_by_price(set_price)
20
- @items.select { |item| item.price.to_i >= set_price.to_i }
21
- end
22
- end
@@ -1,89 +0,0 @@
1
- class CLI
2
- INTRO_MESSAGE = "WELCOME TO CRAIGSLIST SCRAPPER!"
3
-
4
- def run
5
- @scrape = CraigsList.new
6
- puts INTRO_MESSAGE
7
- choice = ""
8
- while choice != "exit"
9
- choice = display_main_menu
10
- if choice == "scrape"
11
- get_menu_input
12
- create_items_from_array(scrape_apple_prodcuts)
13
- grab_apple_prodcuts
14
- end
15
- end
16
- end
17
-
18
-
19
- def display_main_menu
20
- stars = "************************".colorize(:yellow)
21
- puts "#{stars} MAIN MENU #{stars}"
22
- puts "Enter \"scrape\" to scrape.".colorize(:blue)
23
- puts "Enter \"exit\" to end program.".colorize(:yellow)
24
- puts "What would you like to do?".colorize(:blue)
25
- gets.chomp
26
- end
27
-
28
- def get_menu_input
29
- display_states
30
- puts "Please enter a number for the state you'd like to scrape.".colorize(:green)
31
- #convert number input from user
32
- @state_scraped = convert_to_state(gets.chomp)
33
- display_cities(@state_scraped)
34
- puts "Please enter a number for the city you'd like to scrape.".colorize(:green)
35
- @city_scraped = convert_to_city(@state_scraped, gets.chomp)
36
- puts "You have chosen the state of #{@state_scraped}, and the city of #{@city_scraped.capitalize}."
37
- end
38
-
39
- def display_states
40
- @scrape.get_states_names.each_with_index do |state, index|
41
- print "#{index + 1}. #{state} ".ljust(28)
42
- if (index + 1) % 5 == 0
43
- print "\n"
44
- end
45
- end
46
- print "\n"
47
- end
48
-
49
- def display_cities(state)
50
- @state_cities = @scrape.get_state_cities(state)
51
- #find max length of city and use it left justify everything else for screen output
52
- max_length = @state_cities.map(&:length).max
53
- @state_cities.each_with_index do |city, index|
54
- print "#{index + 1}. #{city.capitalize.ljust(max_length)} "
55
- if (index + 1) % 3 == 0
56
- print "\n"
57
- end
58
- end
59
- print "\n"
60
- end
61
-
62
- def convert_to_state(state_number)
63
- #it takes in a number and returns the corresponding state's name
64
- @scrape.get_states_names[state_number.to_i - 1]
65
- end
66
-
67
- def convert_to_city(state, city_number)
68
- #it takes in a number and returns the corresponding city's name
69
- @state_cities[city_number.to_i - 1]
70
- end
71
-
72
- def scrape_apple_prodcuts
73
- @scraped_city_url = @scrape.return_city_link(@state_scraped, @city_scraped)
74
- @phones = @scrape.scrape_by_city_url(@scraped_city_url)
75
- end
76
-
77
- def grab_apple_prodcuts
78
- puts "Price enter a price higher than 150 to see the list of phones, defualt price is 150.".colorize(:blue)
79
- display_apple_products_info(@city.get_apple_prods_by_price(gets.chomp))
80
- end
81
-
82
- def get_choice
83
- puts "Enter number to see link phone on browser.".colorize(:cyan)
84
- puts "next for more phones".colorize(:green)
85
- puts "Or enter exit to re-scrape.".colorize(:blue)
86
- gets.chomp
87
- end
88
-
89
- end
@@ -1,106 +0,0 @@
1
- require 'nokogiri'
2
- require 'open-uri'
3
- require 'pry'
4
-
5
- class CraigsList
6
- attr_accessor :site_url, :doc
7
-
8
- def initialize()
9
- @site_url = "https://www.craigslist.org/about/sites"
10
- @doc = Nokogiri::HTML(open(@site_url))
11
- end
12
-
13
- def get_states_names
14
- #it returns an array of states of the U.S., CLI will use to display them
15
- doc.css(".colmask").first.css("h4").collect { |st| st.text}
16
- end
17
-
18
- def get_state_cities(state_name)
19
- #it returns an array of cities belonging to a particular state
20
- #1. find the state first.
21
- #2. then collect the state's city array, return a flatten array so only cities can be used
22
- #to be displayed in CLI
23
- state_cities_array = []
24
- states_cities_links.each do |states, cities_links|
25
- if states.to_s == state_name
26
- #collect only cities
27
- state_cities_array = cities_links.collect { |city| city.keys }
28
- break
29
- end
30
- end
31
- state_cities_array.flatten!
32
-
33
- end
34
-
35
- def return_city_link(state, city)
36
- #it returns the link of a particular city
37
- #1. find state hash
38
- #2. find the city
39
- #3. get city's link
40
- city_url = ""
41
- states_cities_links.find do |key, value|
42
- if key.to_s == state
43
- value.find do |city_hash|
44
- if city_hash.has_key?(city)
45
- city_url = city_hash[city]
46
- end
47
- end
48
- end
49
- end
50
- city_url
51
- end
52
- def scrape_by_city_url(city_url)
53
- items_array_of_hashes = []
54
- #1. returns an array of hashes for every link (phone found) for a particular scrape criteria
55
- #2. build site link with searching criteria phones with pic, new, os
56
- #3. grab all phones that meet this search criteria.
57
- #4. traverse the collection, and grab each needed attribute one by one.
58
- #5. build hash, and save it to array.
59
- #6. return hash
60
- city_url = city_url + "search/moa?hasPic=1&condition=10&mobile_os=2"
61
- city_doc = Nokogiri::HTML(open(city_url))
62
- grab_all_phones = city_doc.css(".result-info")
63
- grab_all_phones.each do |phones|
64
- phone_url = phones.css("a")[0]["href"]
65
- phone_price = phones.css(".result-price").text.split("$")[1]
66
- phone_description = phones.css("a").text.split("\n")[0]
67
- items_array_of_hashes.push({:url => phone_url,
68
- :price => phone_price,
69
- :description => phone_description})
70
- end
71
- items_array_of_hashes
72
- end
73
-
74
-
75
- private
76
-
77
- def cities_and_links
78
- #it returns a two dimensional array of cities, with their links as a hash by the state
79
- # [[{"citya" => linka}, {"cityb" => linkb}, {"cityc" => linkc}], [{"cityz" => linkz}]]
80
-
81
- two_dimension_city = []
82
- doc.css(".colmask").first.css("ul").each do |city|
83
- #collect returns [{"city1" => link1}, {city2 => link2}]
84
- #collect removes "/" and unnecessary spaces from cities
85
- two_dimension_city.push(city.css("li a").collect { |city| { city.text.split("/")[0].strip => city["href"] }})
86
- end
87
- two_dimension_city
88
- end
89
-
90
- def states_cities_links
91
- #returns a array of hashes with keys equal to states, and values
92
- #equal to an array of cities and their respective links
93
- #{ :state1 => [{"city1" => link1}, {city2 => link2}, {city3 => link3}],
94
- # :state2 => [{}]}
95
-
96
- states_cities_links_hash = {}
97
- #proceed by states, make hash, then push into array
98
- #cities index implicitly starts from the first state
99
- get_states_names.each_with_index do |state, index|
100
- states_cities_links_hash[state.to_sym] = cities_and_links[index]
101
- end
102
- states_cities_links_hash
103
- end
104
-
105
-
106
- end
@@ -1,8 +0,0 @@
1
- class Item
2
- attr_accessor :city, :price, :description, :url
3
-
4
- def initialize(item_attributes)
5
- item_attributes.each {|key, value| self.send(("#{key}="), value)}
6
- end
7
-
8
- end