Opisy scen szly do bazy z `"`, `<br>` i surowymi `<br />`, a apka i strona SEO pokazuja opis jako tekst, wiec bylo to widac doslownie. clean_description dekoduje encje, `<br>` i koniec akapitu zamienia na nowa linie, a znane znaczniki wycina (`<3` zostaje tekstem). Wpiete w normalize_scene i normalize_movie. bulk_rescrape_hqporner.py i repair_truncated_titles.py liczyly title_normalized jako lower(title), przez co 6005 scen mialo interpunkcje w kluczu dopasowania. Oba licza teraz normalize() i dekoduja encje w tytule. Skrypty: fix_html_entity_titles.py przemianowany na fix_html_entities.py z przebiegiem po opisach; nowy fix_title_normalized.py przelicza klucz tam, gdzie rozjechal sie z normalize(title). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
67 lines
2.2 KiB
Python
67 lines
2.2 KiB
Python
"""RawMovie → NormalizedMovie. Reuse normalize_studio/performer/tag z scenes.py."""
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from datetime import date
|
|
|
|
from app.connectors.base import RawMovie, RawMovieChapter, RawPlaybackSource
|
|
from app.normalize.scenes import (
|
|
NormalizedPerformer,
|
|
NormalizedStudio,
|
|
NormalizedTag,
|
|
normalize_performer,
|
|
normalize_studio,
|
|
normalize_tag,
|
|
)
|
|
from app.normalize.text import clean_description, normalize, slugify, unescape_html
|
|
|
|
|
|
@dataclass
|
|
class NormalizedMovie:
|
|
external_id: str
|
|
title: str
|
|
title_normalized: str
|
|
slug: str
|
|
release_year: int | None
|
|
release_date: date | None
|
|
description: str | None
|
|
duration_sec: int | None
|
|
director: str | None
|
|
country: str | None
|
|
rating: float | None
|
|
poster_url: str | None
|
|
backdrop_url: str | None
|
|
url: str | None
|
|
|
|
studio: NormalizedStudio | None = None
|
|
performers: list[NormalizedPerformer] = field(default_factory=list)
|
|
tags: list[NormalizedTag] = field(default_factory=list)
|
|
chapters: list[RawMovieChapter] = field(default_factory=list)
|
|
playback_sources: list[RawPlaybackSource] = field(default_factory=list)
|
|
cross_source_refs: dict[str, str] = field(default_factory=dict)
|
|
|
|
|
|
def normalize_movie(raw: RawMovie) -> NormalizedMovie:
|
|
title = unescape_html(raw.title)
|
|
return NormalizedMovie(
|
|
external_id=raw.external_id,
|
|
title=title,
|
|
title_normalized=normalize(title),
|
|
slug=slugify(title),
|
|
release_year=raw.release_year,
|
|
release_date=raw.release_date,
|
|
description=clean_description(raw.description),
|
|
duration_sec=raw.duration_sec,
|
|
director=raw.director,
|
|
country=raw.country,
|
|
rating=raw.rating,
|
|
poster_url=raw.poster_url,
|
|
backdrop_url=raw.backdrop_url,
|
|
url=raw.url,
|
|
studio=normalize_studio(raw.studio) if raw.studio else None,
|
|
performers=[normalize_performer(p) for p in raw.performers],
|
|
tags=[normalize_tag(t) for t in raw.tags],
|
|
chapters=list(raw.chapters),
|
|
playback_sources=list(raw.playback_sources),
|
|
cross_source_refs=dict(raw.cross_source_refs),
|
|
)
|