spotlite 0.7.2 → 0.8.0
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/CHANGELOG.md +14 -0
- data/README.md +8 -41
- data/Rakefile +23 -3
- data/lib/spotlite.rb +1 -8
- data/lib/spotlite/movie.rb +169 -80
- data/lib/spotlite/person.rb +90 -14
- data/lib/spotlite/string_extensions.rb +9 -9
- data/lib/spotlite/version.rb +1 -1
- data/spec/fixtures/movie_find_conan +722 -0
- data/spec/fixtures/{search_no_results → movie_find_no_results} +95 -149
- data/spec/fixtures/nm0000233/index +6118 -0
- data/spec/fixtures/nm0005132/index +817 -740
- data/spec/fixtures/nm0864666/index +199 -221
- data/spec/fixtures/nm1659547/index +748 -719
- data/spec/fixtures/person_find_conan +722 -0
- data/spec/fixtures/{search_the_core → person_find_no_results} +112 -219
- data/spec/fixtures/tt0002186/index +212 -242
- data/spec/fixtures/tt0047396/releaseinfo +217 -292
- data/spec/fixtures/tt0112873/index +556 -539
- data/spec/fixtures/tt0133093/criticreviews +169 -250
- data/spec/fixtures/tt0133093/fullcredits +212 -299
- data/spec/fixtures/tt0133093/index +444 -491
- data/spec/fixtures/tt0133093/keywords +416 -492
- data/spec/fixtures/tt0133093/mediaindex_still_frame +114 -158
- data/spec/fixtures/tt0133093/releaseinfo +282 -344
- data/spec/fixtures/tt0133093/technical +1144 -0
- data/spec/fixtures/tt0133093/trivia +1350 -1230
- data/spec/fixtures/tt0169547/index +629 -644
- data/spec/fixtures/tt0317248/index +579 -608
- data/spec/fixtures/tt1134629/fullcredits +257 -340
- data/spec/spec_helper.rb +24 -23
- data/spec/spotlite/find_spec.rb +38 -0
- data/spec/spotlite/movie_spec.rb +73 -57
- data/spec/spotlite/person_spec.rb +60 -1
- data/spotlite.gemspec +9 -9
- metadata +34 -56
- data/lib/spotlite/box_office_top.rb +0 -11
- data/lib/spotlite/coming_soon.rb +0 -24
- data/lib/spotlite/in_theaters.rb +0 -25
- data/lib/spotlite/list.rb +0 -18
- data/lib/spotlite/opening_this_week.rb +0 -11
- data/lib/spotlite/search.rb +0 -45
- data/lib/spotlite/top.rb +0 -23
- data/spec/fixtures/movies_coming_soon +0 -2103
- data/spec/fixtures/movies_in_theaters +0 -2708
- data/spec/fixtures/top +0 -10823
- data/spec/spotlite/box_office_top_spec.rb +0 -29
- data/spec/spotlite/coming_soon_spec.rb +0 -29
- data/spec/spotlite/opening_this_week_spec.rb +0 -29
- data/spec/spotlite/search_spec.rb +0 -34
- data/spec/spotlite/top_spec.rb +0 -21
- data/tasks/fixtures.rake +0 -15
checksums.yaml
ADDED
@@ -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
|
data/CHANGELOG.md
CHANGED
@@ -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(
|
25
|
+
> movie = Spotlite::Movie.new('0133093')
|
26
26
|
# Or use search instead
|
27
|
-
> list = Spotlite::
|
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", "
|
34
|
+
=> ["Action", "Sci-Fi"]
|
35
35
|
> movie.countries
|
36
36
|
=> [{:code=>"us", :name=>"USA"}, {:code=>"au", :name=>"Australia"}]
|
37
37
|
> movie.directors
|
38
|
-
=> [
|
39
|
-
|
40
|
-
|
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
|
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
|
data/lib/spotlite.rb
CHANGED
@@ -8,11 +8,4 @@ require "nokogiri"
|
|
8
8
|
require "spotlite/version"
|
9
9
|
require "spotlite/movie"
|
10
10
|
require "spotlite/person"
|
11
|
-
require "spotlite/
|
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"
|
data/lib/spotlite/movie.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
|
-
|
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, :
|
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(
|
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('"',
|
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(
|
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+]/,
|
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[
|
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[
|
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(
|
142
|
+
src = details.at('#img_primary img')['src'] rescue nil
|
104
143
|
|
105
144
|
if src =~ /^(http:.+@@)/ || src =~ /^(http:.+?)\.[^\/]+$/
|
106
|
-
$1 +
|
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(
|
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(
|
115
|
-
year = node.at(
|
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
|
134
|
-
# with keys
|
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
|
-
|
186
|
+
parse_crew('Directed by')
|
137
187
|
end
|
138
188
|
|
139
|
-
# Returns a list of writers as an array of
|
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
|
-
|
191
|
+
parse_crew('Writing Credits')
|
143
192
|
end
|
144
193
|
|
145
|
-
# Returns a list of producers as an array of
|
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
|
-
|
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
|
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
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
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
|
169
|
-
|
170
|
-
|
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
|
-
|
173
|
-
|
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(
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
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(
|
227
|
-
src = image[
|
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 +
|
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(
|
346
|
+
@release_info ||= open_page('releaseinfo')
|
245
347
|
end
|
246
348
|
|
247
349
|
def full_credits # :nodoc:
|
248
|
-
@full_credits ||= open_page(
|
350
|
+
@full_credits ||= open_page('fullcredits')
|
249
351
|
end
|
250
352
|
|
251
353
|
def plot_keywords # :nodoc:
|
252
|
-
@plot_keywords ||= open_page(
|
354
|
+
@plot_keywords ||= open_page('keywords')
|
253
355
|
end
|
254
356
|
|
255
357
|
def movie_trivia # :nodoc:
|
256
|
-
@movie_trivia ||= open_page(
|
358
|
+
@movie_trivia ||= open_page('trivia')
|
257
359
|
end
|
258
360
|
|
259
361
|
def reviews
|
260
|
-
@reviews ||= open_page(
|
362
|
+
@reviews ||= open_page('criticreviews')
|
261
363
|
end
|
262
364
|
|
263
|
-
def still_frames
|
264
|
-
@still_frames ||= open_page(
|
365
|
+
def still_frames # :nodoc:
|
366
|
+
@still_frames ||= open_page('mediaindex?refine=still_frame')
|
265
367
|
end
|
266
368
|
|
267
|
-
def
|
268
|
-
|
269
|
-
"Accept-Language" => "en-us"))
|
369
|
+
def technical_info
|
370
|
+
@technical_info ||= open_page('technical')
|
270
371
|
end
|
271
372
|
|
272
|
-
def
|
273
|
-
|
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
|
|