Ticket #6219: imdb_script5.patch

File imdb_script5.patch, 12.2 KB (added by jyavenard@…, 12 years ago)

Using new Python bindings, properly fill genres, cast and country

  • imdbpy.py

     
    159159        movies = []
    160160        for m in sorted_movies:
    161161                try:
    162                         movies.append([imdb_access.get_imdbID(m), m['title'], int(m['year'])])
     162                        item = [imdb_access.get_imdbID(m), m['title'], int(m['year'])]
    163163                except KeyError:
    164                         movies.append([imdb_access.get_imdbID(m), m['title'], 1901])
    165                 movies.append([imdb_access.get_imdbID(m), m['title'], int(m['year'])])
     164                        item = [imdb_access.get_imdbID(m), m['title'], 1901]
     165                movies.append(item)
    166166        return movies
    167167
    168168def find_poster_url(imdb_id):
     
    327327                shortest_found = None
    328328                #print "%d plots found" % len(plots)
    329329                for plot in plots:
    330                         text = plot.split("::")[1]
     330                        #IMDbPY 3.9 doesn't order the content of plot like earlier version of IMDbPY.
     331                        # IMDB 3.6 is : plot_content::author
     332                        # IMDB 3.9 is : author::plot_content
     333                        #So we assume that should one side longer than the other, it's actually where the description is
     334                        splitvalue = plot.split("::")
     335                        if len(splitvalue[0]) > len(splitvalue[1]):
     336                                text = splitvalue[0]
     337                        else:
     338                                text = splitvalue[1]
    331339                        if shortest_found == None or len(text) < len(shortest_found):
    332340                                shortest_found = text
    333341                metadata.plot = shortest_found
     
    397405
    398406        if options.movie_search is not None:
    399407                results = title_search(options.movie_search.decode("utf8"))
    400                 for result in results:
    401                         print "%s:%s (%d)" % (result[0], result[1], result[2])
     408                if results:
     409                        for result in results:
     410                                print "%s:%s (%d)" % (result[0], result[1], result[2])
    402411        elif options.poster_search is not None:
    403412                poster_search(options.poster_search)
    404413        elif options.metadata_search is not None:
  • fetch_poster.py

     
    4646http://www.pythonware.com/products/pil/"""
    4747        imaging_library = False
    4848
     49#Number of default IMDb retry
     50import time
     51defaultretries=3
     52
     53def functionretry(func, arg1, arg2=None, retries=None):
     54        global defaultretries
     55       
     56        if retries == None:
     57                retries = defaultretries
     58       
     59        attempts = 0
     60        stop = False
     61        while (not stop):
     62                try:
     63                        if arg2:
     64                                result = func(arg1, arg2)
     65                        else:
     66                                result = func(arg1)                             
     67                        stop = True
     68                except:
     69                        result = None
     70                if not stop:
     71                        attempts += 1
     72                        if attempts > retries:
     73                                stop = True
     74                        if attempts <= retries:
     75                                print 'Failed to retrieve data, retry in 5s'
     76                                time.sleep(5)
     77                       
     78        if attempts > retries:
     79                print 'Error retrieving data : No more attempts'
     80        return result
     81
    4982class PosterImage:
    5083        """
    5184        Holds a single poster image.
     
    104137                max_results = 4
    105138                images = []
    106139               
    107                 for url in poster_urls:
    108                         image_url = self.find_poster_image_url(url)
    109                         if image_url is not None:
    110                                 images.append(self.download_image(image_url, ".jpg"))
    111                                 results += 1
    112                         if results >= max_results:
    113                                 break
     140                if poster_urls:
     141                        for url in poster_urls:
     142                                image_url = self.find_poster_image_url(url)
     143                                if image_url is not None:
     144                                        images.append(self.download_image(image_url, ".jpg"))
     145                                        results += 1
     146                                if results >= max_results:
     147                                        break
    114148                return images
    115149                               
    116150        def find_poster_image_url(self, poster_page_url):
     
    196230                        return [self.download_image(poster_url, extension)]
    197231                return []
    198232                       
    199 def find_best_posters(title, count=1, accept_horizontal=False, imdb_id=None):
     233def find_best_posters(title, count=1, accept_horizontal=False, imdb_id=None, retries=None):
    200234               
    201235        fetchers = [MoviePosterPosterFetcher(), IMDbPosterFetcher()]
    202236        #fetchers = [IMDbPosterFetcher()]       
     
    218252                        break
    219253               
    220254        for fetcher in fetchers:
    221                 new_posters = fetcher.fetch(title, imdb_id)
    222                 for poster in new_posters:
    223                         if not accept_horizontal and not poster.is_vertical():
    224                                 os.remove(poster.file_name)
    225                                 continue
    226                         posters.append(poster)
     255                new_posters = functionretry(fetcher.fetch, title, arg2=imdb_id, retries=retries)
     256                if new_posters:
     257                        for poster in new_posters:
     258                                if not accept_horizontal and not poster.is_vertical():
     259                                        os.remove(poster.file_name)
     260                                        continue
     261                                posters.append(poster)
    227262               
    228263        def size_cmp(a, b):
    229264                return cmp(a.pixels(), b.pixels())
     
    237272        return posters[0:count]
    238273               
    239274def main():
     275        global defaultretries
    240276       
    241        
    242277        p = optparse.OptionParser()
    243278        p.add_option('--number', '-n', action="store", type="int", default=1,
    244279                help="the count of biggest posters to get")
     
    247282        p.add_option('--poster_search', '-P', metavar='IMDB_ID', default=None, dest="imdb_id",
    248283                help="Displays a list of URL's to movie posters.  The lines are "\
    249284                "ranked by descending value. For MythVideo.")           
     285        p.add_option('--retry', '-t', action="store", type="int", dest="retries",default=3,
     286                help="Number of retries, 0 means no retry [default 3]")
    250287               
    251288        options, arguments = p.parse_args()
    252289       
     290        defaultretries = options.retries
     291
    253292        title = ""
    254293        if len(arguments) != 1:
    255294                if options.imdb_id:
    256295                        # TODO: Fetch the title from IMDb.
    257                         metadata = imdbpy.metadata_search(options.imdb_id)
    258                         title = imdbpy.parse_meta(metadata, "Title")
     296                        metadata = functionretry(imdbpy.metadata_search,options.imdb_id)
     297                        if metadata:
     298                                title = imdbpy.parse_meta(metadata, "Title")
     299                        else:
     300                                print "Error can't retrieve title from IMDb"
     301                                sys.exit(1)                             
    259302                else:
    260303                        print "Please give a video title as argument."
    261304                        sys.exit(1)                             
     
    263306                title = arguments[0]
    264307               
    265308        posters = find_best_posters(title, options.number, options.all,
    266                                 imdb_id=options.imdb_id)       
     309                                imdb_id=options.imdb_id, retries=defaultretries)       
    267310       
    268311        if options.imdb_id is not None:
    269312                for poster in posters:
     
    276319               
    277320if __name__ == '__main__':
    278321        main()         
    279        
    280  No newline at end of file
     322       
  • find_meta.py

     
    102102# MythTV settings table).
    103103poster_dir = "./"
    104104
     105#Number of default IMDb retry
     106import time
     107defaultretries=3
     108
     109def functionretry(func, arg1, arg2=None, retries=None):
     110        global defaultretries
     111       
     112        if retries == None:
     113                retries = defaultretries
     114       
     115        attempts = 0
     116        stop = False
     117        while (not stop):
     118                try:
     119                        if arg2:
     120                                result = func(arg1, arg2)
     121                        else:
     122                                result = func(arg1)                             
     123                        stop = True
     124                except:
     125                        result = None
     126                if not stop:
     127                        attempts += 1
     128                        if attempts > retries:
     129                                stop = True
     130                        if attempts <= retries:
     131                                print_verbose ('Failed to retrieve data, retry in 5s')
     132                                time.sleep(5)
     133                       
     134        if attempts > retries:
     135                print_verbose ('Error retrieving data : No more attempts')
     136        return result
     137
    105138def print_verbose(string):
    106139        global verbose
    107140        if verbose:
     
    153186                        lowest_cutpoint = pos
    154187
    155188        title = title[0:lowest_cutpoint]
     189        # Remove trailing year in the form of "name [year]" or "name (year)" if any
     190        m = re.compile(r"(.*)([\(\[]([0-9]+)[\]\)])$")
     191        found = m.match(title.strip())
     192        if found:
     193                title = found.group(1)
    156194        return title.strip()
    157195
    158196def parse_meta(variable, oldvalue, emptyvalue="", meta=""):
     
    347385                                        title = aka_title + " (" + title + ")"
    348386                                        print_verbose("Found AKA: %s" % title)
    349387                                break
     388                        # For IMDbPY >= 3.9
     389                        # Grill Point::(International: English title)
     390                        # Catastrofi d'amore::(Italy) [it]
     391                        akaRegexp = ".+::\(.+\) \[%s\].*" % aka_language
     392                        m = re.match(akaRegexp, aka)
     393                        if m is not None:
     394                                aka_title = aka.split("::")[0]
     395                                if aka_title != title:
     396                                        title = aka_title + " (" + title + ")"
     397                                        print_verbose("Found AKA: %s" % title)
     398                                break
    350399
    351400        if disc is not None:
    352401                title += " [disc" + unicode(disc) + "]"
     
    400449        if genrestring is not None and len(genrestring) > 0:
    401450                genres = genrestring.split(",")
    402451
     452        #Always set category to "Unknown", until we can identify what it really is
     453        category = mythvideo.getGenreId("Unknown")
    403454        if len(genres) < 1:
    404455                print_verbose("No genres.")
    405                 category = mythvideo.getGenreId("Unknown")
    406456        else:
    407                 # Only one genre supported?
    408                 category = mythvideo.getGenreId(genres[0])
     457                #Remove previous genres
     458                mythvideo.cleanGenres(intid)
     459                #Set all the genres
     460                for genre in genres:
     461                        mythvideo.setGenres(genre.strip(), intid)
    409462
     463        countrystring = parse_metadata('Countries', "", "")
     464        countries = []
     465        if countrystring is not None and len(countrystring) > 0:
     466                countries = countrystring.split(",")
     467
     468        #Always set category to "Unknown", until we can identify what it really is
     469        if len(countries) < 1:
     470                print_verbose("No countries.")
     471        else:
     472                #Remove previous genres
     473                mythvideo.cleanCountry(intid)
     474                #Set all the countries
     475                for country in countries:
     476                        mythvideo.setCountry(country.strip(), intid)
     477
     478        caststring = parse_metadata('Cast', "", "")
     479        cast = []
     480        if caststring is not None and len(caststring) > 0:
     481                cast = caststring.split(",")
     482
     483        #Always set category to "Unknown", until we can identify what it really is
     484        if len(cast) < 1:
     485                print_verbose("No cast.")
     486        else:
     487                #Remove previous cast
     488                mythvideo.cleanCast(intid)
     489                #Set all the cast
     490                for actor in cast:
     491                        mythvideo.setCast(actor.strip(), intid)
     492
    410493        if coverfile == None:
    411494                coverfile = "No cover"
    412495
     
    427510        otherwise returns the base name of the poster image file.
    428511        """
    429512        global poster_dir,overwrite
     513        global defaultretries
    430514        image_extensions = ["png", "jpg", "bmp"]
    431515
    432516        poster_files = []
     
    436520        if len(poster_files) == 0 or overwrite:
    437521                # Try to fetch the poster image from the web.
    438522                posters = fetch_poster.find_best_posters(\
    439                         title, count=1, accept_horizontal=True, imdb_id=imdb_id)
     523                        title, count=1, accept_horizontal=True, imdb_id=imdb_id,retries=defaultretries)
    440524
    441525                if len(posters) == 0:
    442526                        return None
     
    528612
    529613                print_verbose("Title search '%s'" % title)
    530614
    531                 candidates = imdbpy.title_search(title)
     615                candidates = functionretry(imdbpy.title_search, title)
     616                       
    532617                if candidates is None or len(candidates) == 0:
    533618                        # TODO: Try with the dirname
    534619                        pass
     
    560645
    561646        print_verbose("Querying IMDb for meta data for ID %s..." % imdb_id)
    562647        try:
    563                 meta = imdbpy.fetch_metadata(imdb_id)
     648                meta = functionretry(imdbpy.fetch_metadata,imdb_id)
    564649                if meta is not None:
    565650                        if meta.series_episode:
    566651                                title, season, episode = imdbpy.detect_series_title(title)
     
    708793                metadata = load_metadata_file(metadata_target)
    709794
    710795        if imdb_id is not None:
    711                 meta = imdbpy.fetch_metadata(imdb_id)
     796                meta = functionretry(imdbpy.fetch_metadata,imdb_id)
    712797                if meta.series_episode:
    713798                        fileName = os.path.basename(pathName)
    714799                        t, season, episode = imdbpy.detect_series_title(fileName)
     
    734819                return
    735820
    736821        if imdb_id is not None:
    737                 metadata = imdbpy.metadata_search(imdb_id)
     822                metadata = functionretry(imdbpy.metadata_search,imdb_id)
     823
    738824                if metadata is not None:
    739825                        metadata += "IMDb:%s" % imdb_id + "\n"
    740826                        save_metadata(dirName, dirName + "/video.metadata", metadata)
     
    815901        global verbose, overwrite, interactive, recursive, dbimport
    816902        global import_from_files, metafiles, poster_dir, poster_search
    817903        global aka_language
     904        global defaultretries
    818905
    819906        usage = "usage: %prog [options] videopath1 [videopath2 videopath3...]"
    820907
     
    831918                help="Traverse sub directories of the given directory recursively.")
    832919
    833920        p.add_option('--no_dbimport', '-n', action="store_true", default=False,
    834                 help="Do not import metadata directly to MythDB.")
     921                help="Do not import      metadata directly to MythDB.")
    835922        p.add_option('--fromfiles', '-f', action="store_true", default=False,
    836923                help="Import data to MythDB from .metadata files if found. Requires -d.")
    837924        p.add_option('--metafiles', '-m', action="store_true", default=False,
     
    848935                default=None,
    849936                help="Add the title name in the given country (two letter code, e.g., 'fi') "\
    850937                "to the movie title.")
     938        p.add_option('--retry', '-t', action="store", type="int", dest="retries",default=3,
     939                help="Number of retries, 0 means no retry [default 3]")
    851940
    852941        options, arguments = p.parse_args()
    853942
     
    865954        prune = options.prune
    866955        poster_search = not options.skip_poster_search
    867956        aka_language = options.lang_code
     957       
     958        defaultretries = options.retries
    868959
    869960        if not (metafiles or dbimport):
    870961                print "You must define writing to either MythDB import (-d) or metadata files (-m)."