class Spotlite::Movie

Represents a movie on IMDb.com

Attributes

imdb_id[RW]
response[RW]
url[RW]

Public Class Methods

find(query) click to toggle source

Returns a list of movies as an array of Spotlite::Movie objects Takes single parameter and searches for movies by title and alternative titles

# File lib/spotlite/movie.rb, line 24
def self.find(query)
  results = Spotlite::Client.get(
    'http://www.imdb.com/find', query: { q: query, s: 'tt', ttype: 'ft' }
  )
  results.css('.result_text').map do |result|
    imdb_id = result.at('a')['href'].parse_imdb_id
    title   = result.at('a').text.strip
    year    = result.children.take(3).last.text.parse_year

    [imdb_id, title, year]
  end.map do |values|
    self.new(*values)
  end
end
new(imdb_id, title = nil, year = nil) click to toggle source

Initialize a new movie object by its IMDb ID as a string

movie = Spotlite::Movie.new('0133093')

Spotlite::Movie class objects are lazy loading. No HTTP request will be performed upon object initialization. HTTP request will be performed once when you use a method that needs remote data Currently, all data is spread across 6 pages: main movie page, /releaseinfo, /fullcredits, /keywords, /trivia, and /criticreviews

# File lib/spotlite/movie.rb, line 15
def initialize(imdb_id, title = nil, year = nil)
  @imdb_id = "%07d" % imdb_id.to_i
  @title   = title
  @year    = year
  @url     = "http://www.imdb.com/title/tt#{@imdb_id}/"
end

Public Instance Methods

alternative_titles() click to toggle source

Returns a list of movie alternative titles as an array of hashes with keys title (string) and comment (string)

# File lib/spotlite/movie.rb, line 195
def alternative_titles
  array = []
  release_info.css('#akas').css('tr').map do |row|
    cells = row.css('td')
    array << { :title => cells.last.text.strip, :comment => cells.first.text.strip }
  end

  array
end
cast() click to toggle source

Returns a list of actors as an array Spotlite::Person objects

# File lib/spotlite/movie.rb, line 233
def cast
  full_credits.css('table.cast_list tr').reject do |row|
    # Skip 'Rest of cast' row
    row.children.size == 1
  end.map do |row|
    imdb_id = row.at('td:nth-child(2) a')['href'].parse_imdb_id
    name = row.at('td:nth-child(2) a').text.strip_whitespace
    credits_text = row.last_element_child.text.strip_whitespace

    [imdb_id, name, 'Cast', credits_text]
  end.map do |values|
    Spotlite::Person.new(*values)
  end
end
content_rating() click to toggle source

Returns content rating as a string

# File lib/spotlite/movie.rb, line 113
def content_rating
  details.at("div.subtext meta[itemprop='contentRating']")['content'] rescue nil
end
countries() click to toggle source

Returns a list of countries as an array of hashes with keys: code (string) and name (string)

# File lib/spotlite/movie.rb, line 124
def countries
  array = []
  details.css("div.txt-block a[href^='/country/']").each do |node|
    array << {:code => node['href'].clean_href, :name => node.text.strip}
  end

  array
end
credits() click to toggle source

Returns combined `cast` and `crew` as an array of Spotlite::Person objects

# File lib/spotlite/movie.rb, line 275
def credits
  cast + crew
end
crew() click to toggle source

Combines all crew categories and returns an array of Spotlite::Person objects

# File lib/spotlite/movie.rb, line 270
def crew
  crew_categories.map{ |category| parse_crew(category) }.flatten
end
crew_categories() click to toggle source

Returns available crew categories, e.g. “Art Department”, “Writing Credits”, or “Stunts”, as an array of strings

# File lib/spotlite/movie.rb, line 280
def crew_categories
  array = []
  full_credits.css('h4.dataHeaderWithBorder').reject{ |h| h['id'] == 'cast' }.map do |node|
    array << (node.children.size > 1 ? node.children.first.text.strip_whitespace : node.children.text.strip_whitespace)
  end

  array
end
critic_reviews() click to toggle source

Returns a list of critic reviews as an array of hashes with keys: source (string), author (string), excerpt (string), and score (integer)

# File lib/spotlite/movie.rb, line 318
def critic_reviews
  array = []
  reviews.css("tr[itemprop='reviews']").map do |review|
    source = review.at("b[itemprop='publisher'] span[itemprop='name']").text
    author = review.at("span[itemprop='author'] span[itemprop='name']").text
    url = review.at("a[itemprop='url']")['href'] rescue nil
    excerpt = review.at("div[itemprop='reviewbody']").text.strip
    score = review.at("span[itemprop='ratingValue']").text.to_i

    array << {
      source: source.empty? ? nil : source,
      author: author.empty? ? nil : author,
      url: url,
      excerpt: excerpt,
      score: score
    }
  end

  array
end
description() click to toggle source

Returns short description as a string

# File lib/spotlite/movie.rb, line 97
def description
  desc = details.at("div.summary_text[itemprop='description']").text.strip.clean_description rescue nil
  (desc.nil? || desc.empty?) ? nil : desc
end
directors() click to toggle source

Returns a list of directors as an array of Spotlite::Person objects

# File lib/spotlite/movie.rb, line 206
def directors
  parse_crew('Directed by')
end
genres() click to toggle source

Returns a list of genres as an array of strings

# File lib/spotlite/movie.rb, line 118
def genres
  details.css("div.subtext a[href^='/genre/']").map { |genre| genre.text } rescue []
end
images() click to toggle source

Returns URLs of movie still frames as an array of strings

# File lib/spotlite/movie.rb, line 340
def images
  array = []
  still_frames.css('#media_index_thumbnail_grid img').map do |image|
    src = image['src'] rescue nil

    if src =~ /^(http:.+@@)/ || src =~ /^(http:.+?)\.[^\/]+$/
      array << $1 + '.jpg'
    end
  end

  array
end
keywords() click to toggle source

Returns a list of keywords as an array of strings

# File lib/spotlite/movie.rb, line 179
def keywords
  plot_keywords.css("a[href^='/keyword/']").map { |keyword| keyword.text.strip } rescue []
end
languages() click to toggle source

Returns a list of languages as an array of hashes with keys: code (string) and name (string)

# File lib/spotlite/movie.rb, line 135
def languages
  array = []
  details.css("div.txt-block a[href^='/language/']").each do |node|
    array << {:code => node['href'].clean_href, :name => node.text.strip}
  end

  array
end
metascore() click to toggle source

Returns Metascore rating as an integer

# File lib/spotlite/movie.rb, line 87
def metascore
  details.at("div.titleReviewBar a[href^=criticreviews] span").text.to_i rescue nil
end
original_title() click to toggle source

Returns original non-english title as a string

# File lib/spotlite/movie.rb, line 72
def original_title
  details.at("div.originalTitle").children.first.text.gsub('"', '').strip rescue nil
end
parse_crew(category) click to toggle source

Returns a list of crew members of a certain category as an array Spotlite::Person objects

# File lib/spotlite/movie.rb, line 249
def parse_crew(category)
  table = full_credits.search("[text()^='#{category}']").first.next_element rescue nil
  if table && table.name == 'table'
    table.css('tr').reject do |row|
      # Skip empty table rows with one non-braking space
      row.text.strip.size == 1
    end.map do |row|
      imdb_id = row.first_element_child.at('a')['href'].parse_imdb_id
      name = row.first_element_child.at('a').text.strip_whitespace
      credits_text = row.last_element_child.text.strip_whitespace.clean_credits_text

      [imdb_id, name, category, credits_text]
    end.map do |values|
      Spotlite::Person.new(*values)
    end
  else
    []
  end
end
poster_url() click to toggle source

Returns primary poster URL as a string

# File lib/spotlite/movie.rb, line 150
def poster_url
  src = details.at('div.poster img')['src'] rescue nil

  if src =~ /^(http:.+@@)/ || src =~ /^(http:.+?)\.[^\/]+$/
    $1 + '.jpg'
  end
end
producers() click to toggle source

Returns a list of producers as an array of Spotlite::Person objects

# File lib/spotlite/movie.rb, line 216
def producers
  parse_crew('Produced by')
end
rating() click to toggle source

Returns IMDb rating as a float

# File lib/spotlite/movie.rb, line 82
def rating
  details.at("div.imdbRating span[itemprop='ratingValue']").text.to_f rescue nil
end
release_date() click to toggle source

Returns original release date as a date

# File lib/spotlite/movie.rb, line 312
def release_date
  release_dates.first[:date] rescue nil
end
release_dates() click to toggle source

Returns a list of regions and corresponding release dates as an array of hashes with keys: region code (string), region name (string), date (date), and comment (string) If day is unknown, 1st day of month is assigned If day and month are unknown, 1st of January is assigned

# File lib/spotlite/movie.rb, line 294
def release_dates
  array = []
  table = release_info.at('#release_dates')
  table.css('tr').map do |row|
    cells = row.css('td')
    code = cells.first.at('a')['href'].clean_href.split('=').last.downcase rescue nil
    region = cells.first.at('a').text rescue nil
    date = cells.at('.release_date').text.strip.parse_date
    comment = cells.last.text.strip.clean_release_comment
    comment = nil if comment.empty?

    array << { :code => code, :region => region, :date => date, :comment => comment }
  end unless table.nil?

  array
end
runtime() click to toggle source

Returns runtime (length) in minutes as an integer

# File lib/spotlite/movie.rb, line 145
def runtime
  details.at("div.subtext time[itemprop='duration']")['datetime'].gsub(/[^\d+]/, '').to_i rescue nil
end
stars() click to toggle source

Returns a list of starred actors as an array of Spotlite::Person objects

# File lib/spotlite/movie.rb, line 221
def stars
  details.css("div.plot_summary_wrapper span[itemprop='actors'] a[href^='/name/nm']").map do |node|
    imdb_id = node['href'].parse_imdb_id
    name = node.text.strip

    [imdb_id, name]
  end.map do |values|
    Spotlite::Person.new(*values)
  end
end
storyline() click to toggle source

Returns storyline as a string. Often is the same as description

# File lib/spotlite/movie.rb, line 103
def storyline
  details.at("#titleStoryLine div[itemprop='description'] p").text.strip.clean_description rescue nil
end
summaries() click to toggle source

Returns a list of plot summaries as an array of strings

# File lib/spotlite/movie.rb, line 108
def summaries
  plot_summaries.css("p.plotSummary").map { |summary| summary.text.strip }
end
taglines() click to toggle source

Returns a list of taglines as an array of strings

# File lib/spotlite/movie.rb, line 189
def taglines
  movie_taglines.css("#taglines_content > .soda").map { |node| node.text.clean_tagline }
end
technical() click to toggle source

Returns technical information like film length, aspect ratio, cameras, etc. as a hash of arrays of strings

# File lib/spotlite/movie.rb, line 354
def technical
  hash = {}
  table = technical_info.at_css('#technical_content table') rescue nil

  table.css('tr').map do |row|
    hash[row.css('td').first.text.strip] = row.css('td').last.children.
      map(&:text).
      map(&:strip_whitespace).
      reject(&:empty?).
      reject{|i| i == '|'}.
      slice_before{|i| /^[^\(]/.match i}.
      map{|i| i.join(' ')}
  end unless table.nil?

  hash
end
title() click to toggle source

Returns title as a string

# File lib/spotlite/movie.rb, line 66
def title
  # strip some non-breaking space at the end
  @title ||= details.at("h1[itemprop='name']").children.first.text.strip.gsub(' ', '') rescue nil
end
trivia() click to toggle source

Returns a list of trivia facts as an array of strings

# File lib/spotlite/movie.rb, line 184
def trivia
  movie_trivia.css("div.sodatext").map { |node| node.text.strip } rescue []
end
votes() click to toggle source

Returns number of votes as an integer

# File lib/spotlite/movie.rb, line 92
def votes
  details.at("div.imdbRating span[itemprop='ratingCount']").text.gsub(/[^\d+]/, '').to_i rescue nil
end
writers() click to toggle source

Returns a list of writers as an array of Spotlite::Person objects

# File lib/spotlite/movie.rb, line 211
def writers
  parse_crew('Writing Credits')
end
year() click to toggle source

Returns year of original release as an integer

# File lib/spotlite/movie.rb, line 77
def year
  @year ||= details.at("h1[itemprop='name'] span#titleYear a").text.parse_year rescue nil
end

Private Instance Methods

reviews() click to toggle source
# File lib/spotlite/movie.rb, line 393
def reviews
  @reviews ||= open_page('criticreviews')
end