fix(parser): handle None return from raw_parser to avoid AttributeError (#992)

When raw_parser fails to parse non-episodic resources (movies, collections),
it returns None. Add guard clause in title_parser to skip these gracefully
instead of crashing on attribute access. Downgrade log level from error to
info since this is expected behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Estrella Pan
2026-03-01 08:12:18 +01:00
parent 66a2b45f57
commit d980c3c714
2 changed files with 6 additions and 3 deletions

View File

@@ -14,8 +14,8 @@ SOURCE_RE = re.compile(r"B-Global|[Bb]aha|[Bb]ilibili|AT-X|Web")
SUB_RE = re.compile(r"[简繁日字幕]|CH|BIG5|GB")
FALLBACK_EP_PATTERNS = [
re.compile(r" (\d+) ?(?=\[)"), # #876/#910: digits before [
re.compile(r"\[(\d+)\(\d+\)\]"), # #773: [02(57)]
re.compile(r" (\d+) ?(?=\[)"), # #876/#910: digits before [
re.compile(r"\[(\d+)\(\d+\)\]"), # #773: [02(57)]
]
PREFIX_RE = re.compile(r"[^\w\s\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff-]")
@@ -32,6 +32,7 @@ def _fallback_parse(content_title: str) -> tuple | None:
return season_info, episode_info, other
return None
CHINESE_NUMBER_MAP = {
"": 1,
"": 2,
@@ -201,7 +202,7 @@ def process(raw_title: str):
def raw_parser(raw: str) -> Episode | None:
ret = process(raw)
if ret is None:
logger.error(f"Parser cannot analyse {raw}")
logger.info(f"Detected non-episodic resource: {raw}, skipping.")
return None
name_en, name_zh, name_jp, season, sr, episode, sub, dpi, source, group = ret
return Episode(

View File

@@ -68,6 +68,8 @@ class TitleParser:
episode = Episode(**episode_dict)
else:
episode = raw_parser(raw)
if episode is None:
return None
titles = {
"zh": episode.title_zh,