worth_watching 0.1.5 → 1.0.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 +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
|