diff --git a/app/connectors/direct_scrapers/siska.py b/app/connectors/direct_scrapers/siska.py index 9c06c04..1395642 100644 --- a/app/connectors/direct_scrapers/siska.py +++ b/app/connectors/direct_scrapers/siska.py @@ -45,14 +45,16 @@ _BASE = "https://siska.tv" _HOST_RE = re.compile(r"^https://(?:www\.)?siska\.(?:tv|video)/", re.IGNORECASE) # Kafelek: . Reszta pól w oknie po tym matchu. +# Strona nie escapuje apostrofu w atrybutach (title='Brenna's Mouths'), wiec wartosc +# konczy sie na apostrofie, po ktorym idzie nastepny atrybut, a nie na pierwszym. _A_RE = re.compile( - r"[^']*)'\s+" + r"[^<>]*?)'\s+" r"href='(?Phttps://(?:www\.)?siska\.(?:tv|video)/video\.php\?videoID=\d+)'", re.IGNORECASE, ) _DUR_RE = re.compile(r"th_video_duration'>\s*([\d]{1,2}(?:\s*:\s*[\d]{2}){1,2})\s*<") _THUMB_RE = re.compile(r"data-src='([^']+\.(?:jpg|jpeg|webp|png))'", re.IGNORECASE) -_ALT_RE = re.compile(r"alt='([^']*)'") +_ALT_RE = re.compile(r"alt='([^<>]*?)'(?=\s+[\w-]+=|\s*/?>)") _CAT_RE = re.compile(r"/category/([^/]+)/", re.IGNORECASE) @@ -122,21 +124,22 @@ class SiskaScraper(BaseBrowseScraper): thumbnail_url = _canonical(tm.group(1)) if tm else None # alt='Performer - Tytuł - Studio' → performer (pierwszy), studio (ostatni). + # Kilka osob stoi w pierwszym czlonie po przecinku ("A, B - Tytul"). performers: list[RawPerformer] = [] studio: RawStudio | None = None am = _ALT_RE.search(window) if am and " - " in am.group(1): parts = [p.strip() for p in am.group(1).split(" - ") if p.strip()] if len(parts) >= 2: - pname = parts[0] sname = parts[-1] - if pname: - performers.append( - RawPerformer( - external_id=f"{self.sitetag}:performer:{_slugify(pname)}", - name=pname, + for pname in (n.strip() for n in parts[0].split(",")): + if pname: + performers.append( + RawPerformer( + external_id=f"{self.sitetag}:performer:{_slugify(pname)}", + name=pname, + ) ) - ) if sname and len(parts) >= 3: studio = RawStudio( external_id=f"{self.sitetag}:studio:{_slugify(sname)}", diff --git a/tests/test_siska_listing.py b/tests/test_siska_listing.py new file mode 100644 index 0000000..80d4a7c --- /dev/null +++ b/tests/test_siska_listing.py @@ -0,0 +1,41 @@ +from app.connectors.direct_scrapers import siska +from app.connectors.direct_scrapers.siska import SiskaScraper + +# Dwa kafelki jak na siska.tv 2026-09-27; pierwszy z nieescapowanym apostrofem. +_LISTING = """ +
  • +
  • +""" + + +class _Res: + text = _LISTING + + +def _crawl(monkeypatch): + monkeypatch.setattr(siska, "browser_get", lambda url, timeout=None: _Res()) + monkeypatch.setattr(siska, "compute_thumbnail_phash", lambda *a, **k: None) + return SiskaScraper().crawl_page(1) + + +def test_apostrophe_in_title_keeps_tile(monkeypatch): + scenes = _crawl(monkeypatch) + assert [s.url for s in scenes] == [ + "https://siska.tv/video.php?videoID=226988", + "https://siska.tv/video.php?videoID=226987", + ] + assert scenes[0].title == "Filling Chanel and Brenna's Mouths" + assert scenes[0].duration_sec == 36 * 60 + 58 + + +def test_comma_separated_performers_are_split(monkeypatch): + first, second = _crawl(monkeypatch) + assert [p.name for p in first.performers] == ["Chanel Camryn", "Brenna McKenna"] + # dwa czlony alt = osoby + tytul, studia brak + assert first.studio is None + assert [p.name for p in second.performers] == ["Jane Doe"] + assert second.studio.name == "Some Studio"