xvideos (JSON-LD) i kilka innych tubow oddaje tytuly z encjami HTML5 (`we're`, `(AI)`), czasem podwojnie zakodowane. normalize robil z nich slowa `apos`, `lpar`, wiec tytul nie trafial w wyszukiwarke ani w kanon. unescape_html w app/normalize/text.py dekoduje encje zakonczone srednikiem po slowniku HTML5, do skutku (max 3 przebiegi). Wpiete w normalize_scene i normalize_movie oraz w parsery xvideos_browse i pornxp. Skrypt fix_html_entity_titles.py poprawia istniejace wiersze (title, title_normalized, slug gdy byl wyliczony z tytulu). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
67 lines
2.1 KiB
Python
67 lines
2.1 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 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=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),
|
|
)
|