national-rail 0.3.8 → 0.3.10
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/lib/national-rail/journey_planner.rb +54 -14
- metadata +85 -6
@@ -5,8 +5,34 @@ require 'tidy_ffi'
|
|
5
5
|
|
6
6
|
module NationalRail
|
7
7
|
|
8
|
+
class ParseError < StandardError
|
9
|
+
attr_reader :original_exception, :page_html
|
10
|
+
def initialize(original_exception, page_html)
|
11
|
+
super(original_exception.message)
|
12
|
+
@original_exception, @page_html = original_exception, page_html
|
13
|
+
end
|
14
|
+
def inspect
|
15
|
+
"#{self.class} wrapping #{@original_exception.inspect}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class InputError < StandardError; end
|
20
|
+
|
8
21
|
class JourneyPlanner
|
9
22
|
|
23
|
+
class << self
|
24
|
+
attr_accessor :capture_path
|
25
|
+
def capture(page, filename)
|
26
|
+
if capture_path.present?
|
27
|
+
FileUtils.mkdir_p(capture_path)
|
28
|
+
path = File.join(capture_path, filename)
|
29
|
+
File.open(path, "w") { |f| f.write(TidyFFI::Tidy.new(page.parser.to_html).clean) }
|
30
|
+
end
|
31
|
+
rescue => e
|
32
|
+
puts e
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
10
36
|
class NokogiriParser < Mechanize::Page
|
11
37
|
attr_reader :doc
|
12
38
|
def initialize(uri = nil, response = nil, body = nil, code = nil)
|
@@ -38,23 +64,32 @@ module NationalRail
|
|
38
64
|
|
39
65
|
attr_reader :departure_time, :number_of_changes
|
40
66
|
|
41
|
-
def initialize(agent, date, departure_time, number_of_changes, link)
|
67
|
+
def initialize(agent, date, departure_time, number_of_changes, link, status)
|
42
68
|
@agent, @date = agent, date
|
43
69
|
@departure_time, @number_of_changes, @link = departure_time, number_of_changes, link
|
70
|
+
@status = status
|
71
|
+
end
|
72
|
+
|
73
|
+
def cancelled?
|
74
|
+
@status =~ %r{cancelled}i
|
44
75
|
end
|
45
76
|
|
46
77
|
def details
|
47
|
-
return if number_of_changes.to_i > 0
|
78
|
+
return {} if number_of_changes.to_i > 0
|
79
|
+
return {} if cancelled?
|
48
80
|
@agent.transact do
|
49
|
-
|
81
|
+
details_page = @link.click
|
82
|
+
JourneyPlanner.capture(details_page, "details.html")
|
83
|
+
parse_details(details_page, @date)
|
50
84
|
end
|
51
85
|
end
|
52
86
|
|
53
87
|
def parse_details(page, date)
|
54
88
|
details = {}
|
55
89
|
description = (page.doc/"table#journeyLegDetails tbody tr.lastRow td[@colspan='6'] div").last.inner_text.gsub(/\s+/, " ").strip
|
56
|
-
|
57
|
-
details
|
90
|
+
company_matches = /(.*) service from .* to .*/.match(description)
|
91
|
+
return details unless company_matches
|
92
|
+
details[:company] = company_matches[1].strip
|
58
93
|
origins, destinations = (/.* service from (.*) to (.*)/.match(description)[1,2]).map{ |s| s.split(",").map(&:strip) }
|
59
94
|
details[:origins], details[:destinations] = origins, destinations
|
60
95
|
parser = TimeParser.new(date)
|
@@ -90,9 +125,9 @@ module NationalRail
|
|
90
125
|
}
|
91
126
|
details
|
92
127
|
rescue => e
|
93
|
-
|
94
|
-
|
95
|
-
raise e
|
128
|
+
JourneyPlanner.capture(page, "details-error.html")
|
129
|
+
page_html = TidyFFI::Tidy.new(page.parser.to_html).clean
|
130
|
+
raise ParseError.new(e, page_html)
|
96
131
|
end
|
97
132
|
end
|
98
133
|
|
@@ -106,6 +141,7 @@ module NationalRail
|
|
106
141
|
def plan(options = {})
|
107
142
|
summary_rows = []
|
108
143
|
@agent.get("http://www.nationalrail.co.uk/") do |home_page|
|
144
|
+
JourneyPlanner.capture(home_page, "index.html")
|
109
145
|
button = nil
|
110
146
|
times_page = home_page.form_with(:action => "http://ojp.nationalrail.co.uk/en/s/planjourney/plan") do |form|
|
111
147
|
button = form.buttons.last
|
@@ -132,8 +168,10 @@ module NationalRail
|
|
132
168
|
form["_includeOvertakenTrains"] = "on"
|
133
169
|
end.click_button(button)
|
134
170
|
|
171
|
+
JourneyPlanner.capture(times_page, "summary.html")
|
172
|
+
|
135
173
|
if (times_page.doc/".error-message").any?
|
136
|
-
raise (times_page.doc/".error-message").first.inner_text.gsub(/\s+/, " ").strip
|
174
|
+
raise InputError.new((times_page.doc/".error-message").first.inner_text.gsub(/\s+/, " ").strip)
|
137
175
|
end
|
138
176
|
|
139
177
|
date = Date.parse((times_page.doc/".journey-details span").first.children.first.inner_text.gsub(/\s+/, " ").gsub(/\+ 1 day/, '').strip)
|
@@ -145,22 +183,24 @@ module NationalRail
|
|
145
183
|
next
|
146
184
|
end
|
147
185
|
|
148
|
-
departure_time = TimeParser.new(date).time((tr/"td
|
186
|
+
departure_time = TimeParser.new(date).time((tr/"td:nth-child(1)").inner_text.strip)
|
149
187
|
number_of_changes = (tr/"td:nth-child(6)").inner_text.strip
|
188
|
+
status = (tr/"td:nth-child(10) .status").inner_text.strip
|
150
189
|
|
151
190
|
anchor = (tr/"a[@id^=journeyOption]").first
|
152
191
|
next unless anchor
|
153
192
|
|
154
193
|
link = times_page.links.detect { |l| l.attributes["id"] == anchor.attributes["id"].value }
|
155
194
|
|
156
|
-
summary_rows << SummaryRow.new(@agent, date, departure_time, number_of_changes, link)
|
195
|
+
summary_rows << SummaryRow.new(@agent, date, departure_time, number_of_changes, link, status)
|
157
196
|
end
|
158
197
|
end
|
159
198
|
summary_rows
|
160
199
|
rescue => e
|
161
|
-
|
162
|
-
|
163
|
-
|
200
|
+
page = @agent.current_page
|
201
|
+
JourneyPlanner.capture(page, "summary-error.html")
|
202
|
+
page_html = TidyFFI::Tidy.new(page.parser.to_html).clean
|
203
|
+
raise ParseError.new(e, page_html)
|
164
204
|
end
|
165
205
|
end
|
166
206
|
end
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: national-rail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 7
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
9
|
+
- 10
|
10
|
+
version: 0.3.10
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- James Mead
|
@@ -14,16 +15,18 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-12-05 00:00:00 +00:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: mechanize
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ~>
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 23
|
27
30
|
segments:
|
28
31
|
- 1
|
29
32
|
- 0
|
@@ -35,9 +38,11 @@ dependencies:
|
|
35
38
|
name: hpricot
|
36
39
|
prerelease: false
|
37
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
38
42
|
requirements:
|
39
43
|
- - ~>
|
40
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 59
|
41
46
|
segments:
|
42
47
|
- 0
|
43
48
|
- 8
|
@@ -49,9 +54,11 @@ dependencies:
|
|
49
54
|
name: nokogiri
|
50
55
|
prerelease: false
|
51
56
|
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
52
58
|
requirements:
|
53
59
|
- - ~>
|
54
60
|
- !ruby/object:Gem::Version
|
61
|
+
hash: 15
|
55
62
|
segments:
|
56
63
|
- 1
|
57
64
|
- 4
|
@@ -63,9 +70,11 @@ dependencies:
|
|
63
70
|
name: activesupport
|
64
71
|
prerelease: false
|
65
72
|
requirement: &id004 !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
66
74
|
requirements:
|
67
75
|
- - ~>
|
68
76
|
- !ruby/object:Gem::Version
|
77
|
+
hash: 7
|
69
78
|
segments:
|
70
79
|
- 3
|
71
80
|
- 0
|
@@ -74,19 +83,85 @@ dependencies:
|
|
74
83
|
type: :runtime
|
75
84
|
version_requirements: *id004
|
76
85
|
- !ruby/object:Gem::Dependency
|
77
|
-
name:
|
86
|
+
name: ffi
|
78
87
|
prerelease: false
|
79
88
|
requirement: &id005 !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - "="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 1
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
- 6
|
97
|
+
- 3
|
98
|
+
version: 0.6.3
|
99
|
+
type: :runtime
|
100
|
+
version_requirements: *id005
|
101
|
+
- !ruby/object:Gem::Dependency
|
102
|
+
name: tidy_ffi
|
103
|
+
prerelease: false
|
104
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
80
106
|
requirements:
|
81
107
|
- - ~>
|
82
108
|
- !ruby/object:Gem::Version
|
109
|
+
hash: 29
|
83
110
|
segments:
|
84
111
|
- 0
|
85
112
|
- 1
|
86
113
|
- 3
|
87
114
|
version: 0.1.3
|
88
115
|
type: :runtime
|
89
|
-
version_requirements: *
|
116
|
+
version_requirements: *id006
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: i18n
|
119
|
+
prerelease: false
|
120
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ~>
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
hash: 13
|
126
|
+
segments:
|
127
|
+
- 0
|
128
|
+
- 4
|
129
|
+
- 1
|
130
|
+
version: 0.4.1
|
131
|
+
type: :runtime
|
132
|
+
version_requirements: *id007
|
133
|
+
- !ruby/object:Gem::Dependency
|
134
|
+
name: tzinfo
|
135
|
+
prerelease: false
|
136
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ~>
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
hash: 61
|
142
|
+
segments:
|
143
|
+
- 0
|
144
|
+
- 3
|
145
|
+
- 23
|
146
|
+
version: 0.3.23
|
147
|
+
type: :runtime
|
148
|
+
version_requirements: *id008
|
149
|
+
- !ruby/object:Gem::Dependency
|
150
|
+
name: webmock
|
151
|
+
prerelease: false
|
152
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
hash: 13
|
158
|
+
segments:
|
159
|
+
- 1
|
160
|
+
- 6
|
161
|
+
- 1
|
162
|
+
version: 1.6.1
|
163
|
+
type: :development
|
164
|
+
version_requirements: *id009
|
90
165
|
description:
|
91
166
|
email: james@floehopper.org
|
92
167
|
executables: []
|
@@ -113,23 +188,27 @@ rdoc_options: []
|
|
113
188
|
require_paths:
|
114
189
|
- lib
|
115
190
|
required_ruby_version: !ruby/object:Gem::Requirement
|
191
|
+
none: false
|
116
192
|
requirements:
|
117
193
|
- - ">="
|
118
194
|
- !ruby/object:Gem::Version
|
195
|
+
hash: 3
|
119
196
|
segments:
|
120
197
|
- 0
|
121
198
|
version: "0"
|
122
199
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
200
|
+
none: false
|
123
201
|
requirements:
|
124
202
|
- - ">="
|
125
203
|
- !ruby/object:Gem::Version
|
204
|
+
hash: 3
|
126
205
|
segments:
|
127
206
|
- 0
|
128
207
|
version: "0"
|
129
208
|
requirements: []
|
130
209
|
|
131
210
|
rubyforge_project: national-rail
|
132
|
-
rubygems_version: 1.3.
|
211
|
+
rubygems_version: 1.3.7
|
133
212
|
signing_key:
|
134
213
|
specification_version: 3
|
135
214
|
summary: A Ruby API for the National Rail website
|