From 9225ae95dea84b3a5c949d05fc072548679980f1 Mon Sep 17 00:00:00 2001 From: goon-foss Date: Thu, 24 Sep 2026 13:03:11 +0200 Subject: [PATCH] fix(scrapers): krotka nazwa wykonawcy nie przypina go do wszystkich wynikow Bramka nazwy w slugu zwracala True, gdy zaden czlon nazwy nie mial 3 znakow ("Wa A", "Al B", "T P"), a wolajacy pomijali ja przy pustych tokenach. Performer-driven dopinal wiec takiego wykonawce do kazdego wyniku wyszukiwarki tuba: 108 wykonawcow, 10,5 tys. blednych przypisan w 7,9 tys. scen. Teraz takie nazwy nic nie dopasowuja. Na produkcji bledne przypisania usuniete (kopia w scene_performers_removed_20260924). Co-Authored-By: Claude Opus 5.5 --- app/connectors/direct_scrapers/_search_base.py | 12 ++++++------ app/connectors/direct_scrapers/hqporner.py | 5 ++--- tests/test_search_slug_gate.py | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 tests/test_search_slug_gate.py diff --git a/app/connectors/direct_scrapers/_search_base.py b/app/connectors/direct_scrapers/_search_base.py index 06403f8..182a546 100644 --- a/app/connectors/direct_scrapers/_search_base.py +++ b/app/connectors/direct_scrapers/_search_base.py @@ -144,7 +144,11 @@ class BaseSearchScraper(BaseDirectTubeScraper): if len(tok) >= BaseSearchScraper._query_token_min_len ] if not toks: - return True + # Nazwa z samych krotkich czlonow ("Wa A", "Al B", "T P", "L A S") nie ma czego + # szukac w slugu. Kiedys zwracalismy tu True, wiec performer-driven doklejal + # takiego wykonawce do KAZDEGO wyniku wyszukiwarki tuba: "Wa A" 498 scen, + # "Al B" 485, "T P" 344 (zgloszenie 0982b000, 2026-09-24). Lepiej nic. + return False phrase = r"[^a-z0-9]*".join(toks) # Dozwolone końcowe „s": slug gubi apostrof, więc dzierżawcze „TiffaniTime's" # zapisuje jako „tiffanitimes". Nie luzuje to bramki, bo przed tym „s" i tak @@ -173,10 +177,6 @@ class BaseSearchScraper(BaseDirectTubeScraper): log.debug("%s search %s status=%d", self.sitetag, url, r.status_code) return - query_tokens = { - tok for tok in query.lower().split() if len(tok) >= self._query_token_min_len - } - seen: set[str] = set() try: thumb_map = self._thumbnail_map(r.text) @@ -216,7 +216,7 @@ class BaseSearchScraper(BaseDirectTubeScraper): # To ma znaczenie, bo `all_performers` niżej dokleja szukanego performera # BEZWARUNKOWO do każdej sceny, która tu przejdzie. Ten warunek jest jedyną # bramką między wyszukiwarką tuba (dopasowuje rozmyto) a obsadą w bazie. - if query_tokens and not self._slug_matches_query(slug_lower, query): + if not self._slug_matches_query(slug_lower, query): continue title = self._title_from_slug(slug) diff --git a/app/connectors/direct_scrapers/hqporner.py b/app/connectors/direct_scrapers/hqporner.py index e73f816..fe0fb5f 100644 --- a/app/connectors/direct_scrapers/hqporner.py +++ b/app/connectors/direct_scrapers/hqporner.py @@ -55,8 +55,7 @@ class HQPornerScraper(BaseDirectTubeScraper): # token → sceny z setkami błędnych aktorek (do 503; hqporner = 5659/5897 takich scen, # bug-report 2026-06-07). `all` wymaga pełnego dopasowania nazwy → precyzja. # Pojedyncze nazwy ("Belladonna") nadal działają (jeden token musi być). - query_tokens = {tok for tok in query.lower().split() if len(tok) >= 3} - # Człon <3 znaki ("Lady Vi", "Mia Li", "Ai Uehara") wypada z `query_tokens`, więc + # Człon <3 znaki ("Lady Vi", "Mia Li", "Ai Uehara") wypada z tokenów bramki, więc # zostaje sam pospolity człon i `all` degeneruje się do „slug zawiera 'lady'", # czyli KAŻDA scena z tym słowem (audit 2026-07-28: Lady Vi miała 116 przypisań # z tube, z czego 115 tylko przez „lady", realnie o niej 1). Gdy nazwa ma taki @@ -82,7 +81,7 @@ class HQPornerScraper(BaseDirectTubeScraper): # `all(tok in slug)` przepuszczał „tiffany" w „s-tiffany-love" i „time" # w „first-time" — zgłoszenie 2026-08-13, strona Tiffani Time). slug_lower = slug_part.lower() - if query_tokens and not BaseSearchScraper._slug_matches_query(slug_lower, query): + if not BaseSearchScraper._slug_matches_query(slug_lower, query): continue if _needs_compact and _compact not in re.sub(r"[^a-z0-9]", "", slug_lower): continue diff --git a/tests/test_search_slug_gate.py b/tests/test_search_slug_gate.py new file mode 100644 index 0000000..a31b1fb --- /dev/null +++ b/tests/test_search_slug_gate.py @@ -0,0 +1,18 @@ +from app.connectors.direct_scrapers._search_base import BaseSearchScraper + +gate = BaseSearchScraper._slug_matches_query + + +def test_short_only_names_never_match(): + # Kiedys True dla kazdego slugu: "Wa A" trafial do 498 scen, "Al B" do 485. + for name in ("Wa A", "Al B", "T P", "Ms P", "L A S", "Cl O"): + assert not gate("tidy-up", name) + assert not gate("wa-a-hot-scene", name) + + +def test_phrase_gate_unchanged_for_normal_names(): + assert gate("tiffani-time-first-scene", "Tiffani Time") + assert not gate("first-time-with-tiffani", "Tiffani Time") + assert gate("violet_myers_prodigious", "Violet Myers") + # czlon < 3 znakow pomijany, reszta frazy dalej musi pasowac + assert gate("mia-li-in-the-shower", "Mia Li")