spotlite 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +14 -0
  3. data/README.md +8 -41
  4. data/Rakefile +23 -3
  5. data/lib/spotlite.rb +1 -8
  6. data/lib/spotlite/movie.rb +169 -80
  7. data/lib/spotlite/person.rb +90 -14
  8. data/lib/spotlite/string_extensions.rb +9 -9
  9. data/lib/spotlite/version.rb +1 -1
  10. data/spec/fixtures/movie_find_conan +722 -0
  11. data/spec/fixtures/{search_no_results → movie_find_no_results} +95 -149
  12. data/spec/fixtures/nm0000233/index +6118 -0
  13. data/spec/fixtures/nm0005132/index +817 -740
  14. data/spec/fixtures/nm0864666/index +199 -221
  15. data/spec/fixtures/nm1659547/index +748 -719
  16. data/spec/fixtures/person_find_conan +722 -0
  17. data/spec/fixtures/{search_the_core → person_find_no_results} +112 -219
  18. data/spec/fixtures/tt0002186/index +212 -242
  19. data/spec/fixtures/tt0047396/releaseinfo +217 -292
  20. data/spec/fixtures/tt0112873/index +556 -539
  21. data/spec/fixtures/tt0133093/criticreviews +169 -250
  22. data/spec/fixtures/tt0133093/fullcredits +212 -299
  23. data/spec/fixtures/tt0133093/index +444 -491
  24. data/spec/fixtures/tt0133093/keywords +416 -492
  25. data/spec/fixtures/tt0133093/mediaindex_still_frame +114 -158
  26. data/spec/fixtures/tt0133093/releaseinfo +282 -344
  27. data/spec/fixtures/tt0133093/technical +1144 -0
  28. data/spec/fixtures/tt0133093/trivia +1350 -1230
  29. data/spec/fixtures/tt0169547/index +629 -644
  30. data/spec/fixtures/tt0317248/index +579 -608
  31. data/spec/fixtures/tt1134629/fullcredits +257 -340
  32. data/spec/spec_helper.rb +24 -23
  33. data/spec/spotlite/find_spec.rb +38 -0
  34. data/spec/spotlite/movie_spec.rb +73 -57
  35. data/spec/spotlite/person_spec.rb +60 -1
  36. data/spotlite.gemspec +9 -9
  37. metadata +34 -56
  38. data/lib/spotlite/box_office_top.rb +0 -11
  39. data/lib/spotlite/coming_soon.rb +0 -24
  40. data/lib/spotlite/in_theaters.rb +0 -25
  41. data/lib/spotlite/list.rb +0 -18
  42. data/lib/spotlite/opening_this_week.rb +0 -11
  43. data/lib/spotlite/search.rb +0 -45
  44. data/lib/spotlite/top.rb +0 -23
  45. data/spec/fixtures/movies_coming_soon +0 -2103
  46. data/spec/fixtures/movies_in_theaters +0 -2708
  47. data/spec/fixtures/top +0 -10823
  48. data/spec/spotlite/box_office_top_spec.rb +0 -29
  49. data/spec/spotlite/coming_soon_spec.rb +0 -29
  50. data/spec/spotlite/opening_this_week_spec.rb +0 -29
  51. data/spec/spotlite/search_spec.rb +0 -34
  52. data/spec/spotlite/top_spec.rb +0 -21
  53. data/tasks/fixtures.rake +0 -15
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cde36af5671b2f9ca6b4a495c1776c5ba6517e14
4
+ data.tar.gz: af543b22410dfedcdbb8ae0b9891f5001641d43a
5
+ SHA512:
6
+ metadata.gz: 6b4aa323ca78309219b4859defec059dadffa3745ad134cfe5f96425306ee2f5a65df089396f0b5a3186d50495689b04b7d086a4b7c6a98bb4125adf818e61f4
7
+ data.tar.gz: e3dac3d146ef5d59712706114c838ad03c9916653556c2c97902989245ec38e850ebc6718bea65d3e4b6375d0ea75ba6ae653dd04f595fad3be552876ff3d4c8
@@ -1,3 +1,17 @@
1
+ ## v0.8.0 06-Jul-2014
2
+
3
+ * Added `Spotlite::Movie.search` class method to perform advanced search by parameters
4
+ * Added `Spotlite::Movie.find` class method for simple title search
5
+ * Added `technical` method for `Movie` class to get movie technical information
6
+ * Added `alternative_titles` method for `Movie` class
7
+ * Added `Spotlite::Person.search` class method to perform advanced search by parameters
8
+ * Added `Spotlite::Person.find` class method for simple name search
9
+ * Added `filmography` method for `Person` class
10
+ * Moved task to refresh fixtures out of namespace. Now it can be called as `rake refresh_fixtures`
11
+ * Added `rake console` task. It will automatically `require 'spotlite'`
12
+ * Removed `Spotlite::List` class and all of its subclasses
13
+
14
+
1
15
  ## v0.7.2 15-Dec-2013
2
16
 
3
17
  * Fixes for updated Top 250 page
data/README.md CHANGED
@@ -22,62 +22,29 @@ Or install it yourself as:
22
22
 
23
23
  > require 'spotlite'
24
24
  # Access movie directly by its IMDb ID
25
- > movie = Spotlite::Movie.new("0133093")
25
+ > movie = Spotlite::Movie.new('0133093')
26
26
  # Or use search instead
27
- > list = Spotlite::Search.new("the matrix").movies
27
+ > list = Spotlite::Movie.find('the matrix')
28
28
  > movie = list.first
29
29
  > movie.title
30
30
  => "The Matrix"
31
31
  > movie.runtime
32
32
  => 136
33
33
  > movie.genres
34
- => ["Action", "Adventure", "Sci-Fi"]
34
+ => ["Action", "Sci-Fi"]
35
35
  > movie.countries
36
36
  => [{:code=>"us", :name=>"USA"}, {:code=>"au", :name=>"Australia"}]
37
37
  > movie.directors
38
- => [{:imdb_id=>"0905152", :name=>"Andy Wachowski"},
39
- {:imdb_id=>"0905154", :name=>"Lana Wachowski"}]
40
- > movie.cast[0..4]
41
- => [{:imdb_id=>"0000206", :name=>"Keanu Reeves", :character=>"Neo"},
42
- {:imdb_id=>"0000401", :name=>"Laurence Fishburne", :character=>"Morpheus"},
43
- {:imdb_id=>"0005251", :name=>"Carrie-Anne Moss", :character=>"Trinity"},
44
- {:imdb_id=>"0915989", :name=>"Hugo Weaving", :character=>"Agent Smith"},
45
- {:imdb_id=>"0287825", :name=>"Gloria Foster", :character=>"Oracle"}]
38
+ => [#<Spotlite::Person:0x007f96a092be70 @imdb_id="0905152", @name="Andy Wachowski", @url="http://www.imdb.com/name/nm0905152/", @credits_category="Directed by", @credits_text="(as The Wachowski Brothers)">, #<Spotlite::Person:0x007f96a092bda8 @imdb_id="0905154", @name="Lana Wachowski", @url="http://www.imdb.com/name/nm0905154/", @credits_category="Directed by", @credits_text="(as The Wachowski Brothers)">]
39
+ > movie.cast[0..2]
40
+ => [#<Spotlite::Person:0x007f96a19521a0 @imdb_id="0000206", @name="Keanu Reeves", @url="http://www.imdb.com/name/nm0000206/", @credits_category="Cast", @credits_text="Neo">, #<Spotlite::Person:0x007f96a1951c28 @imdb_id="0000401", @name="Laurence Fishburne", @url="http://www.imdb.com/name/nm0000401/", @credits_category="Cast", @credits_text="Morpheus">, #<Spotlite::Person:0x007f96a1951a70 @imdb_id="0005251", @name="Carrie-Anne Moss", @url="http://www.imdb.com/name/nm0005251/", @credits_category="Cast", @credits_text="Trinity">]
46
41
 
47
- ### IMDb Top 250
48
-
49
- > list = Spotlite::Top.new.movies
50
-
51
- ### Movies opening this week
52
-
53
- > list = Spotlite::OpeningThisWeek.new.movies
54
-
55
- ### This week's box office top 10
56
-
57
- > list = Spotlite::BoxOfficeTop.new.movies
58
-
59
- ### Movies that are coming soon
60
-
61
- > list = Spotlite::ComingSoon.new.movies
62
-
63
42
  ## Important notice
64
43
 
65
44
  Movie titles will be localized if movie has an alternative title specific to your country.
66
45
  Example: _The Great Gatsby_ (http://www.imdb.com/title/tt1343092) has an alternative title _Gatsby le magnifique_ `France (imdb display title)` and will be localized accordingly based on your IP address, if you reside in France. Non-localized title is still avaliable with `original_title` method.
67
46
  Sorry, there is nothing I can do about it at the moment.
68
47
 
69
- ## Class tree
70
-
71
- Spotlite
72
- |
73
- |- Movie
74
- `- List
75
- |- Search
76
- |- Top
77
- `- InTheaters
78
- |- OpeningThisWeek
79
- `- BoxOfficeTop
80
-
81
48
  ## Contributing
82
49
 
83
50
  1. Fork it
@@ -125,13 +92,13 @@ First, run tests with `LIVE_TEST=true` environment variable:
125
92
 
126
93
  Adjust methods that are failing, according to the new layout. And refresh fixtures:
127
94
 
128
- $ rake fixtures:refresh
95
+ $ rake refresh_fixtures
129
96
 
130
97
  It will run through all elements of `IMDB_SAMPLES` hash to get fresh data.
131
98
 
132
99
  ## License
133
100
 
134
- Copyright (c) 2013 Artem Pakk
101
+ Copyright (c) 2013-2014 Artem Pakk
135
102
 
136
103
  MIT License
137
104
 
data/Rakefile CHANGED
@@ -1,8 +1,28 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
3
 
4
- load File.expand_path(File.dirname(__FILE__) + "/tasks/fixtures.rake")
5
-
6
4
  RSpec::Core::RakeTask.new("spec")
7
-
8
5
  task :default => :spec
6
+
7
+ desc "Launch irb console"
8
+ task :console do
9
+ require 'irb'
10
+ require 'irb/completion'
11
+ require 'spotlite'
12
+ ARGV.clear
13
+ IRB.start
14
+ end
15
+
16
+ desc "Refresh spec fixtures with fresh data from IMDb.com"
17
+ task :refresh_fixtures do
18
+ require File.expand_path(File.dirname(__FILE__) + "/spec/spec_helper")
19
+
20
+ IMDB_SAMPLES.each_pair do |url, fixture|
21
+ page = `curl -isH "Accept-Language: en-us" '#{url}'`
22
+
23
+ File.open(File.expand_path(File.dirname(__FILE__) + "/spec/fixtures/#{fixture}"), 'w') do |f|
24
+ f.write(page)
25
+ end
26
+
27
+ end
28
+ end
@@ -8,11 +8,4 @@ require "nokogiri"
8
8
  require "spotlite/version"
9
9
  require "spotlite/movie"
10
10
  require "spotlite/person"
11
- require "spotlite/list"
12
- require "spotlite/search"
13
- require "spotlite/top"
14
- require "spotlite/in_theaters"
15
- require "spotlite/opening_this_week"
16
- require "spotlite/box_office_top"
17
- require "spotlite/coming_soon"
18
- require "spotlite/string_extensions"
11
+ require "spotlite/string_extensions"
@@ -1,12 +1,13 @@
1
- module Spotlite
1
+ require 'cgi'
2
2
 
3
+ module Spotlite
3
4
  # Represents a movie on IMDb.com
4
5
  class Movie
5
- attr_accessor :imdb_id, :title, :year
6
+ attr_accessor :imdb_id, :url
6
7
 
7
8
  # Initialize a new movie object by its IMDb ID as a string
8
9
  #
9
- # movie = Spotlite::Movie.new("0133093")
10
+ # movie = Spotlite::Movie.new('0133093')
10
11
  #
11
12
  # Spotlite::Movie class objects are lazy loading. No HTTP request
12
13
  # will be performed upon object initialization. HTTP request will
@@ -14,10 +15,49 @@ module Spotlite
14
15
  # Currently, all data is spread across 6 pages: main movie page,
15
16
  # /releaseinfo, /fullcredits, /keywords, /trivia, and /criticreviews
16
17
  def initialize(imdb_id, title = nil, year = nil)
17
- @imdb_id = imdb_id
18
+ @imdb_id = "%07d" % imdb_id.to_i
18
19
  @title = title
19
20
  @year = year
20
- @url = "http://www.imdb.com/title/tt#{imdb_id}/"
21
+ @url = "http://www.imdb.com/title/tt#{@imdb_id}/"
22
+ end
23
+
24
+ # Returns a list of movies as an array of +Spotlite::Movie+ objects
25
+ # Takes single parameter and searches for movies by title and alternative titles
26
+ def self.find(query)
27
+ results = Nokogiri::HTML open("http://www.imdb.com/find?q=#{CGI::escape(query)}&s=tt&ttype=ft", 'Accept-Language' => 'en-us')
28
+ results.css('.result_text').map do |result|
29
+ imdb_id = result.at('a')['href'].parse_imdb_id
30
+ title = result.at('a').text.strip
31
+ year = result.children.take(3).last.text.parse_year
32
+
33
+ [imdb_id, title, year]
34
+ end.map do |values|
35
+ self.new(*values)
36
+ end
37
+ end
38
+
39
+ # Returns a list of movies as an array of +Spotlite::Movie+ objects
40
+ # Takes optional parameters as a hash
41
+ # See https://github.com/defeed/spotlite/wiki/Advanced-movie-search for details
42
+ def self.search(params = {})
43
+ defaults = {
44
+ :title_type => 'feature',
45
+ :view => 'simple',
46
+ :count => 250,
47
+ :start => 1,
48
+ :sort => 'moviemeter,asc'
49
+ }
50
+ params = defaults.merge(params).map{ |k, v| "#{k}=#{v}" }.join('&')
51
+ results = Nokogiri::HTML open("http://www.imdb.com/search/title?#{params}", 'Accept-Language' => 'en-us')
52
+ results.css('td.title').map do |result|
53
+ imdb_id = result.at('a')['href'].parse_imdb_id
54
+ title = result.at('a').text.strip
55
+ year = result.at('.year_type').text.parse_year
56
+
57
+ [imdb_id, title, year]
58
+ end.map do |values|
59
+ self.new(*values)
60
+ end
21
61
  end
22
62
 
23
63
  # Returns title as a string
@@ -27,7 +67,7 @@ module Spotlite
27
67
 
28
68
  # Returns original non-english title as a string
29
69
  def original_title
30
- details.at("h1.header span.title-extra[itemprop='name']").children.first.text.gsub('"', "").strip rescue nil
70
+ details.at("h1.header span.title-extra[itemprop='name']").children.first.text.gsub('"', '').strip rescue nil
31
71
  end
32
72
 
33
73
  # Returns year of original release as an integer
@@ -42,12 +82,12 @@ module Spotlite
42
82
 
43
83
  # Returns Metascore rating as an integer
44
84
  def metascore
45
- details.at("div.star-box-details a[href^=criticreviews]").text.strip.split("/").first.to_i rescue nil
85
+ details.at("div.star-box-details a[href^=criticreviews]").text.strip.split('/').first.to_i rescue nil
46
86
  end
47
87
 
48
88
  # Returns number of votes as an integer
49
89
  def votes
50
- details.at("div.star-box-details span[itemprop='ratingCount']").text.gsub(/[^\d+]/, "").to_i rescue nil
90
+ details.at("div.star-box-details span[itemprop='ratingCount']").text.gsub(/[^\d+]/, '').to_i rescue nil
51
91
  end
52
92
 
53
93
  # Returns short description as a string
@@ -75,7 +115,7 @@ module Spotlite
75
115
  def countries
76
116
  array = []
77
117
  details.css("div.txt-block a[href^='/country/']").each do |node|
78
- array << {:code => node["href"].clean_href, :name => node.text.strip}
118
+ array << {:code => node['href'].clean_href, :name => node.text.strip}
79
119
  end
80
120
 
81
121
  array
@@ -86,7 +126,7 @@ module Spotlite
86
126
  def languages
87
127
  array = []
88
128
  details.css("div.txt-block a[href^='/language/']").each do |node|
89
- array << {:code => node["href"].clean_href, :name => node.text.strip}
129
+ array << {:code => node['href'].clean_href, :name => node.text.strip}
90
130
  end
91
131
 
92
132
  array
@@ -94,25 +134,24 @@ module Spotlite
94
134
 
95
135
  # Returns runtime (length) in minutes as an integer
96
136
  def runtime
97
- details.at("time[itemprop='duration']").text.to_i rescue nil ||
98
- details.at("#overview-top .infobar").text.strip[/\d{2,3} min/].to_i rescue nil
137
+ details.at("time[itemprop='duration']").text.gsub(',', '').to_i rescue nil
99
138
  end
100
139
 
101
140
  # Returns primary poster URL as a string
102
141
  def poster_url
103
- src = details.at("#img_primary img")["src"] rescue nil
142
+ src = details.at('#img_primary img')['src'] rescue nil
104
143
 
105
144
  if src =~ /^(http:.+@@)/ || src =~ /^(http:.+?)\.[^\/]+$/
106
- $1 + ".jpg"
145
+ $1 + '.jpg'
107
146
  end
108
147
  end
109
148
 
110
149
  # Returns an array of recommended movies as an array of initialized objects of +Movie+ class
111
150
  def recommended_movies
112
- details.css(".rec-title").map do |node|
151
+ details.css('.rec-title').map do |node|
113
152
  imdb_id = node.at("a[href^='/title/tt']")['href'].parse_imdb_id
114
- title = node.at("a").text.strip
115
- year = node.at("span").text.parse_year
153
+ title = node.at('a').text.strip
154
+ year = node.at('span').text.parse_year
116
155
 
117
156
  [imdb_id, title, year]
118
157
  end.map do |values|
@@ -130,50 +169,95 @@ module Spotlite
130
169
  movie_trivia.css("div.sodatext").map { |node| node.text.strip } rescue []
131
170
  end
132
171
 
133
- # Returns a list of directors as an array of hashes
134
- # with keys: +imdb_id+ (string) and +name+ (string)
172
+ # Returns a list of movie alternative titles as an array of hashes
173
+ # with keys +title+ (string) and +comment+ (string)
174
+ def alternative_titles
175
+ array = []
176
+ release_info.css('#akas').css('tr').map do |row|
177
+ cells = row.css('td')
178
+ array << { :title => cells.last.text.strip, :comment => cells.first.text.strip }
179
+ end
180
+
181
+ array
182
+ end
183
+
184
+ # Returns a list of directors as an array of +Spotlite::Person+ objects
135
185
  def directors
136
- parse_staff("Directed by")
186
+ parse_crew('Directed by')
137
187
  end
138
188
 
139
- # Returns a list of writers as an array of hashes
140
- # with keys: +imdb_id+ (string) and +name+ (string)
189
+ # Returns a list of writers as an array of +Spotlite::Person+ objects
141
190
  def writers
142
- parse_staff("Writing Credits")
191
+ parse_crew('Writing Credits')
143
192
  end
144
193
 
145
- # Returns a list of producers as an array of hashes
146
- # with keys: +imdb_id+ (string) and +name+ (string)
194
+ # Returns a list of producers as an array of +Spotlite::Person+ objects
147
195
  def producers
148
- parse_staff("Produced by")
196
+ parse_crew('Produced by')
197
+ end
198
+
199
+ # Returns a list of starred actors as an array of +Spotlite::Person+ objects
200
+ def stars
201
+ details.css("td#overview-top div[itemprop='actors'] a[href^='/name/nm']").map do |node|
202
+ imdb_id = node['href'].parse_imdb_id
203
+ name = node.text.strip
204
+
205
+ [imdb_id, name]
206
+ end.map do |values|
207
+ Spotlite::Person.new(*values)
208
+ end
149
209
  end
150
210
 
151
- # Returns a list of actors as an array of hashes
152
- # with keys: +imdb_id+ (string), +name+ (string), and +character+ (string)
211
+ # Returns a list of actors as an array +Spotlite::Person+ objects
153
212
  def cast
154
- table = full_credits.css("table.cast_list")
155
- names = table.css("td[itemprop='actor']").map { |node| node.text.strip } rescue []
156
- links = table.css("td[itemprop='actor'] a").map { |node| node["href"].clean_href } rescue []
157
- imdb_ids = links.map { |link| link.parse_imdb_id } unless links.empty?
158
- characters = table.css("td.character").map { |node| node.text.clean_character }
159
-
160
- array = []
161
- 0.upto(names.size - 1) do |i|
162
- array << {:imdb_id => imdb_ids[i], :name => names[i], :character => characters[i]}
213
+ full_credits.css('table.cast_list tr').reject do |row|
214
+ # Skip 'Rest of cast' row
215
+ row.children.size == 1
216
+ end.map do |row|
217
+ imdb_id = row.at('td:nth-child(2) a')['href'].parse_imdb_id
218
+ name = row.at('td:nth-child(2) a').text.strip_whitespace
219
+ credits_text = row.last_element_child.text.strip_whitespace
220
+
221
+ [imdb_id, name, 'Cast', credits_text]
222
+ end.map do |values|
223
+ Spotlite::Person.new(*values)
163
224
  end
164
-
165
- array
166
225
  end
167
226
 
168
- # Returns a list of starred actors as an array of hashes
169
- # with keys: +imdb_id+ (string) and +name+ (string)
170
- def stars
227
+ # Returns a list of crew members of a certain category as an array +Spotlite::Person+ objects
228
+ def parse_crew(category)
229
+ table = full_credits.search("[text()^='#{category}']").first.next_element rescue []
230
+ if table && table.name == 'table'
231
+ table.css('tr').reject do |row|
232
+ # Skip empty table rows with one non-braking space
233
+ row.text.strip.size == 1
234
+ end.map do |row|
235
+ imdb_id = row.first_element_child.at('a')['href'].parse_imdb_id
236
+ name = row.first_element_child.at('a').text.strip_whitespace
237
+ credits_text = row.last_element_child.text.strip_whitespace
238
+
239
+ [imdb_id, name, category, credits_text]
240
+ end.map do |values|
241
+ Spotlite::Person.new(*values)
242
+ end
243
+ end
244
+ end
245
+
246
+ # Combines all crew categories and returns an array of +Spotlite::Person+ objects
247
+ def crew
248
+ crew_categories.map{ |category| parse_crew(category) }.flatten
249
+ end
250
+
251
+ # Returns combined `cast` and `crew` as an array of +Spotlite::Person+ objects
252
+ def credits
253
+ cast + crew
254
+ end
255
+
256
+ # Returns available crew categories, e.g. "Art Department", "Writing Credits", or "Stunts", as an array of strings
257
+ def crew_categories
171
258
  array = []
172
- details.css("td#overview-top div[itemprop='actors'] a[href^='/name/nm']").map do |node|
173
- name = node.text.strip
174
- imdb_id = node["href"].parse_imdb_id
175
-
176
- array << {:imdb_id => imdb_id, :name => name}
259
+ full_credits.css('h4.dataHeaderWithBorder').reject{ |h| h['id'] == 'cast' }.map do |node|
260
+ array << (node.children.size > 1 ? node.children.first.text.strip_whitespace : node.children.text.strip_whitespace)
177
261
  end
178
262
 
179
263
  array
@@ -186,15 +270,17 @@ module Spotlite
186
270
  # If day and month are unknown, 1st of January is assigned
187
271
  def release_dates
188
272
  array = []
189
- release_info.at("#release_dates").css("tr").map do |row|
190
- code = row.at("a")["href"].clean_href.split("=").last.downcase rescue nil
191
- region = row.at("a").text rescue nil
192
- date = row.at("td.release_date").text.strip.parse_date rescue nil
193
- comment = row.css("td").last.text.strip.clean_release_comment rescue nil
273
+ table = release_info.at('#release_dates')
274
+ table.css('tr').map do |row|
275
+ cells = row.css('td')
276
+ code = cells.first.at('a')['href'].clean_href.split('=').last.downcase rescue nil
277
+ region = cells.first.at('a').text rescue nil
278
+ date = cells.at('.release_date').text.strip.parse_date
279
+ comment = cells.last.text.strip.clean_release_comment
194
280
  comment = nil if comment.empty?
195
281
 
196
282
  array << {:code => code, :region => region, :date => date, :comment => comment}
197
- end
283
+ end unless table.nil?
198
284
 
199
285
  array
200
286
  end
@@ -223,17 +309,33 @@ module Spotlite
223
309
  # Returns URLs of movie still frames as an array of strings
224
310
  def images
225
311
  array = []
226
- still_frames.css("#media_index_thumbnail_grid img").map do |image|
227
- src = image["src"] rescue nil
312
+ still_frames.css('#media_index_thumbnail_grid img').map do |image|
313
+ src = image['src'] rescue nil
228
314
 
229
315
  if src =~ /^(http:.+@@)/ || src =~ /^(http:.+?)\.[^\/]+$/
230
- array << $1 + ".jpg"
316
+ array << $1 + '.jpg'
231
317
  end
232
318
  end
233
319
 
234
320
  array
235
321
  end
236
322
 
323
+ # Returns technical information like film length, aspect ratio, cameras, etc. as a hash of arrays of strings
324
+ def technical
325
+ hash = {}
326
+ table = technical_info.at_css('#technical_content table') rescue nil
327
+
328
+ table.css('tr').map do |row|
329
+ hash[row.css('td').first.text.strip] = row.css('td').last.children.
330
+ map(&:text).
331
+ map(&:strip_whitespace).
332
+ reject(&:empty?).
333
+ reject{|i| i == '|'}
334
+ end unless table.nil?
335
+
336
+ hash
337
+ end
338
+
237
339
  private
238
340
 
239
341
  def details # :nodoc:
@@ -241,48 +343,35 @@ module Spotlite
241
343
  end
242
344
 
243
345
  def release_info # :nodoc:
244
- @release_info ||= open_page("releaseinfo")
346
+ @release_info ||= open_page('releaseinfo')
245
347
  end
246
348
 
247
349
  def full_credits # :nodoc:
248
- @full_credits ||= open_page("fullcredits")
350
+ @full_credits ||= open_page('fullcredits')
249
351
  end
250
352
 
251
353
  def plot_keywords # :nodoc:
252
- @plot_keywords ||= open_page("keywords")
354
+ @plot_keywords ||= open_page('keywords')
253
355
  end
254
356
 
255
357
  def movie_trivia # :nodoc:
256
- @movie_trivia ||= open_page("trivia")
358
+ @movie_trivia ||= open_page('trivia')
257
359
  end
258
360
 
259
361
  def reviews
260
- @reviews ||= open_page("criticreviews")
362
+ @reviews ||= open_page('criticreviews')
261
363
  end
262
364
 
263
- def still_frames
264
- @still_frames ||= open_page("mediaindex?refine=still_frame")
365
+ def still_frames # :nodoc:
366
+ @still_frames ||= open_page('mediaindex?refine=still_frame')
265
367
  end
266
368
 
267
- def open_page(page = nil) # :nodoc:
268
- Nokogiri::HTML(open("http://www.imdb.com/title/tt#{@imdb_id}/#{page}",
269
- "Accept-Language" => "en-us"))
369
+ def technical_info
370
+ @technical_info ||= open_page('technical')
270
371
  end
271
372
 
272
- def parse_staff(staff) # :nodoc:
273
- array = []
274
- # table = full_credits.at("a[name='#{staff}']").parent.parent.parent.parent rescue nil
275
- table = full_credits.search("[text()*='#{staff}']").first.next_element rescue nil
276
- if table && table.name == "table"
277
- table.css("a[href^='/name/nm']").map do |node|
278
- imdb_id = node["href"].parse_imdb_id
279
- name = node.text.strip
280
-
281
- array << {:imdb_id => imdb_id, :name => name}
282
- end
283
- end
284
-
285
- array.uniq
373
+ def open_page(page = nil) # :nodoc:
374
+ Nokogiri::HTML open("#{@url}#{page}", 'Accept-Language' => 'en-us')
286
375
  end
287
376
  end
288
377