buoy_data 1.0.0.beta.0 → 1.0.0.beta.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.
- data/VERSION +1 -1
- data/buoy_data.gemspec +3 -2
- data/lib/buoy_data/buoy_list.rb +8 -27
- data/lib/buoy_data/noaa_buoy_list.rb +2 -27
- data/lib/buoy_data/noaa_station.rb +105 -0
- data/lib/buoy_data.rb +1 -0
- data/spec/noaa_buoy_list_spec.rb +14 -3
- metadata +4 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.0.0.beta.
|
1
|
+
1.0.0.beta.1
|
data/buoy_data.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{buoy_data}
|
8
|
-
s.version = "1.0.0.beta.
|
8
|
+
s.version = "1.0.0.beta.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Adam Weller"]
|
12
|
-
s.date = %q{2011-
|
12
|
+
s.date = %q{2011-04-17}
|
13
13
|
s.description = %q{The goal of this gem is to provide marine buoy data from a variety of sources}
|
14
14
|
s.email = %q{minch@trazzler.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
"lib/buoy_data/noaa_buoy_list.rb",
|
32
32
|
"lib/buoy_data/noaa_buoy_observation.rb",
|
33
33
|
"lib/buoy_data/noaa_buoy_reading.rb",
|
34
|
+
"lib/buoy_data/noaa_station.rb",
|
34
35
|
"spec/noaa_buoy_forecast_spec.rb",
|
35
36
|
"spec/noaa_buoy_list_spec.rb",
|
36
37
|
"spec/noaa_buoy_observation_spec.rb",
|
data/lib/buoy_data/buoy_list.rb
CHANGED
@@ -6,17 +6,21 @@ module BuoyData
|
|
6
6
|
def get
|
7
7
|
stats = {
|
8
8
|
:stations => [],
|
9
|
-
:
|
9
|
+
:station_count => 0,
|
10
|
+
:errors => [],
|
11
|
+
:error_count => 0
|
10
12
|
}
|
11
13
|
@doc = doc
|
12
14
|
@station_list = stations doc
|
13
15
|
|
14
|
-
@station_list.each do |
|
16
|
+
@station_list.each do |station_url|
|
15
17
|
begin
|
16
|
-
h = scrape_station
|
18
|
+
h = scrape_station(station_url)
|
17
19
|
stats[:stations].push h
|
20
|
+
stats[:station_count] += 1
|
18
21
|
rescue => e
|
19
|
-
stats[:
|
22
|
+
stats[:error_count] += 1
|
23
|
+
stats[:errors].push({ :url => s, :error => e.backtrace })
|
20
24
|
end
|
21
25
|
end
|
22
26
|
|
@@ -39,28 +43,5 @@ module BuoyData
|
|
39
43
|
|
40
44
|
def scrape_station(url)
|
41
45
|
end
|
42
|
-
|
43
|
-
def lat_lng_from(text)
|
44
|
-
text = text.sub(/ \(.*$/, '')
|
45
|
-
matches = /([0-9\.]+ ?[NESW]) ([0-9\.]+ ?[NESW])/.match(text)
|
46
|
-
|
47
|
-
matches && matches.size == 3 ? [ $1, $2 ] : []
|
48
|
-
end
|
49
|
-
|
50
|
-
def normal_lat(lat)
|
51
|
-
lat, dir = lat.split(/ /)
|
52
|
-
lat = lat.to_f
|
53
|
-
lat = -lat if dir == 'S'
|
54
|
-
|
55
|
-
lat
|
56
|
-
end
|
57
|
-
|
58
|
-
def normal_lng(lng)
|
59
|
-
lng, dir = lng.split(/ /)
|
60
|
-
lng = lng.to_f
|
61
|
-
lng = -lng if dir == 'W'
|
62
|
-
|
63
|
-
lng
|
64
|
-
end
|
65
46
|
end
|
66
47
|
end
|
@@ -17,33 +17,8 @@ module BuoyData
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def scrape_station(url)
|
20
|
-
url = [base_url, url].join('/')
|
21
|
-
|
22
|
-
h = {}
|
23
|
-
xpath = "//h1"
|
24
|
-
|
25
|
-
# Title, Station Id and Description
|
26
|
-
title = doc.xpath(xpath).text
|
27
|
-
h[:url] = url
|
28
|
-
h[:title] = title
|
29
|
-
station_id, description = title.split(/ - /)
|
30
|
-
station_id = station_id.sub(/station ?/i, '')
|
31
|
-
h[:station_id] = station_id
|
32
|
-
h[:description] = description
|
33
|
-
|
34
|
-
# Lat and Lng
|
35
|
-
xpath += "/following-sibling::table/tr/td/p/b"
|
36
|
-
elements = doc.xpath(xpath)
|
37
|
-
elements = elements.map(&:text)
|
38
|
-
element = elements.find{|e| /\d{2,3}\.\d{2,3}/.match(e)}
|
39
|
-
latlng = lat_lng_from element
|
40
|
-
|
41
|
-
unless latlng.empty?
|
42
|
-
h[:lat] = normal_lat latlng.first
|
43
|
-
h[:lng] = normal_lng latlng.last
|
44
|
-
end
|
45
|
-
|
46
|
-
h
|
20
|
+
url = [ base_url, url ].join('/')
|
21
|
+
NoaaStation.new.scrape(url)
|
47
22
|
end
|
48
23
|
end
|
49
24
|
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module BuoyData
|
2
|
+
require 'open-uri'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
class NoaaStation
|
6
|
+
def scrape(url)
|
7
|
+
h = {}
|
8
|
+
xpath = "//h1"
|
9
|
+
|
10
|
+
doc = Nokogiri::HTML(open(url))
|
11
|
+
|
12
|
+
# Title, Station Id and Description
|
13
|
+
title = doc.xpath(xpath).first.text
|
14
|
+
title = title.rstrip
|
15
|
+
h[:url] = url
|
16
|
+
h[:title] = title
|
17
|
+
station_id, description = title.split(/ - /)
|
18
|
+
station_id = station_id.sub(/station ?/i, '')
|
19
|
+
station_id = /[A-Z0-9]+/.match(station_id).to_s rescue nil
|
20
|
+
h[:station_id] = station_id
|
21
|
+
h[:description] = description
|
22
|
+
|
23
|
+
# Lat and Lng
|
24
|
+
xpath += "/following-sibling::table/tr/td/p/b"
|
25
|
+
elements = doc.xpath(xpath)
|
26
|
+
elements = elements.map(&:text)
|
27
|
+
element = elements.find{|e| /\d{2,3}\.\d{2,3}/.match(e)}
|
28
|
+
latlng = lat_lng_from element
|
29
|
+
|
30
|
+
unless latlng.empty?
|
31
|
+
h[:lat] = normal_lat latlng.first
|
32
|
+
h[:lng] = normal_lng latlng.last
|
33
|
+
end
|
34
|
+
|
35
|
+
# Latest reading
|
36
|
+
xpath = "//table/caption[@class='titleDataHeader'][text()[contains(.,'Conditions')]]"
|
37
|
+
xpath += "/../tr"
|
38
|
+
elements = doc.xpath xpath
|
39
|
+
|
40
|
+
current_reading = {}
|
41
|
+
unless elements.empty?
|
42
|
+
elements.each do |element|
|
43
|
+
reading = scrape_condition_from_element(element)
|
44
|
+
current_reading.merge! reading unless reading.blank?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# If we couldn't get a water temp from this station then it's not of use
|
49
|
+
return {} unless valid_reading? current_reading
|
50
|
+
h.merge! current_reading
|
51
|
+
|
52
|
+
h
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
# No water temp (wtmp) is our filter
|
57
|
+
def valid_reading?(reading)
|
58
|
+
!reading.blank? && reading.keys.include?(:wtmp)
|
59
|
+
end
|
60
|
+
|
61
|
+
def scrape_condition_from_element(element)
|
62
|
+
reading = {}
|
63
|
+
# (include units)
|
64
|
+
#regexp = /\(([A-Z]+)\):\n\t ?(.*)\n$/
|
65
|
+
# (no units)
|
66
|
+
regexp = /\(([A-Z]+)\):\n\t ?([0-9.-]+).*\n$/
|
67
|
+
text = element.text
|
68
|
+
|
69
|
+
if regexp.match(text)
|
70
|
+
key = $1
|
71
|
+
return reading unless key
|
72
|
+
key = key.downcase.to_sym
|
73
|
+
value = $2
|
74
|
+
return reading unless value
|
75
|
+
value = value.lstrip.rstrip.to_f
|
76
|
+
reading = { key => value }
|
77
|
+
end
|
78
|
+
|
79
|
+
reading
|
80
|
+
end
|
81
|
+
|
82
|
+
def lat_lng_from(text)
|
83
|
+
text = text.sub(/ \(.*$/, '')
|
84
|
+
matches = /([0-9\.]+ ?[NESW]) ([0-9\.]+ ?[NESW])/.match(text)
|
85
|
+
|
86
|
+
matches && matches.size == 3 ? [ $1, $2 ] : []
|
87
|
+
end
|
88
|
+
|
89
|
+
def normal_lat(lat)
|
90
|
+
lat, dir = lat.split(/ /)
|
91
|
+
lat = lat.to_f
|
92
|
+
lat = -lat if dir == 'S'
|
93
|
+
|
94
|
+
lat
|
95
|
+
end
|
96
|
+
|
97
|
+
def normal_lng(lng)
|
98
|
+
lng, dir = lng.split(/ /)
|
99
|
+
lng = lng.to_f
|
100
|
+
lng = -lng if dir == 'W'
|
101
|
+
|
102
|
+
lng
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/buoy_data.rb
CHANGED
@@ -2,6 +2,7 @@ require 'httparty'
|
|
2
2
|
require 'buoy_data/buoy_list'
|
3
3
|
require 'buoy_data/buoy_reading'
|
4
4
|
require 'buoy_data/noaa_buoy_reading'
|
5
|
+
require 'buoy_data/noaa_station'
|
5
6
|
require 'buoy_data/noaa_buoy_list'
|
6
7
|
require 'buoy_data/noaa_buoy_observation'
|
7
8
|
require 'buoy_data/noaa_buoy_forecast'
|
data/spec/noaa_buoy_list_spec.rb
CHANGED
@@ -7,13 +7,24 @@ describe BuoyData::NoaaBuoyList do
|
|
7
7
|
it "should get buoy list" do
|
8
8
|
buoy_list.should be
|
9
9
|
buoy_list.stub(:stations).and_return(stubbed_station_list)
|
10
|
-
stations = buoy_list.get
|
11
10
|
|
12
|
-
|
11
|
+
results = buoy_list.get
|
12
|
+
results.should_not be_empty
|
13
|
+
results[:errors].should be_empty
|
14
|
+
stations = results[:stations]
|
15
|
+
stations.compact.should_not be_empty
|
16
|
+
station = stations.first
|
17
|
+
|
18
|
+
# Verify we have water temp value
|
19
|
+
wtmp = station[:wtmp]
|
20
|
+
wtmp.should be_kind_of Float
|
13
21
|
end
|
14
22
|
end
|
15
23
|
|
16
24
|
def stubbed_station_list
|
17
|
-
[
|
25
|
+
[
|
26
|
+
"station_page.php?station=41012",
|
27
|
+
"station_page.php?station=sauf1"
|
28
|
+
]
|
18
29
|
end
|
19
30
|
end
|
metadata
CHANGED
@@ -7,8 +7,8 @@ version: !ruby/object:Gem::Version
|
|
7
7
|
- 0
|
8
8
|
- 0
|
9
9
|
- beta
|
10
|
-
-
|
11
|
-
version: 1.0.0.beta.
|
10
|
+
- 1
|
11
|
+
version: 1.0.0.beta.1
|
12
12
|
platform: ruby
|
13
13
|
authors:
|
14
14
|
- Adam Weller
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-
|
19
|
+
date: 2011-04-17 00:00:00 -04:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -95,6 +95,7 @@ files:
|
|
95
95
|
- lib/buoy_data/noaa_buoy_list.rb
|
96
96
|
- lib/buoy_data/noaa_buoy_observation.rb
|
97
97
|
- lib/buoy_data/noaa_buoy_reading.rb
|
98
|
+
- lib/buoy_data/noaa_station.rb
|
98
99
|
- spec/noaa_buoy_forecast_spec.rb
|
99
100
|
- spec/noaa_buoy_list_spec.rb
|
100
101
|
- spec/noaa_buoy_observation_spec.rb
|