ten_largest_cities 1.0.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 +7 -0
- data/bin/run.rb +4 -0
- data/config/environment.rb +10 -0
- data/lib/city.rb +32 -0
- data/lib/city_scraper.rb +53 -0
- data/lib/cli.rb +74 -0
- data/lib/country.rb +50 -0
- data/lib/country_scraper.rb +49 -0
- metadata +50 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: '04258b023e2281becc21eda5021ec2fdb3d630583305662453c2c3d6023cbd88'
|
|
4
|
+
data.tar.gz: 595b730a99055b1107d5511de2dfe2fc106633245ab315771c1aa1a5f879b405
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 0f87f5c63478f8d2d601af96bbc2569eb10edc100d012a30ac6f11021849cf8d1c0a64394bf8a7d969c9c92df361854a2282218d3235c2fb340d693b46016e74
|
|
7
|
+
data.tar.gz: 829fcd994c0eebc794ca36a660a815fe018076eefe0ea8682a4cb61e312ce17452013702f4d88b727256ef7f4eac39e2e2efc0da33d23831a5355a8748f11553
|
data/bin/run.rb
ADDED
data/lib/city.rb
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
class City
|
|
3
|
+
attr_accessor :city_name, :population, :location, :country
|
|
4
|
+
|
|
5
|
+
@@all = []
|
|
6
|
+
|
|
7
|
+
#This uses the scraped information to make new cities
|
|
8
|
+
def initialize(city_name, population, location, country)
|
|
9
|
+
@city_name = city_name
|
|
10
|
+
@population = population
|
|
11
|
+
@location = location
|
|
12
|
+
@country = country
|
|
13
|
+
@@all << self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#This displays all of the city objects
|
|
17
|
+
def self.all
|
|
18
|
+
@@all
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#this allows the user to see the desired city data displayed
|
|
22
|
+
def self.info
|
|
23
|
+
i = 0
|
|
24
|
+
self.all.collect do |city|
|
|
25
|
+
puts "#{i+=1}. #{city.city_name}".light_blue
|
|
26
|
+
puts "Population: #{city.population}"
|
|
27
|
+
puts "Coordinates: #{city.location}"
|
|
28
|
+
end
|
|
29
|
+
puts "\n"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
data/lib/city_scraper.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
|
|
2
|
+
class CityScraper
|
|
3
|
+
attr_accessor :country, :city_table
|
|
4
|
+
|
|
5
|
+
#initialize runs the scraper through the required methods of opening, collecting, creating cities
|
|
6
|
+
def initialize(country)
|
|
7
|
+
@country = country
|
|
8
|
+
@city_table = open_page
|
|
9
|
+
chunked = collect_cities
|
|
10
|
+
create_cities(chunked)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
#opens the webpage to initiate the scraping process
|
|
14
|
+
def open_page
|
|
15
|
+
html = open(self.country.largest_cities_link)
|
|
16
|
+
data = Nokogiri::HTML(html).css('table.restable.sortable').css('td')
|
|
17
|
+
city_table = data.css('td').collect {|l| l}
|
|
18
|
+
city_table
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
#uses the collected data to iterate through and print out the pertinent text
|
|
22
|
+
def collect_cities
|
|
23
|
+
result = []
|
|
24
|
+
chunked = []
|
|
25
|
+
city_table.each_with_index do |v, i|
|
|
26
|
+
if (i > 0 && v.children.text.length > 2 && v.children.first.text != v.children.last.text)
|
|
27
|
+
data = v.children.first.text.concat(v.children.last.text)
|
|
28
|
+
result << data
|
|
29
|
+
elsif (i > 0 && v.children.text.length > 2 && v.children.first.text == v.children.last.text)
|
|
30
|
+
data = v.children.text
|
|
31
|
+
result << data
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
result
|
|
35
|
+
|
|
36
|
+
#collects 3 data points and associates them together
|
|
37
|
+
while result.length > 2
|
|
38
|
+
chunked << result.slice!(0,3)
|
|
39
|
+
end
|
|
40
|
+
chunked
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#creates new city objects based off of these collected datapoints
|
|
44
|
+
def create_cities(chunked)
|
|
45
|
+
chunked.collect do |city|
|
|
46
|
+
city_name = city[0]
|
|
47
|
+
population = city[1]
|
|
48
|
+
location = city[2]
|
|
49
|
+
country = self.country.name
|
|
50
|
+
new = City.new(city_name, population, location, country)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
data/lib/cli.rb
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
class Cli
|
|
2
|
+
attr_accessor :country
|
|
3
|
+
|
|
4
|
+
#welcome message and first menu option - search or exit. posts country list if selected.
|
|
5
|
+
def start
|
|
6
|
+
puts "\nIt's time to learn about countries and their largest cities!".blue
|
|
7
|
+
puts "Browse the menu by typing the first letter of a country's name - or type 'exit'.".blue
|
|
8
|
+
letter = gets.strip.upcase
|
|
9
|
+
if letter == "EXIT"
|
|
10
|
+
finished
|
|
11
|
+
elsif (letter != "EXIT" && ("A".."Z").to_a.include?(letter))
|
|
12
|
+
Scraper.new
|
|
13
|
+
list = Country.search_all_names(letter)
|
|
14
|
+
puts list
|
|
15
|
+
puts "\n"
|
|
16
|
+
country_info
|
|
17
|
+
else
|
|
18
|
+
start
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
#second menu option - choose a country? posts country information if selected
|
|
23
|
+
def country_info
|
|
24
|
+
puts "\nPlease type the name of the desired country.".blue
|
|
25
|
+
name = gets.strip.downcase
|
|
26
|
+
if Country.find_by_name(name) != nil
|
|
27
|
+
self.country = Country.find_by_name(name)
|
|
28
|
+
puts "\nGreat! Let's take a look.\n".blue
|
|
29
|
+
list = self.country.info
|
|
30
|
+
puts list
|
|
31
|
+
city_info
|
|
32
|
+
else
|
|
33
|
+
country_info
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#third menu option - continue to city data, or quit? posts city data if selected
|
|
38
|
+
def city_info
|
|
39
|
+
puts "\nDo you want to learn more about #{self.country.name}'s largest cities? (Y/N)".blue
|
|
40
|
+
continue = gets.strip.upcase
|
|
41
|
+
if continue == "Y"
|
|
42
|
+
CityScraper.new(self.country)
|
|
43
|
+
puts "\n"
|
|
44
|
+
list = City.info
|
|
45
|
+
puts list
|
|
46
|
+
puts "Additional City Information:"
|
|
47
|
+
puts "#{self.country.largest_cities_link}"
|
|
48
|
+
finished
|
|
49
|
+
elsif continue == "N"
|
|
50
|
+
finished
|
|
51
|
+
else
|
|
52
|
+
city_info
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
#finishes program
|
|
57
|
+
def finished
|
|
58
|
+
puts "\n"
|
|
59
|
+
puts "Do you want to learn about a new country? (Y/N)"
|
|
60
|
+
continue = gets.strip.upcase
|
|
61
|
+
if continue == "Y"
|
|
62
|
+
Country.all.clear
|
|
63
|
+
City.all.clear
|
|
64
|
+
Cli.new.start
|
|
65
|
+
elsif continue == "N"
|
|
66
|
+
puts "That's all I got! Please check out the links provided for additional info.".blue
|
|
67
|
+
puts "\n"
|
|
68
|
+
else
|
|
69
|
+
finished
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
end
|
data/lib/country.rb
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
|
|
2
|
+
class Country
|
|
3
|
+
attr_accessor :country_link, :name, :abbreviation, :largest_cities_link
|
|
4
|
+
@@all = []
|
|
5
|
+
|
|
6
|
+
#This uses the scraped information to make new countries
|
|
7
|
+
def initialize(name, abbreviation, country_link)
|
|
8
|
+
@name = name
|
|
9
|
+
@abbreviation = abbreviation
|
|
10
|
+
@country_link = country_link
|
|
11
|
+
l_name = name.downcase.gsub(" ", "-")
|
|
12
|
+
@largest_cities_link = "https://www.geonames.org/#{self.abbreviation}/largest-cities-in-#{l_name}.html"
|
|
13
|
+
@@all << self
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#This displays all of the country objects
|
|
17
|
+
def self.all
|
|
18
|
+
@@all.sort! {|a,b| a.name <=> b.name}
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.search_all_names(input)
|
|
22
|
+
input = input.to_s
|
|
23
|
+
result = []
|
|
24
|
+
self.all.each do |v|
|
|
25
|
+
if input == v.name[0]
|
|
26
|
+
result << "#{v.name}"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
result
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
#this allows you to look up a country object by country name
|
|
33
|
+
def self.find_by_name(input)
|
|
34
|
+
self.all.detect { |x| x.name.downcase == input }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
#looking up cities via using country object to initiate the city scraper
|
|
38
|
+
def self.lookup_cities(name)
|
|
39
|
+
country = self.find_by_name(name)
|
|
40
|
+
country = CityScraper.new(country)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
#this allows the user to see the data displayed
|
|
44
|
+
def info
|
|
45
|
+
puts "Country Name: #{self.name}".light_blue
|
|
46
|
+
puts "Country Abbreviation: #{self.abbreviation}"
|
|
47
|
+
puts "Country Info link: #{self.country_link}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
class Scraper
|
|
2
|
+
#Scraper.new pulls methods together: open the page, scrape, and instantiate new countries
|
|
3
|
+
def initialize
|
|
4
|
+
country_table = open_page
|
|
5
|
+
country_table = collect_countries(country_table)
|
|
6
|
+
create_countries(country_table)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
#this opens our website url and stores it as a zoomed-in array
|
|
10
|
+
def open_page
|
|
11
|
+
html = open("https://www.geonames.org/countries/")
|
|
12
|
+
country_table = Nokogiri::HTML(html).css('#countries')
|
|
13
|
+
country_table = country_table.css('td').css('a').collect {|l| l}
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#this iterates over the country table data to chunk together data
|
|
17
|
+
def collect_countries(country_table)
|
|
18
|
+
result = []
|
|
19
|
+
chunked = []
|
|
20
|
+
|
|
21
|
+
country_table.each_with_index do |v, i|
|
|
22
|
+
if i.even?
|
|
23
|
+
country_abbreviation = v.attributes['name'].value
|
|
24
|
+
result << country_abbreviation
|
|
25
|
+
else
|
|
26
|
+
country_name = v.children.text
|
|
27
|
+
country_link = v.attributes['href'].value
|
|
28
|
+
result << country_name
|
|
29
|
+
result << "https://www.geonames.org#{country_link}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
#taking each set of three data points and associating them together
|
|
33
|
+
while result.length > 3
|
|
34
|
+
chunked << result.slice!(0,3)
|
|
35
|
+
end
|
|
36
|
+
chunked
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#this creates new countries based on the data chunks
|
|
40
|
+
def create_countries(country_table)
|
|
41
|
+
country_table.each do |country|
|
|
42
|
+
abbreviation = country[0]
|
|
43
|
+
name = country[1]
|
|
44
|
+
info_link = country[2]
|
|
45
|
+
name = Country.new(name, abbreviation, info_link)
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ten_largest_cities
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 1.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Mackenzie Moore
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2019-03-25 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description:
|
|
14
|
+
email:
|
|
15
|
+
executables:
|
|
16
|
+
- run.rb
|
|
17
|
+
extensions: []
|
|
18
|
+
extra_rdoc_files: []
|
|
19
|
+
files:
|
|
20
|
+
- bin/run.rb
|
|
21
|
+
- config/environment.rb
|
|
22
|
+
- lib/city.rb
|
|
23
|
+
- lib/city_scraper.rb
|
|
24
|
+
- lib/cli.rb
|
|
25
|
+
- lib/country.rb
|
|
26
|
+
- lib/country_scraper.rb
|
|
27
|
+
homepage: https://github.com/mackenzie-km/ten_largest_cities
|
|
28
|
+
licenses:
|
|
29
|
+
- MIT
|
|
30
|
+
metadata: {}
|
|
31
|
+
post_install_message:
|
|
32
|
+
rdoc_options: []
|
|
33
|
+
require_paths:
|
|
34
|
+
- bin
|
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0'
|
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - ">="
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: '0'
|
|
45
|
+
requirements: []
|
|
46
|
+
rubygems_version: 3.0.3
|
|
47
|
+
signing_key:
|
|
48
|
+
specification_version: 4
|
|
49
|
+
summary: learn about countries and their largest cities
|
|
50
|
+
test_files: []
|