diff --git a/youtube_dl/YoutubeDL.py b/youtube_dl/YoutubeDL.py index a7bf5a1b0..26f3db79e 100755 --- a/youtube_dl/YoutubeDL.py +++ b/youtube_dl/YoutubeDL.py @@ -163,6 +163,8 @@ class YoutubeDL(object): playlistrandom: Download playlist items in random order. matchtitle: Download only matching titles. rejecttitle: Reject downloads for matching titles. + matchuploader: Download only matchin uploader. + rejectuploader: Reject downloads for matching uploader. logger: Log messages to a logging.Logger instance. logtostderr: Log messages to stderr instead of stdout. writedescription: Write the video description to a .description file @@ -620,7 +622,7 @@ class YoutubeDL(object): return None def _match_entry(self, info_dict, incomplete): - """ Returns None iff the file should be downloaded """ + """ Returns None if the file should be downloaded """ video_title = info_dict.get('title', info_dict.get('id', 'video')) if 'title' in info_dict: @@ -634,11 +636,25 @@ class YoutubeDL(object): if rejecttitle: if re.search(rejecttitle, title, re.IGNORECASE): return '"' + title + '" title matched reject pattern "' + rejecttitle + '"' + + if 'uploader' in info_dict: + # This can happen when we're just evaluating the playlist + uploader = info_dict['uploader'] + matchuploader = self.params.get('matchuploader', False) + if matchuploader: + if not re.search(matchuploader, uploader, re.IGNORECASE): + return '"' + uploader + '" uploader did not match pattern "' + matchuploader + '"' + rejectuploader = self.params.get('rejectuploader', False) + if rejectuploader: + if re.search(rejectuploader, uploader, re.IGNORECASE): + return '"' + uploader + '" uploader matched reject pattern "' + rejectuploader + '"' + date = info_dict.get('upload_date') if date is not None: dateRange = self.params.get('daterange', DateRange()) if date not in dateRange: return '%s upload date is not in range %s' % (date_from_str(date).isoformat(), dateRange) + view_count = info_dict.get('view_count') if view_count is not None: min_views = self.params.get('min_views') @@ -647,8 +663,10 @@ class YoutubeDL(object): max_views = self.params.get('max_views') if max_views is not None and view_count > max_views: return 'Skipping %s, because it has exceeded the maximum view count (%d/%d)' % (video_title, view_count, max_views) + if age_restricted(info_dict.get('age_limit'), self.params.get('age_limit')): return 'Skipping "%s" because it is age restricted' % video_title + if self.in_download_archive(info_dict): return '%s has already been recorded in archive' % video_title diff --git a/youtube_dl/__init__.py b/youtube_dl/__init__.py index 5c5b8094b..6f1571319 100644 --- a/youtube_dl/__init__.py +++ b/youtube_dl/__init__.py @@ -363,6 +363,8 @@ def _real_main(argv=None): 'subtitleslangs': opts.subtitleslangs, 'matchtitle': decodeOption(opts.matchtitle), 'rejecttitle': decodeOption(opts.rejecttitle), + 'matchuploader': decodeOption(opts.matchuploader), + 'rejectuploader': decodeOption(opts.rejectuploader), 'max_downloads': opts.max_downloads, 'prefer_free_formats': opts.prefer_free_formats, 'verbose': opts.verbose, diff --git a/youtube_dl/options.py b/youtube_dl/options.py index 349f44778..27982a80d 100644 --- a/youtube_dl/options.py +++ b/youtube_dl/options.py @@ -261,6 +261,14 @@ def parseOpts(overrideArguments=None): '--reject-title', dest='rejecttitle', metavar='REGEX', help='Skip download for matching titles (regex or caseless sub-string)') + selection.add_option( + '--match-uploader', + dest='matchuploader', metavar='REGEX', + help='Download only matching uploader (regex or caseless sub-string)') + selection.add_option( + '--reject-uploader', + dest='rejectuploader', metavar='REGEX', + help='Skip download for matching uploader (regex or caseless sub-string)') selection.add_option( '--max-downloads', dest='max_downloads', metavar='NUMBER', type=int, default=None,