diff --git a/app/normalize/tag_stoplist.py b/app/normalize/tag_stoplist.py new file mode 100644 index 0000000..89167ff --- /dev/null +++ b/app/normalize/tag_stoplist.py @@ -0,0 +1,74 @@ +"""Tagi, ktore nie opisuja tresci, tylko ja reklamuja. + +Skad sie biora: czesc tubow (najmocniej sxyprn) pozwala uploaderowi wpisac dowolne +hashtagi w tytul, a uploaderzy wklejaja ten sam blok do kazdego posta. Zgloszenie +778cd5be pokazalo scene z 28 tagami, gdzie w tytule u zrodla stalo dokladnie +`#Anal #BigDicks ... #France #Hotwife #artporn #french` przy amerykanskiej scenie. + +Wazne rozroznienie: TEGO NIE DA SIE naprawic wykrywaniem "spamu" statystycznie, bo +blok jest inny u kazdego uploadera, a najczestszy tag na sxyprn (Hardcore) ma tylko +47% udzialu, wiec zaden prog nie oddziela spamu od prawdziwych tagow. Da sie za to +usunac slowa, ktore NIGDY nie sa opisem tresci, niezaleznie od zrodla. Tylko to +robi ta lista. + +Kryterium wpisu: tag nie zawezaja wyszukiwania, bo pasuje do niemal wszystkiego +w katalogu ("porn", "sex", "hot"), albo opisuje sposob dystrybucji, a nie tresc +("premium", "exclusive", "leaked", "download"). + +Swiadomie NIE na liscie: + - `onlyfans` (71 972 przypisan) - to realny typ tresci, ludzie tego szukaja. + - `4k`, `hd`, `720p`, `1080p` (ok. 110 tys.) - niosa jakas informacje, choc + niepewna. Apka ma osobny, wiarygodny filtr jakosci liczony ze zrodel odtwarzania, + wiec te tagi sa zbedne, ale usuniecie ich to decyzja produktowa, nie sprzatanie + smieci. Do przegadania osobno. +""" +from __future__ import annotations + +#: Porownanie po slugu (lowercase, dywizy), bo ta sama rzecz przychodzi jako +#: "Full HD", "full-hd" i "FullHD". +JUNK_TAG_SLUGS: frozenset[str] = frozenset( + { + # pasuje do calego katalogu, wiec nie zawezaja niczego + "porn", + "porno", + "sex", + "xxx", + "adult", + "nude", + "nudes", + "hot", + "sexy", + "video", + "videos", + "movie", + "clip", + # marketing i sposob dystrybucji, nie tresc + "new", + "newest", + "latest", + "top", + "best", + "popular", + "trending", + "premium", + "exclusive", + "free", + "leaked", + "siterip", + "megapack", + "highquality", + "high-quality", + "watch", + "watch-online", + "download", + "stream", + "streaming", + "online", + "full-video", + } +) + + +def is_junk_tag(slug: str) -> bool: + """True dla tagu, ktorego nie chcemy trzymac w katalogu.""" + return slug.strip().lower() in JUNK_TAG_SLUGS diff --git a/app/resolve/tag_resolver.py b/app/resolve/tag_resolver.py index 29fa3ab..79c9595 100644 --- a/app/resolve/tag_resolver.py +++ b/app/resolve/tag_resolver.py @@ -10,6 +10,7 @@ from sqlalchemy.orm import Session from app.models.tag import Tag from app.normalize.scenes import NormalizedTag +from app.normalize.tag_stoplist import is_junk_tag from app.normalize.text import slugify _ALTKEY_RE = re.compile(r"[^a-z0-9]") @@ -83,6 +84,10 @@ def resolve_tag(session: Session, *, norm: NormalizedTag) -> Tag | None: # the whole ingest batch. if len(slug) > 120: return None + # Tagi czysto marketingowe ("porn", "hot", "premium") odrzucamy na wejsciu, zeby + # nie wracaly przy kazdym re-scrape. Patrz app/normalize/tag_stoplist.py. + if is_junk_tag(slug): + return None slug = _canonical_dup2_slug(session, slug) tag = session.execute(select(Tag).where(Tag.slug == slug)).scalar_one_or_none() if tag is not None: