From 38a2724963c0850978e4a77ce65400900b739caa Mon Sep 17 00:00:00 2001 From: goon-foss Date: Fri, 14 Aug 2026 12:00:45 +0200 Subject: [PATCH] feat(tags): odrzucaj tagi marketingowe zamiast opisujacych tresc Zgloszenie 778cd5be: "cos za duzo tych tagow, one sa faktycznie na stronie czy to over attribution?". Sprawdzone u zrodla: tytul posta na sxyprn ma dokladnie te 28 hashtagow, wiec to NIE nasza over-atrybucja, tylko uploader wklejajacy ten sam blok do kazdego wideo (stad #France i #french przy amerykanskiej scenie). Statystycznie tego nie da sie odsiac: blok jest inny u kazdego uploadera, a najczestszy tag na sxyprn (Hardcore) ma 47% udzialu, wiec zaden prog nie oddziela spamu od prawdy. Da sie za to wyciac slowa, ktore nigdy nie opisuja tresci. Tylko to robi ta zmiana. Filtr wpiety w resolve_tag, czyli jedno miejsce, przez ktore ida wszystkie tagi z kazdego zrodla, wiec nie wroca przy re-scrape. Retroaktywnie skasowane 137 861 przypisan scen i 247 filmow, 29 tagow. Sprawdzone przed kasowaniem: tylko 270 scen zostaje bez tagow i ZERO userow ma ktorykolwiek z nich na liscie ukrytych. Srednia liczba tagow na scene 7,7 -> 7,3. VACUUM ANALYZE odpalony od razu. Swiadomie zostawione: onlyfans (realny typ tresci, 72 tys. przypisan) oraz 4k/hd/720p (niosa informacje, choc apka ma juz wiarygodny filtr jakosci ze zrodel odtwarzania, wiec to decyzja produktowa, nie sprzatanie smieci). Co-Authored-By: Claude Opus 5 --- app/normalize/tag_stoplist.py | 74 +++++++++++++++++++++++++++++++++++ app/resolve/tag_resolver.py | 5 +++ 2 files changed, 79 insertions(+) create mode 100644 app/normalize/tag_stoplist.py 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: