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 <noreply@anthropic.com>
This commit is contained in:
goon-foss 2026-08-14 12:00:45 +02:00
parent a1f604a7a4
commit 38a2724963
2 changed files with 79 additions and 0 deletions

View file

@ -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

View file

@ -10,6 +10,7 @@ from sqlalchemy.orm import Session
from app.models.tag import Tag from app.models.tag import Tag
from app.normalize.scenes import NormalizedTag from app.normalize.scenes import NormalizedTag
from app.normalize.tag_stoplist import is_junk_tag
from app.normalize.text import slugify from app.normalize.text import slugify
_ALTKEY_RE = re.compile(r"[^a-z0-9]") _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. # the whole ingest batch.
if len(slug) > 120: if len(slug) > 120:
return None 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) slug = _canonical_dup2_slug(session, slug)
tag = session.execute(select(Tag).where(Tag.slug == slug)).scalar_one_or_none() tag = session.execute(select(Tag).where(Tag.slug == slug)).scalar_one_or_none()
if tag is not None: if tag is not None: