extraspace 0.1.0 → 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 +4 -4
- data/README.md +20 -16
- data/lib/extraspace/address.rb +3 -3
- data/lib/extraspace/availability.rb +2 -2
- data/lib/extraspace/crawler.rb +52 -0
- data/lib/extraspace/dimensions.rb +5 -2
- data/lib/extraspace/facility.rb +10 -4
- data/lib/extraspace/link.rb +26 -0
- data/lib/extraspace/price.rb +1 -1
- data/lib/extraspace/rates.rb +4 -2
- data/lib/extraspace/sitemap.rb +41 -0
- data/lib/extraspace/version.rb +1 -1
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2d656b5fbca3894562492b6a8c3e90c97a4c785cf88d6ff7c2c65c380a5ba8e
|
4
|
+
data.tar.gz: c564ac28246067bfb3d843070aa8ea3dcaa0898e12161e15c7570439cd8d4907
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 503b60e74410c4fe5cf0db8644382555cf0ddb8343790e5eed69d61c7b8d5e494be3cdbd55097fee3454f555f2bd030722b704906384da65d020e688252ad46a
|
7
|
+
data.tar.gz: d48d92e05c00b065619738803344b79254ecb29cec4e9d461a47709169c1125864d278f07ce421647b17d2e6f83efdb09c9a102fe393766edab8d5aa457639db
|
data/README.md
CHANGED
@@ -17,22 +17,26 @@ gem install extrapsace
|
|
17
17
|
```ruby
|
18
18
|
require 'extraspace'
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
puts "
|
27
|
-
puts "
|
28
|
-
puts "
|
29
|
-
puts "
|
30
|
-
puts
|
31
|
-
|
32
|
-
facility.
|
33
|
-
puts "UID: #{price.uid}"
|
34
|
-
puts "Dimensions: #{price.dimensions.display}"
|
35
|
-
puts "Rates: $#{price.rates.street} (street) / $#{price.rates.web} (web)"
|
20
|
+
sitemap = ExtraSpace::Facility.sitemap
|
21
|
+
sitemap.links.each do |link|
|
22
|
+
url = link.loc
|
23
|
+
|
24
|
+
facility = ExtraSpace::Facility.fetch(url:)
|
25
|
+
|
26
|
+
puts "Line 1: #{facility.address.line1}"
|
27
|
+
puts "Line 2: #{facility.address.line2}"
|
28
|
+
puts "City: #{facility.address.city}"
|
29
|
+
puts "State: #{facility.address.state}"
|
30
|
+
puts "ZIP: #{facility.address.zip}"
|
31
|
+
puts "Latitude: #{facility.geocode.latitude}"
|
32
|
+
puts "Longitude: #{facility.geocode.longitude}"
|
36
33
|
puts
|
34
|
+
|
35
|
+
facility.prices.each do |price|
|
36
|
+
puts "UID: #{price.uid}"
|
37
|
+
puts "Dimensions: #{price.dimensions.display}"
|
38
|
+
puts "Rates: $#{price.rates.street} (street) / $#{price.rates.web} (web)"
|
39
|
+
puts
|
40
|
+
end
|
37
41
|
end
|
38
42
|
```
|
data/lib/extraspace/address.rb
CHANGED
@@ -26,9 +26,8 @@ module ExtraSpace
|
|
26
26
|
# @param line1 [String]
|
27
27
|
# @param line2 [String]
|
28
28
|
# @param city [String]
|
29
|
-
# @param
|
30
|
-
# @param
|
31
|
-
# @param postal_code [String]
|
29
|
+
# @param state [String]
|
30
|
+
# @param zip [String]
|
32
31
|
def initialize(line1:, line2:, city:, state:, zip:)
|
33
32
|
@line1 = line1
|
34
33
|
@line2 = line2
|
@@ -37,6 +36,7 @@ module ExtraSpace
|
|
37
36
|
@zip = zip
|
38
37
|
end
|
39
38
|
|
39
|
+
# @return [String]
|
40
40
|
def inspect
|
41
41
|
props = [
|
42
42
|
"line1=#{@line1.inspect}",
|
@@ -7,7 +7,7 @@ module ExtraSpace
|
|
7
7
|
# @return [String]
|
8
8
|
attr_accessor :available
|
9
9
|
|
10
|
-
# @param
|
10
|
+
# @param available [String]
|
11
11
|
def initialize(available:)
|
12
12
|
@available = available
|
13
13
|
end
|
@@ -22,7 +22,7 @@ module ExtraSpace
|
|
22
22
|
|
23
23
|
# @param data [Hash]
|
24
24
|
#
|
25
|
-
# @return [
|
25
|
+
# @return [Availability]
|
26
26
|
def self.parse(data:)
|
27
27
|
new(available: data['available'])
|
28
28
|
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExtraSpace
|
4
|
+
# Used to fetch and parse either HTML or XML via a URL.
|
5
|
+
class Crawler
|
6
|
+
# Raised for unexpected HTTP responses.
|
7
|
+
class FetchError < StandardError
|
8
|
+
# @param url [String]
|
9
|
+
# @param response [HTTP::Response]
|
10
|
+
def initialize(url:, response:)
|
11
|
+
super("url=#{url} status=#{response.status.inspect} body=#{response.body.inspect}")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param url [String]
|
16
|
+
# @raise [FetchError]
|
17
|
+
# @return [Nokogiri::HTML::Document]
|
18
|
+
def self.html(url:)
|
19
|
+
new.html(url:)
|
20
|
+
end
|
21
|
+
|
22
|
+
# @param url [String]
|
23
|
+
# @raise [FetchError]
|
24
|
+
# @return [Nokogiri::XML::Document]
|
25
|
+
def self.xml(url:)
|
26
|
+
new.xml(url:)
|
27
|
+
end
|
28
|
+
|
29
|
+
# @param url [String]
|
30
|
+
# @return [HTTP::Response]
|
31
|
+
def fetch(url:)
|
32
|
+
response = HTTP.get(url)
|
33
|
+
raise FetchError(url:, response: response.flush) unless response.status.ok?
|
34
|
+
|
35
|
+
response
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param url [String]
|
39
|
+
# @raise [FetchError]
|
40
|
+
# @return [Nokogiri::XML::Document]
|
41
|
+
def html(url:)
|
42
|
+
Nokogiri::HTML(String(fetch(url:).body))
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param url [String]
|
46
|
+
# @raise [FetchError]
|
47
|
+
# @return [Nokogiri::XML::Document]
|
48
|
+
def xml(url:)
|
49
|
+
Nokogiri::XML(String(fetch(url:).body))
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -19,7 +19,10 @@ module ExtraSpace
|
|
19
19
|
# @return [String]
|
20
20
|
attr_accessor :display
|
21
21
|
|
22
|
-
# @param
|
22
|
+
# @param depth [Integer]
|
23
|
+
# @param width [Integer]
|
24
|
+
# @param sqft [Integer]
|
25
|
+
# @param display [String]
|
23
26
|
def initialize(depth:, width:, sqft:, display:)
|
24
27
|
@depth = depth
|
25
28
|
@width = width
|
@@ -40,7 +43,7 @@ module ExtraSpace
|
|
40
43
|
|
41
44
|
# @param data [Hash]
|
42
45
|
#
|
43
|
-
# @return [
|
46
|
+
# @return [Dimensions]
|
44
47
|
def self.parse(data:)
|
45
48
|
new(depth: data['depth'], width: data['width'], sqft: data['squareFoot'], display: data['display'])
|
46
49
|
end
|
data/lib/extraspace/facility.rb
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
module ExtraSpace
|
4
4
|
# e.g. https://www.extraspace.com/storage/facilities/us/alabama/auburn/3264/
|
5
5
|
class Facility
|
6
|
+
SITEMAP_URL = 'https://www.extraspace.com/facility-sitemap.xml'
|
7
|
+
|
6
8
|
# @attribute [rw] address
|
7
9
|
# @return [Address]
|
8
10
|
attr_accessor :address
|
@@ -24,6 +26,7 @@ module ExtraSpace
|
|
24
26
|
@prices = prices
|
25
27
|
end
|
26
28
|
|
29
|
+
# @return [String]
|
27
30
|
def inspect
|
28
31
|
props = [
|
29
32
|
"address=#{@address.inspect}",
|
@@ -33,15 +36,18 @@ module ExtraSpace
|
|
33
36
|
"#<#{self.class.name} #{props.join(' ')}>"
|
34
37
|
end
|
35
38
|
|
39
|
+
# @return [Sitemap]
|
40
|
+
def self.sitemap
|
41
|
+
Sitemap.fetch(url: SITEMAP_URL)
|
42
|
+
end
|
43
|
+
|
36
44
|
# @param url [String]
|
37
45
|
#
|
38
46
|
# @return [Facility]
|
39
47
|
def self.fetch(url:)
|
40
|
-
|
41
|
-
document = Nokogiri::HTML(String(response.body))
|
48
|
+
document = Crawler.html(url:)
|
42
49
|
data = JSON.parse(document.at('#__NEXT_DATA__').text)
|
43
|
-
|
44
|
-
parse(data: data)
|
50
|
+
parse(data:)
|
45
51
|
end
|
46
52
|
|
47
53
|
# @param data [Hash]
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExtraSpace
|
4
|
+
# A link in a sitemap.
|
5
|
+
class Link
|
6
|
+
# @attribute [rw] loc
|
7
|
+
# @return [String]
|
8
|
+
attr_accessor :loc
|
9
|
+
|
10
|
+
# @attribute [rw] lastmod
|
11
|
+
# @return [Time]
|
12
|
+
attr_accessor :lastmod
|
13
|
+
|
14
|
+
# @param loc [String]
|
15
|
+
# @param lastmod [String]
|
16
|
+
def initialize(loc:, lastmod:)
|
17
|
+
@loc = loc
|
18
|
+
@lastmod = Time.parse(lastmod)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String]
|
22
|
+
def inspect
|
23
|
+
"#<#{self.class.name} loc=#{@loc.inspect} lastmod=#{@lastmod.inspect}>"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/extraspace/price.rb
CHANGED
data/lib/extraspace/rates.rb
CHANGED
@@ -15,7 +15,9 @@ module ExtraSpace
|
|
15
15
|
# @return [Integer]
|
16
16
|
attr_accessor :web
|
17
17
|
|
18
|
-
# @param
|
18
|
+
# @param nsc [Integer]
|
19
|
+
# @param street [Integer]
|
20
|
+
# @param web [Integer]
|
19
21
|
def initialize(nsc:, street:, web:)
|
20
22
|
@nsc = nsc
|
21
23
|
@street = street
|
@@ -34,7 +36,7 @@ module ExtraSpace
|
|
34
36
|
|
35
37
|
# @param data [Hash]
|
36
38
|
#
|
37
|
-
# @return [
|
39
|
+
# @return [Rates]
|
38
40
|
def self.parse(data:)
|
39
41
|
new(
|
40
42
|
nsc: data['nsc'],
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ExtraSpace
|
4
|
+
# e.g. https://www.extraspace.com/facility-sitemap.xml
|
5
|
+
class Sitemap
|
6
|
+
# @attribute [rw] links
|
7
|
+
# @return [Array<Link>]
|
8
|
+
attr_accessor :links
|
9
|
+
|
10
|
+
# @param document [NokoGiri::XML::Document]
|
11
|
+
#
|
12
|
+
# @return [Sitemap]
|
13
|
+
def self.parse(document:)
|
14
|
+
links = document.xpath('//xmlns:url').map do |url|
|
15
|
+
loc = url.at_xpath('xmlns:loc')&.text
|
16
|
+
lastmod = url.at_xpath('xmlns:lastmod')&.text
|
17
|
+
Link.new(loc:, lastmod:)
|
18
|
+
end
|
19
|
+
|
20
|
+
new(links: links)
|
21
|
+
end
|
22
|
+
|
23
|
+
# @param url [String]
|
24
|
+
#
|
25
|
+
# @return [Sitemap]
|
26
|
+
def self.fetch(url:)
|
27
|
+
document = Crawler.xml(url:)
|
28
|
+
parse(document:)
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param links [Array<Link>]
|
32
|
+
def initialize(links:)
|
33
|
+
@links = links
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [String]
|
37
|
+
def inspect
|
38
|
+
"#<#{self.class.name} links=#{@links.inspect}>"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/extraspace/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extraspace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kevin Sylvestre
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-11-
|
11
|
+
date: 2024-11-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: http
|
@@ -80,11 +80,14 @@ files:
|
|
80
80
|
- lib/extraspace.rb
|
81
81
|
- lib/extraspace/address.rb
|
82
82
|
- lib/extraspace/availability.rb
|
83
|
+
- lib/extraspace/crawler.rb
|
83
84
|
- lib/extraspace/dimensions.rb
|
84
85
|
- lib/extraspace/facility.rb
|
85
86
|
- lib/extraspace/geocode.rb
|
87
|
+
- lib/extraspace/link.rb
|
86
88
|
- lib/extraspace/price.rb
|
87
89
|
- lib/extraspace/rates.rb
|
90
|
+
- lib/extraspace/sitemap.rb
|
88
91
|
- lib/extraspace/version.rb
|
89
92
|
homepage: https://github.com/ksylvest/extraspace
|
90
93
|
licenses:
|
@@ -94,7 +97,7 @@ metadata:
|
|
94
97
|
homepage_uri: https://github.com/ksylvest/extraspace
|
95
98
|
source_code_uri: https://github.com/ksylvest/extraspace
|
96
99
|
changelog_uri: https://github.com/ksylvest/extraspace
|
97
|
-
post_install_message:
|
100
|
+
post_install_message:
|
98
101
|
rdoc_options: []
|
99
102
|
require_paths:
|
100
103
|
- lib
|
@@ -109,8 +112,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
112
|
- !ruby/object:Gem::Version
|
110
113
|
version: '0'
|
111
114
|
requirements: []
|
112
|
-
rubygems_version: 3.5.
|
113
|
-
signing_key:
|
115
|
+
rubygems_version: 3.5.23
|
116
|
+
signing_key:
|
114
117
|
specification_version: 4
|
115
118
|
summary: A crawler for ExtraSpace.
|
116
119
|
test_files: []
|