spotlite 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|