worth_watching 0.1.5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +23 -36
- data/lib/worth_watching.rb +18 -1
- data/lib/worth_watching/aggregator.rb +10 -186
- data/lib/worth_watching/errors.rb +2 -0
- data/lib/worth_watching/imdb/rating_fetcher.rb +38 -0
- data/lib/worth_watching/metacritic/rating_fetcher.rb +28 -0
- data/lib/worth_watching/movie.rb +17 -32
- data/lib/worth_watching/reviews_fetcher.rb +16 -0
- data/lib/worth_watching/rotten_tomatoes/movie_info_fetcher.rb +23 -0
- data/lib/worth_watching/rotten_tomatoes/movie_list_fetcher.rb +51 -0
- data/lib/worth_watching/rotten_tomatoes/movie_parser.rb +47 -0
- data/lib/worth_watching/rotten_tomatoes/review_parser.rb +22 -0
- data/lib/worth_watching/rotten_tomatoes/reviews_fetcher.rb +19 -0
- data/lib/worth_watching/rotten_tomatoes/rotten_tomatoes.rb +5 -0
- data/lib/worth_watching/rotten_tomatoes/searcher.rb +37 -0
- data/lib/worth_watching/tmdb/poster_fetcher.rb +26 -0
- data/lib/worth_watching/version.rb +1 -1
- data/lib/worth_watching/written_review.rb +15 -15
- data/spec/{unit/aggregator_spec.rb → integration/aggregating_a_movie_spec.rb} +18 -45
- data/spec/{test_helper.rb → spec_helper.rb} +0 -0
- data/spec/support/json_responses/a_movie_with_little_info_rt.json +1 -0
- data/spec/unit/imdb/rating_fetcher_spec.rb +31 -0
- data/spec/unit/movie_spec.rb +16 -37
- data/spec/unit/rotten_tomatoes/movie_info_fetcher_spec.rb +63 -0
- data/spec/unit/rotten_tomatoes/movie_list_fetcher_spec.rb +38 -0
- data/spec/unit/rotten_tomatoes/movie_parser_spec.rb +80 -0
- data/spec/unit/rotten_tomatoes/review_parser_spec.rb +47 -0
- data/spec/unit/rotten_tomatoes/reviews_fetcher_spec.rb +18 -0
- data/spec/unit/rotten_tomatoes/searcher_spec.rb +49 -0
- data/spec/unit/tmdb/poster_fetcher_spec.rb +15 -0
- data/spec/unit/written_review_spec.rb +16 -35
- data/worth_watching.gemspec +1 -0
- metadata +51 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8c86cd8984aed68285c27d7efc4468c99a7bfac8
|
4
|
+
data.tar.gz: 5b494c7a1279f7b892bc77f4ced8476936d9f88d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0cc5edba36c66abec35fec8e47780c2b74c7e03a72381c407ac3d7defdb07d29616d6e572347698cc21ce205647cc033d0e1ccda43a6f640dafd23b7bf9af231
|
7
|
+
data.tar.gz: 777a90ae1caa2606a93d1eb81d0b170bcd77703cb1be2f66632b0e42743acd251a739e8cf6336d2133036e6fab823327fa9bfe8a5dca88f2e06038ad826ebc9a
|
data/README.md
CHANGED
@@ -76,7 +76,8 @@ Pass the title of the movie, and the maximum number of results to return
|
|
76
76
|
# Search for movies by title. Returns an array of hashes, each hash representing
|
77
77
|
# a movie in the search result
|
78
78
|
# Note that it returns the Rotten Tomatoes ID for each movie, which is vital to aggregation
|
79
|
-
|
79
|
+
searcher = WorthWatching::RottenTomatoes::Searcher.new("rt_api_key")
|
80
|
+
searcher.search_by_title("the godfather", 4)
|
80
81
|
=> [{:title=>"The Godfather", :rt_id=>"12911", :year=>"1972"},
|
81
82
|
{:title=>"The Godfather, Part II", :rt_id=>"12926", :year=>"1974"},
|
82
83
|
{:title=>"The Godfather, Part III", :rt_id=>"13476", :year=>"1990"},
|
@@ -212,8 +213,7 @@ Rating: 4/5"
|
|
212
213
|
|
213
214
|
### Aggregating a list of movies
|
214
215
|
The Rotten Tomatoes API supports a number of pre-defined lists for both cinema/theater
|
215
|
-
releases and DVD releases.
|
216
|
-
on the Box Office list (best performing cinema releases), WorthWatching supports this.
|
216
|
+
releases and DVD releases.
|
217
217
|
|
218
218
|
Pass the name of the list you would like to process (as a Symbol), the country code
|
219
219
|
(ISO 3166-1 alpha-2) of the country you would like info to be localised to (as a Symbol),
|
@@ -233,47 +233,34 @@ ticket sales
|
|
233
233
|
- ``:new_releases`` - new DVD releases
|
234
234
|
- ``:upcoming_dvd`` - upcoming DVD releases
|
235
235
|
|
236
|
-
**Be careful using this feature! Since WorthWatching will aggregate info for each movie on the list,
|
237
|
-
there is the potential to make a significant number of API calls through repeated use.**
|
238
|
-
|
239
236
|
**The Rotten Tomatoes API
|
240
237
|
does have rate limits (as of March 2014: 5 calls a second, 10,000 calls a day)**
|
241
238
|
|
242
|
-
|
243
239
|
```ruby
|
240
|
+
# Create a new fetcher using your API key
|
241
|
+
list_fetcher = WorthWatching::RottenTomatoes::MovieListFetcher.new("rt_api_key")
|
244
242
|
|
245
|
-
#
|
246
|
-
|
243
|
+
# Get the top 4 box office movies in the UK
|
244
|
+
list_fetcher.fetch_list(:box_office, :uk, 4)
|
245
|
+
=> [{:title=>"A Most Wanted Man", :rt_id=>"771314084", :year=>"2014", :rt_rating=>91},
|
246
|
+
{:title=>"Before I Go to Sleep", :rt_id=>"771367646", :year=>"2014", :rt_rating=>58},
|
247
|
+
{:title=>"Let's Be Cops", :rt_id=>"771372963", :year=>"2014", :rt_rating=>20},
|
248
|
+
{:title=>"Magic in the Moonlight", :rt_id=>"771367659", :year=>"2014", :rt_rating=>51}]
|
247
249
|
|
248
250
|
# Or the top 6 releases on DVD in the US
|
249
|
-
top_dvds =
|
251
|
+
top_dvds = list_fetcher.fetch_list(:top_rentals, :us, 6)
|
252
|
+
=> [{:title=>"Captain America: The Winter Soldier", :rt_id=>"771312513", :year=>"2014", :rt_rating=>89},
|
253
|
+
{:title=>"The Amazing Spider-Man 2", :rt_id=>"771249926", :year=>"2014", :rt_rating=>53},
|
254
|
+
{:title=>"Godzilla", :rt_id=>"771225175", :year=>"2014", :rt_rating=>73},
|
255
|
+
{:title=>"Neighbors", :rt_id=>"771308254", :year=>"2014", :rt_rating=>73},
|
256
|
+
{:title=>"Divergent", :rt_id=>"771315918", :year=>"2014", :rt_rating=>41},
|
257
|
+
{:title=>"Noah", :rt_id=>"771305170", :year=>"2014", :rt_rating=>77}]
|
250
258
|
|
251
|
-
# The above list-based methods return an array of
|
252
|
-
|
259
|
+
# The above list-based methods return an array of hashes, each representing a result
|
260
|
+
number_1_dvd = top_dvds.first
|
261
|
+
=> {:title=>"Captain America: The Winter Soldier", :rt_id=>"771312513", :year=>"2014", :rt_rating=>89}
|
253
262
|
|
254
|
-
|
255
|
-
|
263
|
+
# Use the rt_id (Rotten Tomato ID) to subsequently aggregate movie info
|
264
|
+
aggregated_results = top_dvds.map { |movie| aggregator.aggregate_movie(movie[:rt_id]) }
|
256
265
|
|
257
|
-
number_1_movie.metacritic_rating
|
258
|
-
=> 71
|
259
266
|
```
|
260
|
-
|
261
|
-
### Why is the returned list empty?
|
262
|
-
|
263
|
-
This may be because some movies do not have the minimum amount of data available
|
264
|
-
in order to aggregate their rating info, and are therefore 'discarded' during the aggregation
|
265
|
-
process.
|
266
|
-
|
267
|
-
If a movie's IMDb ID is not available through the Rotten Tomatoes API, rating info
|
268
|
-
cannot be retrieved.
|
269
|
-
|
270
|
-
During testing I also noticed that movies with no available release date were likely
|
271
|
-
to be very obscure and not have any rating info associated with them either. This is
|
272
|
-
the other criteria for a movie being discarded.
|
273
|
-
|
274
|
-
This only tends to happen with very small release independent films, particularly foreign ones.
|
275
|
-
|
276
|
-
The lists where the above is most likely are ``:upcoming`` and ``:upcoming_dvd``, since they
|
277
|
-
contain movies that probably don't have any rating info yet, as they haven't been released.
|
278
|
-
|
279
|
-
The opposite is true for lists like ``:box_office`` and ``top_rentals``.
|
data/lib/worth_watching.rb
CHANGED
@@ -2,6 +2,23 @@ require "worth_watching/version"
|
|
2
2
|
require 'worth_watching/aggregator'
|
3
3
|
require 'worth_watching/movie'
|
4
4
|
require 'worth_watching/written_review'
|
5
|
+
require 'worth_watching/errors'
|
6
|
+
|
7
|
+
require 'worth_watching/rotten_tomatoes/rotten_tomatoes'
|
8
|
+
require 'worth_watching/rotten_tomatoes/movie_parser'
|
9
|
+
require 'worth_watching/rotten_tomatoes/review_parser'
|
10
|
+
require 'worth_watching/rotten_tomatoes/reviews_fetcher'
|
11
|
+
require 'worth_watching/rotten_tomatoes/movie_info_fetcher'
|
12
|
+
require 'worth_watching/rotten_tomatoes/movie_list_fetcher'
|
13
|
+
require 'worth_watching/rotten_tomatoes/searcher'
|
14
|
+
|
15
|
+
require 'worth_watching/imdb/rating_fetcher'
|
16
|
+
|
17
|
+
require 'worth_watching/metacritic/rating_fetcher'
|
18
|
+
|
19
|
+
require 'worth_watching/reviews_fetcher'
|
20
|
+
|
21
|
+
require 'worth_watching/tmdb/poster_fetcher'
|
5
22
|
|
6
23
|
module WorthWatching
|
7
|
-
end
|
24
|
+
end
|
@@ -1,21 +1,12 @@
|
|
1
|
-
require 'nokogiri'
|
2
|
-
require 'typhoeus'
|
3
|
-
require 'json'
|
4
|
-
|
5
1
|
module WorthWatching
|
6
2
|
class Aggregator
|
7
3
|
|
8
4
|
attr_accessor :rt_api_key, :tmdb_api_key
|
9
5
|
attr_reader :movie
|
10
6
|
|
11
|
-
RT_API_BASE_URL = 'http://api.rottentomatoes.com/api/public/v1.0'
|
12
|
-
TMDB_API_BASE_URL = 'http://api.themoviedb.org/3'
|
13
|
-
|
14
|
-
# Initialize a new Aggregator object to retrieve movie info
|
15
7
|
def initialize(rt_api_key, tmdb_api_key)
|
16
8
|
@rt_api_key = rt_api_key
|
17
9
|
@tmdb_api_key = tmdb_api_key
|
18
|
-
@movie = nil # the current movie being aggregated
|
19
10
|
end
|
20
11
|
|
21
12
|
# Retrieve the details of a specific movie using its Rotten Tomatoes ID
|
@@ -23,188 +14,21 @@ module WorthWatching
|
|
23
14
|
# @param rt_id [String] the Rotten Tomatoes ID of the movie
|
24
15
|
# @return [Movie] a Movie object representing the movie
|
25
16
|
def aggregate_movie(rt_id)
|
26
|
-
uri = "#{RT_API_BASE_URL}/movies/#{rt_id}.json?apikey=#{@rt_api_key}"
|
27
|
-
movie_hash = JSON.parse(Typhoeus.get(uri).body)
|
28
|
-
|
29
|
-
@movie = Movie.new(movie_hash)
|
30
|
-
aggregate
|
31
|
-
end
|
32
|
-
|
33
|
-
# Retrieve a list of movies, then aggregate info for each one
|
34
|
-
#
|
35
|
-
# @param list_name[Symbol] the name of the Rotten Tomato list. Possible values: :box_office,
|
36
|
-
# :in_theaters, :opening, :upcoming, :top_rentals, :current_releases, :new_releases, :upcoming_dvd
|
37
|
-
# @param country [Symbol] Localised data for the selected country (ISO 3166-1 alpha-2)
|
38
|
-
# @param result_limit [Integer] the max number of movies to return in the list
|
39
|
-
# @return [Array] an array of Movie objects
|
40
|
-
def aggregate_list(list_name, country, result_limit)
|
41
|
-
case list_name
|
42
|
-
|
43
|
-
# Build the appropriate URI based on the list name.
|
44
|
-
# Some enpoints use 'limit' to specify max results to return, some use 'page_limit'.
|
45
|
-
# Pass both to make the code simpler
|
46
|
-
when :box_office, :in_theaters, :opening, :upcoming
|
47
|
-
uri = "#{RT_API_BASE_URL}/lists/movies/#{list_name.to_s}.json?limit=#{result_limit}"\
|
48
|
-
"&page_limit=#{result_limit}&page=1&country=#{country.to_s}&apikey=#{@rt_api_key}"
|
49
|
-
when :top_rentals, :current_releases, :new_releases, :upcoming_dvd
|
50
|
-
|
51
|
-
# The API endpoint uses 'upcoming' for both DVD and cinema releases
|
52
|
-
# Need to avoid this clash by using ':upcoming_dvd' as possible method param,
|
53
|
-
# but change back when building the URI
|
54
|
-
list_name = :upcoming if list_name == :upcoming_dvd
|
55
|
-
uri = "#{RT_API_BASE_URL}/lists/dvds/#{list_name.to_s}.json?limit=#{result_limit}"\
|
56
|
-
"&page_limit=#{result_limit}&page=1&country=#{country.to_s}&apikey=#{@rt_api_key}"
|
57
|
-
end
|
58
|
-
|
59
|
-
get_movie_list(uri)
|
60
|
-
end
|
61
|
-
|
62
|
-
# Search for movies using a query string. Returns a max of 4 results
|
63
|
-
#
|
64
|
-
# @param movie_title [String] the title of the movie to search for
|
65
|
-
# @param result_limit [Integer] the max number of results to return
|
66
|
-
# @return [Array, false] an array containing hashes represting each movie in the search results, or
|
67
|
-
# false if no results are found.
|
68
|
-
def search_by_title(movie_title, result_limit)
|
69
|
-
uri = "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=#{@rt_api_key}&q=#{CGI.escape(movie_title)}&page_limit=#{result_limit}"
|
70
|
-
|
71
|
-
response = JSON.parse(Typhoeus.get(uri).body)
|
72
|
-
|
73
|
-
if response["total"] == 0
|
74
|
-
return false
|
75
|
-
else
|
76
|
-
# Build the array of movie serach results. Have to use a regexp to extract the Rotten Tomatoes
|
77
|
-
# ID from the movie link since the API does not return it directly.
|
78
|
-
return response["movies"].inject([]) do |movie_list, movie|
|
79
|
-
movie_list << { :title => movie["title"], :rt_id => movie["links"]["self"].match(/\/[0-9]+\./).to_s.gsub(/[\/\.]/, ""), :year => movie["year"].to_s }
|
80
|
-
movie_list
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
|
87
|
-
# Aggregates extra info about @movie that cannot be derived directly from the
|
88
|
-
# Rotten Tomatoes API e.g IMDb/Metacritic rating, HQ posters
|
89
|
-
#
|
90
|
-
# @return [Movie] the movie with aggregated info completed
|
91
|
-
def aggregate
|
92
|
-
retrieve_imdb_info
|
93
|
-
retrieve_metacritic_info
|
94
|
-
get_poster
|
95
|
-
get_reviews
|
96
|
-
return @movie
|
97
|
-
end
|
98
|
-
|
99
|
-
# Retrieves and updates the current movie's IMDb rating
|
100
|
-
def retrieve_imdb_info
|
101
|
-
omdb_response = JSON.parse(Typhoeus.get("http://www.omdbapi.com/?i=tt#{@movie.imdb_id}").body)
|
102
|
-
|
103
|
-
if omdb_response["Response"] == "True"
|
104
|
-
if omdb_response["imdbRating"] == "N/A"
|
105
|
-
scrape_imdb_rating
|
106
|
-
else
|
107
|
-
@movie.imdb_rating = omdb_response["imdbRating"]
|
108
|
-
end
|
109
|
-
else
|
110
|
-
@movie.imdb_rating = "Unavailable"
|
111
|
-
end
|
112
|
-
end
|
113
17
|
|
114
|
-
|
115
|
-
|
116
|
-
metacritic_page = Nokogiri::HTML(Typhoeus.get("http://www.metacritic.com/search/"\
|
117
|
-
"movie/#{CGI.escape(@movie.title)}/results").body)
|
18
|
+
# Get the basic movie info first using the RottenTomatoes API
|
19
|
+
movie = RottenTomatoes::MovieInfoFetcher.new(rt_api_key).fetch_info(rt_id)
|
118
20
|
|
119
|
-
|
120
|
-
metacritic_url = "http://www.metacritic.com#{metacritic_page.at_css('.first_result a').attr(:href)}"
|
21
|
+
raise(InsufficientDataError, "No IMDb ID present, can't aggregate") if movie.imdb_id == nil
|
121
22
|
|
122
|
-
|
123
|
-
if scraped_rating == ""
|
124
|
-
scraped_rating = "No Rating"
|
125
|
-
metacritic_url = "No URL"
|
126
|
-
end
|
127
|
-
|
128
|
-
@movie.metacritic_rating = scraped_rating
|
129
|
-
@movie.metacritic_url = metacritic_url
|
130
|
-
end
|
131
|
-
|
132
|
-
# Scrapes and sets the IMDb rating of the current movie from its IMDb page
|
133
|
-
def scrape_imdb_rating
|
134
|
-
imdb_url = "http://m.imdb.com/title/tt#{@movie.imdb_id}/"
|
135
|
-
|
136
|
-
imdb_page = Nokogiri::HTML(Typhoeus.get(imdb_url).body)
|
137
|
-
|
138
|
-
@movie.imdb_rating = imdb_page.xpath("//*[@class = 'mobile-sprite yellow-star']").first.next_element.text.match(/[0-9]\.[0-9]/).to_s.to_f
|
139
|
-
end
|
140
|
-
|
141
|
-
# Updates the current movie's high resolution poster URL
|
142
|
-
def get_poster
|
143
|
-
uri = "#{TMDB_API_BASE_URL}/movie/tt#{@movie.imdb_id}?api_key=#{tmdb_api_key}"
|
144
|
-
movie_info = JSON.parse(Typhoeus.get(uri).body)
|
145
|
-
|
146
|
-
if movie_info.has_key?("poster_path")
|
147
|
-
@movie.poster = "http://cf2.imgobject.com/t/p/original" + movie_info["poster_path"]
|
148
|
-
else
|
149
|
-
@movie.poster = "No poster available"
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
# Retrieves and updates the current movie's reviews
|
154
|
-
def get_reviews
|
155
|
-
uri = "#{RT_API_BASE_URL}/movies/#{@movie.rt_id}/reviews.json?review_type=top_critic"\
|
156
|
-
"&page_limit=5&page=1&country=uk&apikey=#{@rt_api_key}"
|
157
|
-
review_hash = JSON.parse(Typhoeus.get(uri).body)
|
158
|
-
|
159
|
-
review_list = []
|
160
|
-
|
161
|
-
review_hash["reviews"].each do |review|
|
162
|
-
review_list << WrittenReview.new(review)
|
163
|
-
end
|
164
|
-
|
165
|
-
@movie.reviews = review_list
|
166
|
-
end
|
167
|
-
|
168
|
-
# Checks that a given movie has enough information available via API to aggregate
|
169
|
-
# data. It MUST have an IMDb id and a release date.
|
170
|
-
#
|
171
|
-
# @param [Hash] the hash representation of the movie to check
|
172
|
-
# @return [Boolean] whether the movie has a theater release date and IMDb ID
|
173
|
-
def enough_info?(movie)
|
174
|
-
|
175
|
-
has_release_date = false
|
176
|
-
has_imdb_id = false
|
177
|
-
|
178
|
-
if movie.has_key?("release_dates")
|
179
|
-
if movie["release_dates"].has_key?("theater")
|
180
|
-
has_release_date = !movie["release_dates"]["theater"].empty?
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
# Check IMDb ID is present
|
185
|
-
if movie.has_key?("alternate_ids")
|
186
|
-
if movie["alternate_ids"].has_key?("imdb")
|
187
|
-
has_imdb_id = !movie["alternate_ids"]["imdb"].empty?
|
188
|
-
end
|
189
|
-
end
|
190
|
-
return has_release_date && has_imdb_id
|
191
|
-
end
|
192
|
-
|
193
|
-
# Retrieves a list of movies from the Rotten Tomatoes API, then aggregates
|
194
|
-
# info for each one
|
195
|
-
#
|
196
|
-
# @param uri [String] the Rotten Tomatoes API endpoint for the list
|
197
|
-
# @return [Array] an array of Movie objects
|
198
|
-
def get_movie_list(uri)
|
199
|
-
response = JSON.parse(Typhoeus.get(uri).body)
|
200
|
-
movie_list_response = response["movies"]
|
23
|
+
movie.imdb_rating = IMDB::RatingFetcher.fetch(movie.imdb_id)
|
201
24
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
end
|
25
|
+
metacritic_info = Metacritic::RatingFetcher.fetch(movie.title)
|
26
|
+
movie.metacritic_rating = metacritic_info[:metacritic_rating]
|
27
|
+
movie.metacritic_url = metacritic_info[:metacritic_url]
|
206
28
|
|
207
|
-
|
29
|
+
movie.poster = TMDB::PosterFetcher.new(@tmdb_api_key).fetch(movie.imdb_id)
|
30
|
+
movie.reviews = ReviewsFetcher.new(@rt_api_key).fetch(movie.rt_id)
|
31
|
+
@movie = movie
|
208
32
|
end
|
209
33
|
end
|
210
34
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'typhoeus'
|
2
|
+
require 'json'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module WorthWatching
|
6
|
+
module IMDB
|
7
|
+
class RatingFetcher
|
8
|
+
|
9
|
+
# Fetches movie info of a single movie using the Rotten Tomatoes API,
|
10
|
+
# and returns a Movie object
|
11
|
+
def self.fetch(imdb_id)
|
12
|
+
omdb_response = JSON.parse(Typhoeus.get("http://www.omdbapi.com/?i=tt#{imdb_id}").body)
|
13
|
+
|
14
|
+
if omdb_response["Response"] == "True"
|
15
|
+
if omdb_response["imdbRating"] == "N/A"
|
16
|
+
scrape_imdb_rating(imdb_id)
|
17
|
+
else
|
18
|
+
imdb_rating = omdb_response["imdbRating"].to_f
|
19
|
+
end
|
20
|
+
else
|
21
|
+
imdb_rating = "Unavailable"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Scrapes and sets the IMDb rating of the current movie from its IMDb page
|
28
|
+
def self.scrape_imdb_rating(imdb_id)
|
29
|
+
imdb_url = "http://m.imdb.com/title/tt#{imdb_id}/"
|
30
|
+
|
31
|
+
imdb_page = Nokogiri::HTML(Typhoeus.get(imdb_url).body)
|
32
|
+
|
33
|
+
imdb_page.xpath("//*[@class = 'mobile-sprite yellow-star']").first.next_element.text.match(/[0-9]\.[0-9]/).to_s.to_f
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'typhoeus'
|
2
|
+
require 'nokogiri'
|
3
|
+
require 'cgi'
|
4
|
+
|
5
|
+
module WorthWatching
|
6
|
+
module Metacritic
|
7
|
+
class RatingFetcher
|
8
|
+
|
9
|
+
# Fetches movie info of a single movie using the Rotten Tomatoes API,
|
10
|
+
# and returns a Movie object
|
11
|
+
def self.fetch(movie_title)
|
12
|
+
metacritic_page = Nokogiri::HTML(Typhoeus.get("http://www.metacritic.com/search/"\
|
13
|
+
"movie/#{CGI.escape(movie_title)}/results").body)
|
14
|
+
|
15
|
+
scraped_rating = metacritic_page.css('.first_result .metascore_w').text.to_i
|
16
|
+
metacritic_url = "http://www.metacritic.com#{metacritic_page.at_css('.first_result a').attr(:href)}"
|
17
|
+
|
18
|
+
# If attempt to scrape results in empty string, info must not be available
|
19
|
+
if scraped_rating == ""
|
20
|
+
scraped_rating = "No Rating"
|
21
|
+
metacritic_url = "No URL"
|
22
|
+
end
|
23
|
+
|
24
|
+
{ metacritic_rating: scraped_rating, metacritic_url: metacritic_url }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/worth_watching/movie.rb
CHANGED
@@ -1,24 +1,21 @@
|
|
1
|
-
require 'date'
|
2
|
-
|
3
1
|
module WorthWatching
|
4
2
|
class Movie
|
5
3
|
attr_accessor :title, :plot, :director, :genre, :rt_rating, :rt_url, :cast,
|
6
4
|
:imdb_rating, :imdb_url, :metacritic_rating, :metacritic_url,
|
7
5
|
:release_date, :poster, :rt_id, :imdb_id, :reviews
|
8
6
|
|
9
|
-
def initialize(
|
10
|
-
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@
|
14
|
-
@
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@
|
19
|
-
@
|
20
|
-
@
|
21
|
-
@rt_id = movie_params['id'].to_s
|
7
|
+
def initialize(movie_args)
|
8
|
+
@title = movie_args[:title]
|
9
|
+
@plot = movie_args[:plot]
|
10
|
+
@director = movie_args[:director]
|
11
|
+
@genre = movie_args[:genre]
|
12
|
+
@rt_rating = movie_args[:rt_rating]
|
13
|
+
@rt_url = movie_args[:rt_url]
|
14
|
+
@cast = movie_args[:cast]
|
15
|
+
@imdb_id = movie_args[:imdb_id]
|
16
|
+
@imdb_url = movie_args[:imdb_url]
|
17
|
+
@release_date = movie_args[:release_date]
|
18
|
+
@rt_id = movie_args[:rt_id]
|
22
19
|
|
23
20
|
@imdb_rating = "Not retrieved"
|
24
21
|
@metacritic_rating = "Not retrieved"
|
@@ -29,26 +26,14 @@ module WorthWatching
|
|
29
26
|
# @return [String] the summary
|
30
27
|
def summary
|
31
28
|
divider = "-" * 60
|
32
|
-
"#{divider}\n#{
|
29
|
+
"#{divider}\n#{title}\n#{divider}\nReleased: " +
|
30
|
+
"#{release_date.strftime("%d %b %Y")}\n#{divider}\n#{plot}\n#{divider}" +
|
31
|
+
"\nCast: #{cast}\n#{divider}\n#{rating_summary}\n"
|
33
32
|
end
|
34
33
|
|
35
34
|
def rating_summary
|
36
|
-
"Rotten Tomatoes rating: #{rt_rating}\nIMDB rating: #{imdb_rating}\
|
37
|
-
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
# Builds a cast list string from an array of actor names (up to 4 actors)
|
42
|
-
#
|
43
|
-
# @param cast [Array] the array of actor names
|
44
|
-
# @return [String] a string of actor names separated by commas
|
45
|
-
def build_cast_list(cast)
|
46
|
-
cast_list = cast[0..3].inject("") do |cast_list_string, actor, i|
|
47
|
-
cast_list_string << "#{actor["name"]}, "
|
48
|
-
end
|
49
|
-
|
50
|
-
# Remove the trailing comma
|
51
|
-
cast_list.sub(/, \z/, "")
|
35
|
+
"Rotten Tomatoes rating: #{rt_rating}\nIMDB rating: #{imdb_rating}\n" +
|
36
|
+
"Metacritic rating: #{metacritic_rating}\n"
|
52
37
|
end
|
53
38
|
end
|
54
39
|
end
|