本文整理汇总了Python中guessit.containers.PropertiesContainer.register_property方法的典型用法代码示例。如果您正苦于以下问题:Python PropertiesContainer.register_property方法的具体用法?Python PropertiesContainer.register_property怎么用?Python PropertiesContainer.register_property使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类guessit.containers.PropertiesContainer
的用法示例。
在下文中一共展示了PropertiesContainer.register_property方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Python代码示例。
示例1: GuessEpisodeSpecial
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessEpisodeSpecial(Transformer):
def __init__(self):
Transformer.__init__(self, -205)
self.container = PropertiesContainer()
self.container.register_property('special', 'Special', 'Bonus', 'Omake', 'Ova', 'Oav', 'Pilot', 'Unaired')
self.container.register_property('special', 'Extras?', canonical_form='Extras')
def guess_special(self, string, node=None, options=None):
properties = self.container.find_properties(string, node, 'special', multiple=True)
guesses = self.container.as_guess(properties, multiple=True)
return guesses
def second_pass_options(self, mtree, options=None):
if not mtree.guess.get('type', '').startswith('episode'):
for unidentified_leaf in mtree.unidentified_leaves():
properties = self.container.find_properties(unidentified_leaf.value, unidentified_leaf, 'special')
guess = self.container.as_guess(properties)
if guess:
return {'type': 'episode'}
return None
def supported_properties(self):
return self.container.get_supported_properties()
def process(self, mtree, options=None):
if mtree.guess.get('type', '').startswith('episode') and (not mtree.info.get('episodeNumber') or mtree.info.get('season') == 0):
for title_leaf in mtree.leaves_containing('title'):
guesses = self.guess_special(title_leaf.value, title_leaf, options)
for guess in guesses:
found_guess(title_leaf, guess, update_guess=False)
for unidentified_leaf in mtree.unidentified_leaves():
guesses = self.guess_special(unidentified_leaf.value, unidentified_leaf, options)
for guess in guesses:
found_guess(unidentified_leaf, guess, update_guess=False)
return None
示例2: guess_regexps_id
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
def guess_regexps_id(self, string, node=None, options=None):
container = PropertiesContainer(
enhance=False,
canonical_from_pattern=False)
for regexp in options.get("id_regexps"):
container.register_property(
'regexpId',
regexp,
confidence=1.0,
validator=NoValidator())
found = container.find_properties(string, node, options)
return container.as_guess(found, string)
示例3: expected_series
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
def expected_series(self, string, node=None, options=None):
container = PropertiesContainer(enhance=True, canonical_from_pattern=False)
for expected_serie in options.get('expected_series'):
if expected_serie.startswith('re:'):
expected_serie = expected_serie[3:]
expected_serie = expected_serie.replace(' ', '-')
container.register_property('series', expected_serie, enhance=True)
else:
expected_serie = re.escape(expected_serie)
container.register_property('series', expected_serie, enhance=False)
found = container.find_properties(string, node, options)
return container.as_guess(found, string)
示例4: GuessWeakEpisodesRexps
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessWeakEpisodesRexps(Transformer):
def __init__(self):
Transformer.__init__(self, 15)
self.properties = PropertiesContainer(enhance=False, canonical_from_pattern=False)
def _formater(episodeNumber):
epnum = parse_numeral(episodeNumber)
if not valid_year(epnum):
if epnum > 100:
season, epnum = epnum // 100, epnum % 100
# episodes which have a season > 50 are most likely errors
# (Simpson is at 25!)
if season > 50:
return None
return {'season': season, 'episodeNumber': epnum}
else:
return epnum
self.properties.register_property(['episodeNumber', 'season'], '[0-9]{2,4}', confidence=0.6, formatter=_formater)
self.properties.register_property('episodeNumber', '(?:episode)' + sep + '(' + numeral + ')[^0-9]', confidence=0.3)
def supported_properties(self):
return self.properties.get_supported_properties()
def guess_weak_episodes_rexps(self, string, node=None, options=None):
if node and 'episodeNumber' in node.root.info:
return None
properties = self.properties.find_properties(string, node)
guess = self.properties.as_guess(properties, string)
return guess
def should_process(self, mtree, options=None):
return mtree.guess.get('type', '').startswith('episode')
def process(self, mtree, options=None):
GuessFinder(self.guess_weak_episodes_rexps, 0.6, self.log, options).process_nodes(mtree.unidentified_leaves())
示例5: GuessEpisodeDetails
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessEpisodeDetails(Transformer):
def __init__(self):
Transformer.__init__(self, -205)
self.container = PropertiesContainer()
self.container.register_property(
"episodeDetails", "Special", "Bonus", "Omake", "Ova", "Oav", "Pilot", "Unaired"
)
self.container.register_property("episodeDetails", "Extras?", canonical_form="Extras")
def guess_details(self, string, node=None, options=None):
properties = self.container.find_properties(string, node, options, "episodeDetails", multiple=True)
guesses = self.container.as_guess(properties, multiple=True)
return guesses
def second_pass_options(self, mtree, options=None):
if not mtree.guess.get("type", "").startswith("episode"):
for unidentified_leaf in mtree.unidentified_leaves():
properties = self.container.find_properties(
unidentified_leaf.value, unidentified_leaf, options, "episodeDetails"
)
guess = self.container.as_guess(properties)
if guess:
return {"type": "episode"}
return None
def supported_properties(self):
return self.container.get_supported_properties()
def process(self, mtree, options=None):
if mtree.guess.get("type", "").startswith("episode") and (
not mtree.info.get("episodeNumber") or mtree.info.get("season") == 0
):
for leaf in itertools.chain(mtree.leaves_containing("title"), mtree.unidentified_leaves()):
guesses = self.guess_details(leaf.value, leaf, options)
for guess in guesses:
found_guess(leaf, guess, update_guess=False)
return None
示例6: GuessWebsite
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessWebsite(Transformer):
def __init__(self):
Transformer.__init__(self, 45)
self.container = PropertiesContainer(enhance=False, canonical_from_pattern=False)
tlds = []
f = resource_stream('guessit', 'tlds-alpha-by-domain.txt')
f.readline()
next(f)
for tld in f:
tld = tld.strip()
if b'--' in tld:
continue
tlds.append(tld.decode("utf-8"))
f.close()
tlds_pattern = build_or_pattern(tlds) # All registered domain extension
safe_tlds_pattern = build_or_pattern(['com', 'org', 'net']) # For sure a website extension
safe_subdomains_pattern = build_or_pattern(['www']) # For sure a website subdomain
safe_prefix_tlds_pattern = build_or_pattern(['co', 'com', 'org', 'net']) # Those words before a tlds are sure
self.container.register_property('website', '(?:' + safe_subdomains_pattern + '\.)+' + r'(?:[a-z-]+\.)+' + r'(?:' + tlds_pattern + r')+')
self.container.register_property('website', '(?:' + safe_subdomains_pattern + '\.)*' + r'[a-z-]+\.' + r'(?:' + safe_tlds_pattern + r')+')
self.container.register_property('website', '(?:' + safe_subdomains_pattern + '\.)*' + r'[a-z-]+\.' + r'(?:' + safe_prefix_tlds_pattern + r'\.)+' + r'(?:' + tlds_pattern + r')+')
def supported_properties(self):
return self.container.get_supported_properties()
def guess_website(self, string, node=None, options=None):
found = self.container.find_properties(string, node, 'website')
return self.container.as_guess(found, string)
def process(self, mtree, options=None):
GuessFinder(self.guess_website, 1.0, self.log, options).process_nodes(mtree.unidentified_leaves())
示例7: GuessWebsite
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessWebsite(Transformer):
def __init__(self):
Transformer.__init__(self, 45)
self.container = PropertiesContainer(enhance=False, canonical_from_pattern=False)
tlds_pattern = build_or_pattern(TLDS) # All registered domain extension
safe_tlds_pattern = build_or_pattern(['com', 'org', 'net']) # For sure a website extension
safe_subdomains_pattern = build_or_pattern(['www']) # For sure a website subdomain
safe_prefix_tlds_pattern = build_or_pattern(['co', 'com', 'org', 'net']) # Those words before a tlds are sure
self.container.register_property('website', '(?:' + safe_subdomains_pattern + '\.)+' + r'(?:[a-z-]+\.)+' + r'(?:' + tlds_pattern + r')+')
self.container.register_property('website', '(?:' + safe_subdomains_pattern + '\.)*' + r'[a-z-]+\.' + r'(?:' + safe_tlds_pattern + r')+')
self.container.register_property('website', '(?:' + safe_subdomains_pattern + '\.)*' + r'[a-z-]+\.' + r'(?:' + safe_prefix_tlds_pattern + r'\.)+' + r'(?:' + tlds_pattern + r')+')
def supported_properties(self):
return self.container.get_supported_properties()
def guess_website(self, string, node=None, options=None):
found = self.container.find_properties(string, node, 'website')
return self.container.as_guess(found, string)
def process(self, mtree, options=None):
GuessFinder(self.guess_website, 1.0, self.log, options).process_nodes(mtree.unidentified_leaves())
示例8: GuessProperties
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessProperties(Transformer):
def __init__(self):
Transformer.__init__(self, 35)
self.container = PropertiesContainer()
self.qualities = QualitiesContainer()
def register_property(propname, props, **kwargs):
"""props a dict of {value: [patterns]}"""
for canonical_form, patterns in props.items():
if isinstance(patterns, tuple):
patterns2, pattern_kwarg = patterns
if kwargs:
current_kwarg = dict(kwargs)
current_kwarg.update(pattern_kwarg)
else:
current_kwarg = dict(pattern_kwarg)
current_kwarg['canonical_form'] = canonical_form
self.container.register_property(propname, *patterns2, **current_kwarg)
elif kwargs:
current_kwarg = dict(kwargs)
current_kwarg['canonical_form'] = canonical_form
self.container.register_property(propname, *patterns, **current_kwarg)
else:
self.container.register_property(propname, *patterns, canonical_form=canonical_form)
def register_quality(propname, quality_dict):
"""props a dict of {canonical_form: quality}"""
for canonical_form, quality in quality_dict.items():
self.qualities.register_quality(propname, canonical_form, quality)
register_property('container', {'mp4': ['MP4']})
# http://en.wikipedia.org/wiki/Pirated_movie_release_types
register_property('format', {'VHS': ['VHS', 'VHS-Rip'],
'Cam': ['CAM', 'CAMRip', 'HD-CAM'],
#'Telesync': ['TELESYNC', 'PDVD'],
'Telesync': (['TS', 'HD-TS'], {'confidence': 0.4}),
'Workprint': ['WORKPRINT', 'WP'],
'Telecine': ['TELECINE', 'TC'],
'PPV': ['PPV', 'PPV-Rip'], # Pay Per View
'TV': ['SD-TV', 'SD-TV-Rip', 'Rip-SD-TV', 'TV-Rip', 'Rip-TV'],
'DVB': ['DVB-Rip', 'DVB', 'PD-TV'],
'DVD': ['DVD', 'DVD-Rip', 'VIDEO-TS', 'DVD-R', 'DVD-9', 'DVD-5'],
'HDTV': ['HD-TV', 'TV-RIP-HD', 'HD-TV-RIP', 'HD-RIP'],
'VOD': ['VOD', 'VOD-Rip'],
'WEBRip': ['WEB-Rip'],
'WEB-DL': ['WEB-DL', 'WEB-HD', 'WEB'],
'HD-DVD': ['HD-DVD-Rip', 'HD-DVD'],
'BluRay': ['Blu-ray(?:-Rip)?', 'B[DR]', 'B[DR]-Rip', 'BD[59]', 'BD25', 'BD50']
})
register_quality('format', {'VHS': -100,
'Cam': -90,
'Telesync': -80,
'Workprint': -70,
'Telecine': -60,
'PPV': -50,
'TV': -30,
'DVB': -20,
'DVD': 0,
'HDTV': 20,
'VOD': 40,
'WEBRip': 50,
'WEB-DL': 60,
'HD-DVD': 80,
'BluRay': 100
})
register_property('screenSize', {'360p': ['(?:\d{3,}(?:\\|\/|x|\*))?360(?:i|p?x?)'],
'368p': ['(?:\d{3,}(?:\\|\/|x|\*))?368(?:i|p?x?)'],
'480p': ['(?:\d{3,}(?:\\|\/|x|\*))?480(?:i|p?x?)'],
#'480p': (['hr'], {'confidence': 0.2}), # duplicate dict key
'576p': ['(?:\d{3,}(?:\\|\/|x|\*))?576(?:i|p?x?)'],
'720p': ['(?:\d{3,}(?:\\|\/|x|\*))?720(?:i|p?x?)'],
'900p': ['(?:\d{3,}(?:\\|\/|x|\*))?900(?:i|p?x?)'],
'1080i': ['(?:\d{3,}(?:\\|\/|x|\*))?1080i'],
'1080p': ['(?:\d{3,}(?:\\|\/|x|\*))?1080p?x?'],
'4K': ['(?:\d{3,}(?:\\|\/|x|\*))?2160(?:i|p?x?)']
},
validator=ChainedValidator(DefaultValidator(), OnlyOneValidator()))
class ResolutionValidator(object):
"""Make sure our match is surrounded by separators, or by another entry"""
@staticmethod
def validate(prop, string, node, match, entry_start, entry_end):
"""
span = _get_span(prop, match)
span = _trim_span(span, string[span[0]:span[1]])
start, end = span
sep_start = start <= 0 or string[start - 1] in sep
sep_end = end >= len(string) or string[end] in sep
start_by_other = start in entry_end
end_by_other = end in entry_start
if (sep_start or start_by_other) and (sep_end or end_by_other):
return True
return False
"""
return True
#.........这里部分代码省略.........
示例9: GuessVideoRexps
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessVideoRexps(Transformer):
def __init__(self):
Transformer.__init__(self, 25)
self.container = PropertiesContainer(canonical_from_pattern=False)
self.container.register_property(None, 'cd' + _psep + '(?P<cdNumber>[0-9])(?:' + _psep + 'of' + _psep + '(?P<cdNumberTotal>[0-9]))?', confidence=1.0, enhance=False, global_span=True, formatter=parse_numeral)
self.container.register_property('cdNumberTotal', '([1-9])' + _psep + 'cds?', confidence=0.9, enhance=False, formatter=parse_numeral)
self.container.register_property('bonusNumber', 'x([0-9]{1,2})', enhance=False, global_span=True, formatter=parse_numeral)
self.container.register_property('filmNumber', 'f([0-9]{1,2})', enhance=False, global_span=True, formatter=parse_numeral)
self.container.register_property('edition', 'collector', 'collector-edition', 'edition-collector', canonical_form='Collector Edition')
self.container.register_property('edition', 'special-edition', 'edition-special', canonical_form='Special Edition')
self.container.register_property('edition', 'criterion', 'criterion-edition', 'edition-criterion', canonical_form='Criterion Edition')
self.container.register_property('edition', 'deluxe', 'cdeluxe-edition', 'edition-deluxe', canonical_form='Deluxe Edition')
self.container.register_property('edition', 'director\'?s?-cut', 'director\'?s?-cut-edition', 'edition-director\'?s?-cut', canonical_form='Director\'s cut')
def supported_properties(self):
return self.container.get_supported_properties()
def guess_video_rexps(self, string, node=None, options=None):
found = self.container.find_properties(string, node, options)
return self.container.as_guess(found, string)
def process(self, mtree, options=None):
GuessFinder(self.guess_video_rexps, None, self.log, options).process_nodes(mtree.unidentified_leaves())
示例10: GuessEpisodesRexps
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
#.........这里部分代码省略.........
for x in range(0, len(range_values) - 1):
start_range_ep = parse_numeral(range_values[x])
end_range_ep = parse_numeral(range_values[x+1])
for range_ep in range(start_range_ep, end_range_ep + 1):
if range_ep not in ret:
ret.append(range_ep)
else:
discrete_value = parse_numeral(discrete_element)
if discrete_value not in ret:
ret.append(discrete_value)
if len(ret) > 1:
if not allow_discrete:
valid_ret = []
# replace discrete elements by ranges
valid_ret.append(ret[0])
for i in range(0, len(ret) - 1):
previous = valid_ret[len(valid_ret) - 1]
if ret[i+1] < previous:
pass
else:
valid_ret.append(ret[i+1])
ret = valid_ret
if fill_gaps:
ret = list(range(min(ret), max(ret) + 1))
if len(ret) > 1:
return {None: ret[0], propertyListName: ret}
if len(ret) > 0:
return ret[0]
return None
def episode_parser_x(value):
return list_parser(value, 'episodeList', discrete_separators_re=re.compile('x', re.IGNORECASE))
def episode_parser_e(value):
return list_parser(value, 'episodeList', discrete_separators_re=re.compile('e',re.IGNORECASE), fill_gaps=True)
def episode_parser(value):
return list_parser(value, 'episodeList')
def season_parser(value):
return list_parser(value, 'seasonList')
class ResolutionCollisionValidator(object):
def validate(self, prop, string, node, match, entry_start, entry_end):
return len(match.group(2)) < 3 #limit
self.container.register_property(None, r'(' + season_words_re.pattern + sep + '?(?P<season>' + numeral + ')' + sep + '?' + season_words_re.pattern + '?)', confidence=1.0, formatter=parse_numeral)
self.container.register_property(None, r'(' + season_words_re.pattern + sep + '?(?P<season>' + digital_numeral + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + digital_numeral + ')*)' + sep + '?' + season_words_re.pattern + '?)' + sep, confidence=1.0, formatter={None: parse_numeral, 'season': season_parser}, validator=ChainedValidator(DefaultValidator(), FormatterValidator('season', lambda x: len(x) > 1 if hasattr(x, '__len__') else False)))
self.container.register_property(None, r'(' + season_markers_re.pattern + '(?P<season>' + digital_numeral + ')[^0-9]?' + sep + '?(?P<episodeNumber>(?:e' + digital_numeral + '(?:' + sep + '?[e-]' + digital_numeral + ')*)))', confidence=1.0, formatter={None: parse_numeral, 'episodeNumber': episode_parser_e, 'season': season_parser}, validator=NoValidator())
#self.container.register_property(None, r'[^0-9]((?P<season>' + digital_numeral + ')[^0-9 .-]?-?(?P<episodeNumber>(?:x' + digital_numeral + '(?:' + sep + '?[x-]' + digital_numeral + ')*)))', confidence=1.0, formatter={None: parse_numeral, 'episodeNumber': episode_parser_x, 'season': season_parser}, validator=ChainedValidator(DefaultValidator(), ResolutionCollisionValidator()))
self.container.register_property(None, sep + r'((?P<season>' + digital_numeral + ')' + sep + '' + '(?P<episodeNumber>(?:x' + sep + digital_numeral + '(?:' + sep + '[x-]' + digital_numeral + ')*)))', confidence=1.0, formatter={None: parse_numeral, 'episodeNumber': episode_parser_x, 'season': season_parser}, validator=ChainedValidator(DefaultValidator(), ResolutionCollisionValidator()))
self.container.register_property(None, r'((?P<season>' + digital_numeral + ')' + '(?P<episodeNumber>(?:x' + digital_numeral + '(?:[x-]' + digital_numeral + ')*)))', confidence=1.0, formatter={None: parse_numeral, 'episodeNumber': episode_parser_x, 'season': season_parser}, validator=ChainedValidator(DefaultValidator(), ResolutionCollisionValidator()))
self.container.register_property(None, r'(' + season_markers_re.pattern + '(?P<season>' + digital_numeral + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + digital_numeral + ')*))', confidence=0.6, formatter={None: parse_numeral, 'season': season_parser}, validator=NoValidator())
self.container.register_property(None, r'((?P<episodeNumber>' + digital_numeral + ')' + sep + '?v(?P<version>\d+))', confidence=0.6, formatter=parse_numeral)
self.container.register_property(None, r'(ep' + sep + r'?(?P<episodeNumber>' + numeral + ')' + sep + '?)', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'(ep' + sep + r'?(?P<episodeNumber>' + numeral + ')' + sep + '?v(?P<version>\d+))', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'(' + episode_markers_re.pattern + '(?P<episodeNumber>' + digital_numeral + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + digital_numeral + ')*))', confidence=0.6, formatter={None: parse_numeral, 'episodeNumber': episode_parser})
self.container.register_property(None, r'(' + episode_words_re.pattern + sep + '?(?P<episodeNumber>' + digital_numeral + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + digital_numeral + ')*)' + sep + '?' + episode_words_re.pattern + '?)', confidence=0.8, formatter={None: parse_numeral, 'episodeNumber': episode_parser})
self.container.register_property(None, r'(' + episode_markers_re.pattern + '(?P<episodeNumber>' + digital_numeral + ')' + sep + '?v(?P<version>\d+))', confidence=0.6, formatter={None: parse_numeral, 'episodeNumber': episode_parser})
self.container.register_property(None, r'(' + episode_words_re.pattern + sep + '?(?P<episodeNumber>' + digital_numeral + ')' + sep + '?v(?P<version>\d+))', confidence=0.8, formatter={None: parse_numeral, 'episodeNumber': episode_parser})
self.container.register_property('episodeNumber', r'^ ?(\d{2})' + sep, confidence=0.4, formatter=parse_numeral)
self.container.register_property('episodeNumber', r'^ ?(\d{2})' + sep, confidence=0.4, formatter=parse_numeral)
self.container.register_property('episodeNumber', r'^ ?0(\d{1,2})' + sep, confidence=0.4, formatter=parse_numeral)
self.container.register_property('episodeNumber', sep + r'(\d{2}) ?$', confidence=0.4, formatter=parse_numeral)
self.container.register_property('episodeNumber', sep + r'0(\d{1,2}) ?$', confidence=0.4, formatter=parse_numeral)
self.container.register_property(None, r'((?P<episodeNumber>' + numeral + ')' + sep + '?' + of_separators_re.pattern + sep + '?(?P<episodeCount>' + numeral + ')(?:' + sep + '?(?:episodes?|eps?))?)', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'((?:episodes?|eps?)' + sep + '?(?P<episodeNumber>' + numeral + ')' + sep + '?' + of_separators_re.pattern + sep + '?(?P<episodeCount>' + numeral + '))', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'((?:seasons?|saisons?|s)' + sep + '?(?P<season>' + numeral + ')' + sep + '?' + of_separators_re.pattern + sep + '?(?P<seasonCount>' + numeral + '))', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'((?P<season>' + numeral + ')' + sep + '?' + of_separators_re.pattern + sep + '?(?P<seasonCount>' + numeral + ')' + sep + '?(?:seasons?|saisons?|s))', confidence=0.7, formatter=parse_numeral)
self.container.register_canonical_properties('other', 'FiNAL', 'Complete', validator=WeakValidator())
self.container.register_property(None, r'[^0-9]((?P<season>' + digital_numeral + ')[^0-9 .-]?-?(?P<other>xAll))', confidence=1.0, formatter={None: parse_numeral, 'other': lambda x: 'Complete', 'season': season_parser}, validator=ChainedValidator(DefaultValidator(), ResolutionCollisionValidator()))
def register_options(self, opts, naming_opts, output_opts, information_opts, webservice_opts, other_options):
naming_opts.add_option('-E', '--episode-prefer-number', action='store_true', dest='episode_prefer_number', default=False,
help='Guess "serie.213.avi" as the episodeNumber 213. Without this option, '
'it will be guessed as season 2, episodeNumber 13')
def supported_properties(self):
return ['episodeNumber', 'season', 'episodeList', 'seasonList', 'episodeCount', 'seasonCount', 'version', 'other']
def guess_episodes_rexps(self, string, node=None, options=None):
found = self.container.find_properties(string, node, options)
return self.container.as_guess(found, string)
def should_process(self, mtree, options=None):
return mtree.guess.get('type', '').startswith('episode')
def process(self, mtree, options=None):
GuessFinder(self.guess_episodes_rexps, None, self.log, options).process_nodes(mtree.unidentified_leaves())
示例11: guess_release_group
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
def guess_release_group(self, string, node=None, options=None):
if options and options.get('expected_group'):
expected_container = PropertiesContainer(enhance=True, canonical_from_pattern=False)
for expected_group in options.get('expected_group'):
if expected_group.startswith('re:'):
expected_group = expected_group[3:]
expected_group = expected_group.replace(' ', '-')
expected_container.register_property('releaseGroup', expected_group, enhance=True)
else:
expected_group = re.escape(expected_group)
expected_container.register_property('releaseGroup', expected_group, enhance=False)
found = expected_container.find_properties(string, node, options, 'releaseGroup')
guess = expected_container.as_guess(found, string, self.validate_group_name)
if guess:
return guess
found = self.container.find_properties(string, node, options, 'releaseGroup')
guess = self.container.as_guess(found, string, self.validate_group_name)
validated_guess = None
if guess:
group_node = node.group_node()
if group_node:
for leaf in group_node.leaves_containing(self.previous_safe_properties):
if self.validate_node(leaf, node, True):
if leaf.root.value[leaf.span[1]] == '-':
guess.metadata().confidence = 1
else:
guess.metadata().confidence = 0.7
validated_guess = guess
if not validated_guess:
# If previous group last leaf is identified as a safe property,
# consider the raw value as a releaseGroup
previous_group_node = node.previous_group_node()
if previous_group_node:
for leaf in previous_group_node.leaves_containing(self.previous_safe_properties):
if self.validate_node(leaf, node, False):
guess = Guess({'releaseGroup': node.value}, confidence=1, input=node.value, span=(0, len(node.value)))
if self.validate_group_name(guess):
node.guess = guess
validated_guess = guess
if validated_guess:
# If following group nodes have only one unidentified leaf, it belongs to the release group
next_group_node = node
while True:
next_group_node = next_group_node.next_group_node()
if next_group_node:
leaves = list(next_group_node.leaves())
if len(leaves) == 1 and not leaves[0].guess:
validated_guess['releaseGroup'] = validated_guess['releaseGroup'] + leaves[0].value
leaves[0].guess = validated_guess
else:
break
else:
break
if not validated_guess and node.is_explicit() and node.node_last_idx == 0: # first node from group
validated_guess = build_guess(node, 'releaseGroup', value=node.value[1:len(node.value)-1])
validated_guess.metadata().confidence = 0.4
validated_guess.metadata().span = 1, len(node.value)
node.guess = validated_guess
if validated_guess:
# Strip brackets
validated_guess['releaseGroup'] = strip_brackets(validated_guess['releaseGroup'])
return validated_guess
示例12: GuessEpisodesRexps
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessEpisodesRexps(Transformer):
def __init__(self):
Transformer.__init__(self, 20)
of_separators = ['of', 'sur', '/', '\\']
of_separators_re = re.compile(build_or_pattern(of_separators, escape=True), re.IGNORECASE)
season_words = ['seasons?', 'saisons?', 'series?']
episode_words = ['episodes?']
season_markers = ['s']
episode_markers = ['e', 'ep']
self.container = PropertiesContainer(enhance=False, canonical_from_pattern=False)
season_words_re = re.compile(build_or_pattern(season_words), re.IGNORECASE)
episode_words_re = re.compile(build_or_pattern(episode_words), re.IGNORECASE)
season_markers_re = re.compile(build_or_pattern(season_markers), re.IGNORECASE)
episode_markers_re = re.compile(build_or_pattern(episode_markers), re.IGNORECASE)
def episode_parser_x(value):
return list_parser(value, 'episodeList', discrete_separators_re=re.compile('x', re.IGNORECASE))
def episode_parser_e(value):
return list_parser(value, 'episodeList', discrete_separators_re=re.compile('e', re.IGNORECASE), fill_gaps=True)
def episode_parser(value):
return list_parser(value, 'episodeList')
def season_parser(value):
return list_parser(value, 'seasonList')
class ResolutionCollisionValidator(object):
@staticmethod
def validate(prop, string, node, match, entry_start, entry_end):
# Invalidate when season or episode is more than 100.
try:
season_value = season_parser(match.group(2))
episode_value = episode_parser_x(match.group(3))
return season_value < 100 or episode_value < 100
except:
# This may occur for 1xAll or patterns like this.
return True
self.container.register_property(None, r'(' + season_words_re.pattern + sep + '?(?P<season>' + numeral + ')' + sep + '?' + season_words_re.pattern + '?)', confidence=1.0, formatter=parse_numeral)
self.container.register_property(None, r'(' + season_words_re.pattern + sep + '?(?P<season>' + digital_numeral + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + digital_numeral + ')*)' + sep + '?' + season_words_re.pattern + '?)' + sep, confidence=1.0, formatter={None: parse_numeral, 'season': season_parser}, validator=ChainedValidator(DefaultValidator(), FormatterValidator('season', lambda x: len(x) > 1 if hasattr(x, '__len__') else False)))
self.container.register_property(None, r'(' + season_markers_re.pattern + '(?P<season>' + digital_numeral + ')[^0-9]?' + sep + '?(?P<episodeNumber>(?:e' + digital_numeral + '(?:' + sep + '?[e-]' + digital_numeral + ')*)))', confidence=1.0, formatter={None: parse_numeral, 'episodeNumber': episode_parser_e, 'season': season_parser}, validator=NoValidator())
self.container.register_property(None, r'(' + season_markers_re.pattern + '(?P<season>' + digital_numeral + ')[^0-9]?' + sep + '?(?P<episodeNumber>(?:e' + digital_numeral + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + digital_numeral + ')*)))', confidence=1.0, formatter={None: parse_numeral, 'episodeNumber': episode_parser, 'season': season_parser}, validator=NoValidator())
self.container.register_property(None, sep + r'((?P<season>' + digital_numeral + ')' + sep + '' + '(?P<episodeNumber>(?:x' + sep + digital_numeral + '(?:' + sep + '[x-]' + digital_numeral + ')*)))', confidence=1.0, formatter={None: parse_numeral, 'episodeNumber': episode_parser_x, 'season': season_parser}, validator=ChainedValidator(DefaultValidator(), ResolutionCollisionValidator()))
self.container.register_property(None, r'((?P<season>' + digital_numeral + ')' + '(?P<episodeNumber>(?:x' + digital_numeral + '(?:[x-]' + digital_numeral + ')*)))', confidence=1.0, formatter={None: parse_numeral, 'episodeNumber': episode_parser_x, 'season': season_parser}, validator=ChainedValidator(DefaultValidator(), ResolutionCollisionValidator()))
self.container.register_property(None, r'(' + season_markers_re.pattern + '(?P<season>' + digital_numeral + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + digital_numeral + ')*))', confidence=0.6, formatter={None: parse_numeral, 'season': season_parser}, validator=NoValidator())
self.container.register_property(None, r'((?P<episodeNumber>' + digital_numeral + ')' + sep + '?v(?P<version>\d+))', confidence=0.6, formatter=parse_numeral)
self.container.register_property('version', sep + r'(V\d+)' + sep, confidence=0.6, formatter=parse_numeral, validator=NoValidator())
self.container.register_property(None, r'(ep' + sep + r'?(?P<episodeNumber>' + digital_numeral + ')' + sep + '?)', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'(ep' + sep + r'?(?P<episodeNumber>' + digital_numeral + ')' + sep + '?v(?P<version>\d+))', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'(' + episode_markers_re.pattern + '(?P<episodeNumber>' + digital_numeral + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + digital_numeral + ')*))', confidence=0.6, formatter={None: parse_numeral, 'episodeNumber': episode_parser})
self.container.register_property(None, r'(' + episode_words_re.pattern + sep + '?(?P<episodeNumber>' + digital_numeral + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + digital_numeral + ')*)' + sep + '?' + episode_words_re.pattern + '?)', confidence=0.8, formatter={None: parse_numeral, 'episodeNumber': episode_parser})
self.container.register_property(None, r'(' + episode_markers_re.pattern + '(?P<episodeNumber>' + digital_numeral + ')' + sep + '?v(?P<version>\d+))', confidence=0.6, formatter={None: parse_numeral, 'episodeNumber': episode_parser})
self.container.register_property(None, r'(' + episode_words_re.pattern + sep + '?(?P<episodeNumber>' + digital_numeral + ')' + sep + '?v(?P<version>\d+))', confidence=0.8, formatter={None: parse_numeral, 'episodeNumber': episode_parser})
self.container.register_property('episodeNumber', r'^' + sep + '+(\d{2}' + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + '\d{2}' + ')*)' + sep, confidence=0.4, formatter=episode_parser)
self.container.register_property('episodeNumber', r'^' + sep + '+0(\d{1,2}' + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + '0\d{1,2}' + ')*)' + sep, confidence=0.4, formatter=episode_parser)
self.container.register_property('episodeNumber', sep + r'(\d{2}' + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + r'\d{2}' + ')*)' + sep + '+$', confidence=0.4, formatter=episode_parser)
self.container.register_property('episodeNumber', sep + r'0(\d{1,2}' + '(?:' + sep + '?' + all_separators_re.pattern + sep + '?' + r'0\d{1,2}' + ')*)' + sep + '+$', confidence=0.4, formatter=episode_parser)
self.container.register_property(None, r'((?P<episodeNumber>' + numeral + ')' + sep + '?' + of_separators_re.pattern + sep + '?(?P<episodeCount>' + numeral + ')(?:' + sep + '?(?:episodes?|eps?))?)', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'((?:episodes?|eps?)' + sep + '?(?P<episodeNumber>' + numeral + ')' + sep + '?' + of_separators_re.pattern + sep + '?(?P<episodeCount>' + numeral + '))', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'((?:seasons?|saisons?|s)' + sep + '?(?P<season>' + numeral + ')' + sep + '?' + of_separators_re.pattern + sep + '?(?P<seasonCount>' + numeral + '))', confidence=0.7, formatter=parse_numeral)
self.container.register_property(None, r'((?P<season>' + numeral + ')' + sep + '?' + of_separators_re.pattern + sep + '?(?P<seasonCount>' + numeral + ')' + sep + '?(?:seasons?|saisons?|s))', confidence=0.7, formatter=parse_numeral)
self.container.register_canonical_properties('other', 'FiNAL', 'Complete', validator=WeakValidator())
self.container.register_property(None, r'[^0-9]((?P<season>' + digital_numeral + ')[^0-9 .-]?-?(?P<other>xAll))', confidence=1.0, formatter={None: parse_numeral, 'other': lambda x: 'Complete', 'season': season_parser}, validator=ChainedValidator(DefaultValidator(), ResolutionCollisionValidator()))
def register_arguments(self, opts, naming_opts, output_opts, information_opts, webservice_opts, other_options):
naming_opts.add_argument('-E', '--episode-prefer-number', action='store_true', dest='episode_prefer_number', default=False,
help='Guess "serie.213.avi" as the episodeNumber 213. Without this option, '
'it will be guessed as season 2, episodeNumber 13')
def supported_properties(self):
return ['episodeNumber', 'season', 'episodeList', 'seasonList', 'episodeCount', 'seasonCount', 'version', 'other']
def guess_episodes_rexps(self, string, node=None, options=None):
found = self.container.find_properties(string, node, options)
guess = self.container.as_guess(found, string)
if guess and node:
if 'season' in guess and 'episodeNumber' in guess:
# If two guesses contains both season and episodeNumber in same group, create an episodeList
for existing_guess in node.group_node().guesses:
if 'season' in existing_guess and 'episodeNumber' in existing_guess:
if 'episodeList' not in existing_guess:
existing_guess['episodeList'] = [existing_guess['episodeNumber']]
existing_guess['episodeList'].append(guess['episodeNumber'])
existing_guess['episodeList'].sort()
#.........这里部分代码省略.........
示例13: GuessWeakEpisodesRexps
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessWeakEpisodesRexps(Transformer):
def __init__(self):
Transformer.__init__(self, 15)
of_separators = ["of", "sur", "/", "\\"]
of_separators_re = re.compile(build_or_pattern(of_separators, escape=True), re.IGNORECASE)
self.container = PropertiesContainer(enhance=False, canonical_from_pattern=False, remove_duplicates=True)
episode_words = ["episodes?"]
def episode_list_parser(value):
return list_parser(value, "episodeList")
def season_episode_parser(episode_number):
epnum = parse_numeral(episode_number)
if not valid_year(epnum):
if epnum > 100:
season, epnum = epnum // 100, epnum % 100
# episodes which have a season > 50 are most likely errors
# (Simpson is at 25!)
if season > 50:
return None
return {"season": season, "episodeNumber": epnum}
else:
return epnum
self.container.register_property(
["episodeNumber", "season"],
"[0-9]{2,4}",
confidence=0.6,
formatter=season_episode_parser,
disabler=lambda options: options.get("episode_prefer_number") if options else False,
)
self.container.register_property(
["episodeNumber", "season"], "[0-9]{4}", confidence=0.6, formatter=season_episode_parser
)
self.container.register_property(
None,
"(" + build_or_pattern(episode_words) + sep + "?(?P<episodeNumber>" + numeral + "))[^0-9]",
confidence=0.4,
formatter=parse_numeral,
)
self.container.register_property(
None,
r"(?P<episodeNumber>"
+ numeral
+ ")"
+ sep
+ "?"
+ of_separators_re.pattern
+ sep
+ "?(?P<episodeCount>"
+ numeral
+ ")",
confidence=0.6,
formatter=parse_numeral,
)
self.container.register_property(
"episodeNumber",
"[^0-9](\d{2,3}" + "(?:" + sep + "?" + all_separators_re.pattern + sep + "?" + "\d{2,3}" + ")*)",
confidence=0.4,
formatter=episode_list_parser,
disabler=lambda options: not options.get("episode_prefer_number") if options else True,
)
self.container.register_property(
"episodeNumber",
r"^"
+ sep
+ "?(\d{2,3}"
+ "(?:"
+ sep
+ "?"
+ all_separators_re.pattern
+ sep
+ "?"
+ "\d{2,3}"
+ ")*)"
+ sep,
confidence=0.4,
formatter=episode_list_parser,
disabler=lambda options: not options.get("episode_prefer_number") if options else True,
)
self.container.register_property(
"episodeNumber",
sep
+ r"(\d{2,3}"
+ "(?:"
+ sep
+ "?"
+ all_separators_re.pattern
+ sep
+ "?"
+ "\d{2,3}"
+ ")*)"
+ sep
+ "?$",
confidence=0.4,
formatter=episode_list_parser,
disabler=lambda options: not options.get("episode_prefer_number") if options else True,
#.........这里部分代码省略.........
示例14: GuessProperties
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessProperties(Transformer):
def __init__(self):
Transformer.__init__(self, 35)
self.container = PropertiesContainer()
self.qualities = QualitiesContainer()
def register_property(propname, props):
"""props a dict of {value: [patterns]}"""
for canonical_form, patterns in props.items():
if isinstance(patterns, tuple):
patterns2, kwargs = patterns
kwargs = dict(kwargs)
kwargs['canonical_form'] = canonical_form
self.container.register_property(propname, *patterns2, **kwargs)
else:
self.container.register_property(propname, *patterns, canonical_form=canonical_form)
def register_quality(propname, quality_dict):
"""props a dict of {canonical_form: quality}"""
for canonical_form, quality in quality_dict.items():
self.qualities.register_quality(propname, canonical_form, quality)
register_property('container', {'mp4': ['MP4']})
# http://en.wikipedia.org/wiki/Pirated_movie_release_types
register_property('format', {'VHS': ['VHS'],
'Cam': ['CAM', 'CAMRip'],
'Telesync': ['TELESYNC', 'PDVD'],
'Telesync': (['TS'], {'confidence': 0.2}),
'Workprint': ['WORKPRINT', 'WP'],
'Telecine': ['TELECINE', 'TC'],
'PPV': ['PPV', 'PPV-Rip'], # Pay Per View
'TV': ['SD-TV', 'SD-TV-Rip', 'Rip-SD-TV', 'TV-Rip', 'Rip-TV'],
'DVB': ['DVB-Rip', 'DVB', 'PD-TV'],
'DVD': ['DVD', 'DVD-Rip', 'VIDEO-TS'],
'HDTV': ['HD-TV', 'TV-RIP-HD', 'HD-TV-RIP'],
'VOD': ['VOD', 'VOD-Rip'],
'WEBRip': ['WEB-Rip'],
'WEB-DL': ['WEB-DL'],
'HD-DVD': ['HD-(?:DVD)?-Rip', 'HD-DVD'],
'BluRay': ['Blu-ray', 'B[DR]', 'B[DR]-Rip', 'BD[59]', 'BD25', 'BD50']
})
register_quality('format', {'VHS': -100,
'Cam': -90,
'Telesync': -80,
'Workprint': -70,
'Telecine': -60,
'PPV': -50,
'TV': -30,
'DVB': -20,
'DVD': 0,
'HDTV': 20,
'VOD': 40,
'WEBRip': 50,
'WEB-DL': 60,
'HD-DVD': 80,
'BluRay': 100
})
register_property('screenSize', {'360p': ['(?:\d{3,}(?:\\|\/|x|\*))?360(?:i|p?x?)'],
'368p': ['(?:\d{3,}(?:\\|\/|x|\*))?368(?:i|p?x?)'],
'480p': ['(?:\d{3,}(?:\\|\/|x|\*))?480(?:i|p?x?)'],
'480p': (['hr'], {'confidence': 0.2}),
'576p': ['(?:\d{3,}(?:\\|\/|x|\*))?576(?:i|p?x?)'],
'720p': ['(?:\d{3,}(?:\\|\/|x|\*))?720(?:i|p?x?)'],
'900p': ['(?:\d{3,}(?:\\|\/|x|\*))?900(?:i|p?x?)'],
'1080i': ['(?:\d{3,}(?:\\|\/|x|\*))?1080i'],
'1080p': ['(?:\d{3,}(?:\\|\/|x|\*))?1080(?:p?x?)'],
'4K': ['(?:\d{3,}(?:\\|\/|x|\*))?2160(?:i|p?x?)']
})
register_quality('screenSize', {'360p': -300,
'368p': -200,
'480p': -100,
'576p': 0,
'720p': 100,
'900p': 130,
'1080i': 180,
'1080p': 200,
'4K': 400
})
_videoCodecProperty = {'Real': ['Rv\d{2}'], # http://en.wikipedia.org/wiki/RealVideo
'Mpeg2': ['Mpeg2'],
'DivX': ['DVDivX', 'DivX'],
'XviD': ['XviD'],
'h264': ['[hx]-264(?:-AVC)?', 'MPEG-4(?:-AVC)'],
'h265': ['[hx]-265(?:-HEVC)?', 'HEVC']
}
register_property('videoCodec', _videoCodecProperty)
register_quality('videoCodec', {'Real': -50,
'Mpeg2': -30,
'DivX': -10,
'XviD': 0,
'h264': 100,
#.........这里部分代码省略.........
示例15: GuessProperties
# 需要导入模块: from guessit.containers import PropertiesContainer [as 别名]
# 或者: from guessit.containers.PropertiesContainer import register_property [as 别名]
class GuessProperties(Transformer):
def __init__(self):
Transformer.__init__(self, 35)
self.container = PropertiesContainer()
self.qualities = QualitiesContainer()
def register_property(propname, props, **kwargs):
"""props a dict of {value: [patterns]}"""
for canonical_form, patterns in props.items():
if isinstance(patterns, tuple):
patterns2, pattern_kwarg = patterns
if kwargs:
current_kwarg = dict(kwargs)
current_kwarg.update(pattern_kwarg)
else:
current_kwarg = dict(pattern_kwarg)
current_kwarg["canonical_form"] = canonical_form
self.container.register_property(propname, *patterns2, **current_kwarg)
elif kwargs:
current_kwarg = dict(kwargs)
current_kwarg["canonical_form"] = canonical_form
self.container.register_property(propname, *patterns, **current_kwarg)
else:
self.container.register_property(propname, *patterns, canonical_form=canonical_form)
def register_quality(propname, quality_dict):
"""props a dict of {canonical_form: quality}"""
for canonical_form, quality in quality_dict.items():
self.qualities.register_quality(propname, canonical_form, quality)
# http://en.wikipedia.org/wiki/Pirated_movie_release_types
register_property(
"format",
{
"VHS": ["VHS", "VHS-Rip"],
"Cam": ["CAM", "CAMRip", "HD-CAM"],
#'Telesync': ['TELESYNC', 'PDVD'],
"Telesync": (["TS", "HD-TS"], {"confidence": 0.4}),
"Workprint": ["WORKPRINT", "WP"],
"Telecine": ["TELECINE", "TC"],
"PPV": ["PPV", "PPV-Rip"], # Pay Per View
"TV": ["SD-TV", "SD-TV-Rip", "Rip-SD-TV", "TV-Rip", "Rip-TV"],
"DVB": ["DVB-Rip", "DVB", "PD-TV"],
"DVD": ["DVD", "DVD-Rip", "VIDEO-TS", "DVD-R", "DVD-9", "DVD-5"],
"HDTV": ["HD-TV", "TV-RIP-HD", "HD-TV-RIP", "HD-RIP"],
"VOD": ["VOD", "VOD-Rip"],
"WEBRip": ["WEB-Rip"],
"WEB-DL": ["WEB-DL", "WEB-HD", "WEB"],
"HD-DVD": ["HD-DVD-Rip", "HD-DVD"],
"BluRay": ["Blu-ray(?:-Rip)?", "B[DR]", "B[DR]-Rip", "BD[59]", "BD25", "BD50"],
},
)
register_quality(
"format",
{
"VHS": -100,
"Cam": -90,
"Telesync": -80,
"Workprint": -70,
"Telecine": -60,
"PPV": -50,
"TV": -30,
"DVB": -20,
"DVD": 0,
"HDTV": 20,
"VOD": 40,
"WEBRip": 50,
"WEB-DL": 60,
"HD-DVD": 80,
"BluRay": 100,
},
)
register_property(
"screenSize",
{
"360p": ["(?:\d{3,}(?:\\|\/|x|\*))?360(?:i|p?x?)"],
"368p": ["(?:\d{3,}(?:\\|\/|x|\*))?368(?:i|p?x?)"],
"480p": ["(?:\d{3,}(?:\\|\/|x|\*))?480(?:i|p?x?)"],
#'480p': (['hr'], {'confidence': 0.2}), # duplicate dict key
"576p": ["(?:\d{3,}(?:\\|\/|x|\*))?576(?:i|p?x?)"],
"720p": ["(?:\d{3,}(?:\\|\/|x|\*))?720(?:i|p?x?)"],
"900p": ["(?:\d{3,}(?:\\|\/|x|\*))?900(?:i|p?x?)"],
"1080i": ["(?:\d{3,}(?:\\|\/|x|\*))?1080i"],
"1080p": ["(?:\d{3,}(?:\\|\/|x|\*))?1080p?x?"],
"4K": ["(?:\d{3,}(?:\\|\/|x|\*))?2160(?:i|p?x?)"],
},
validator=ChainedValidator(DefaultValidator(), OnlyOneValidator()),
)
_digits_re = re.compile("\d+")
def resolution_formatter(value):
digits = _digits_re.findall(value)
return "x".join(digits)
self.container.register_property(
"screenSize", "\d{3,4}-?[x\*]-?\d{3,4}", canonical_from_pattern=False, formatter=resolution_formatter
#.........这里部分代码省略.........