applephile 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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